From d9d7188ad7b22e8991a9ef685840ac0e88566b39 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 7 Mar 2020 14:22:56 +0100 Subject: Use vector for PixelBuffer memory allocation. Use optimized render routines in some more painter algorithms. Fix capitalization of Canvas::getPixelBuffer method. --- plugingui/canvas.h | 4 +-- plugingui/layout.cc | 26 +++++++++++------- plugingui/painter.cc | 35 ++++++++++++------------ plugingui/pixelbuffer.cc | 69 ++++++++++++++++++++++++++---------------------- plugingui/pixelbuffer.h | 4 ++- plugingui/widget.cc | 2 +- plugingui/widget.h | 2 +- 7 files changed, 77 insertions(+), 65 deletions(-) (limited to 'plugingui') diff --git a/plugingui/canvas.h b/plugingui/canvas.h index 2326f0e..d6e8f99 100644 --- a/plugingui/canvas.h +++ b/plugingui/canvas.h @@ -31,14 +31,14 @@ namespace GUI { -//! Abstract class that can be used by the Paiter to draw on. +//! Abstract class that can be used by the Painter to draw on. class Canvas { public: virtual ~Canvas() = default; //! @returns a reference to the pixel buffer. - virtual PixelBufferAlpha& GetPixelBuffer() = 0; + virtual PixelBufferAlpha& getPixelBuffer() = 0; }; } // GUI:: diff --git a/plugingui/layout.cc b/plugingui/layout.cc index f38bc20..61e4f77 100644 --- a/plugingui/layout.cc +++ b/plugingui/layout.cc @@ -33,7 +33,8 @@ namespace GUI { -LayoutItem::LayoutItem() : parent(nullptr) +LayoutItem::LayoutItem() + : parent(nullptr) { } @@ -170,7 +171,8 @@ void VBoxLayout::setHAlignment(HAlignment alignment) // HBoxLayout::HBoxLayout(LayoutItem* parent) - : BoxLayout(parent), align(VAlignment::center) + : BoxLayout(parent) + , align(VAlignment::center) { } @@ -242,10 +244,10 @@ void HBoxLayout::setVAlignment(VAlignment alignment) // GridLayout::GridLayout(LayoutItem* parent, std::size_t number_of_columns, - std::size_t number_of_rows) - : BoxLayout(parent) - , number_of_columns(number_of_columns) - , number_of_rows(number_of_rows) + std::size_t number_of_rows) + : BoxLayout(parent) + , number_of_columns(number_of_columns) + , number_of_rows(number_of_rows) { } @@ -297,9 +299,11 @@ int GridLayout::lastUsedRow(int column) const { int last_row = -1; - for (auto const& grid_range : grid_ranges) { + for (auto const& grid_range : grid_ranges) + { auto const& range = grid_range.second; - if (column >= range.column_begin && column < range.column_end) { + if (column >= range.column_begin && column < range.column_end) + { last_row = std::max(last_row, range.row_end - 1); } } @@ -311,9 +315,11 @@ int GridLayout::lastUsedColumn(int row) const { int last_column = -1; - for (auto const& grid_range : grid_ranges) { + for (auto const& grid_range : grid_ranges) + { auto const& range = grid_range.second; - if (row >= range.row_begin && row < range.row_end) { + if (row >= range.row_begin && row < range.row_end) + { last_column = std::max(last_column, range.column_end - 1); } } diff --git a/plugingui/painter.cc b/plugingui/painter.cc index 7f8acba..d3f28ff 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -39,7 +39,7 @@ namespace GUI { Painter::Painter(Canvas& canvas) - : pixbuf(canvas.GetPixelBuffer()) + : pixbuf(canvas.getPixelBuffer()) { colour = Colour(0.0f, 0.0f, 0.0f, 0.5f); } @@ -111,11 +111,11 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) if(steep) { - plot(pixbuf, colour, ypxl1, xpxl1, 1); + pixbuf.addPixel(ypxl1, xpxl1, colour); } else { - plot(pixbuf, colour, xpxl1, ypxl1, 1); + pixbuf.addPixel(xpxl1, ypxl1, colour); } double intery = yend + gradient; // first y-intersection for the main loop @@ -129,11 +129,11 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) if(steep) { - plot(pixbuf, colour, ypxl2, xpxl2, 1); + pixbuf.addPixel(ypxl2, xpxl2, colour); } else { - plot(pixbuf, colour, xpxl2, ypxl2, 1); + pixbuf.addPixel(xpxl2, ypxl2, colour); } // main loop @@ -205,22 +205,21 @@ void Painter::drawText(int x0, int y0, const Font& font, { for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) { - for(int x = -1 * std::min(0, x0); x < renderWidth; ++x) - { - assert(x >= 0); - assert(y >= 0); - assert(x < (int)textbuf->width); - assert(y < (int)textbuf->height); + int x = -1 * std::min(0, x0); - auto c = textbuf->pixel(x, y); + assert(x >= 0); + assert(y >= 0); + assert(x < (int)textbuf->width); + assert(y < (int)textbuf->height); - assert(x + x0 >= 0); - assert(y + y0 >= 0); - assert(x + x0 < (int)pixbuf.width); - assert(y + y0 < (int)pixbuf.height); + auto c = textbuf->getLine(x, y); - pixbuf.addPixel(x + x0, y + y0, c); - } + assert(x + x0 >= 0); + assert(y + y0 >= 0); + assert(x + x0 < (int)pixbuf.width); + assert(y + y0 < (int)pixbuf.height); + + pixbuf.blendLine(x + x0, y + y0, c, renderWidth - x); } } else diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index 918298b..c73e663 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -35,20 +35,18 @@ namespace GUI { PixelBuffer::PixelBuffer(std::size_t width, std::size_t height) - : buf(nullptr) { realloc(width, height); } PixelBuffer::~PixelBuffer() { - free(buf); } void PixelBuffer::realloc(std::size_t width, std::size_t height) { - free(buf); - buf = (std::uint8_t *)calloc(width * height, 3); + buf_data.resize(width * height * 3); + buf = buf_data.data(); this->width = width; this->height = height; } @@ -61,7 +59,7 @@ void PixelBuffer::blendLine(std::size_t x, std::size_t y, { if(line[3] == 0xff) { - memcpy(target, line, 3); + std::memcpy(target, line, 3); } else { @@ -219,53 +217,50 @@ Rect PixelBuffer::updateBuffer(std::vector& pixel_buffers) return dirty_rect; } - PixelBufferAlpha::PixelBufferAlpha(std::size_t width, std::size_t height) - : managed(true) - , buf(nullptr) - , x(0) - , y(0) { realloc(width, height); } PixelBufferAlpha::~PixelBufferAlpha() { - if(managed) - { - free(buf); - } } void PixelBufferAlpha::realloc(std::size_t width, std::size_t height) { - free(buf); - buf = (std::uint8_t *)calloc(width * height, 4); + buf_data.resize(width * height * 4); + buf = buf_data.data(); this->width = width; this->height = height; + clear(); } void PixelBufferAlpha::clear() { - memset(buf, 0, width * height * 4); + std::memset(buf, 0, width * height * 4); } -#undef PX -#define PX(k) ((x + y * width) * 4 + k) void PixelBufferAlpha::setPixel(std::size_t x, std::size_t y, const Colour& c) { - std::uint8_t* pixel = &buf[PX(0)]; - memcpy(pixel, c.data(), 4); + std::uint8_t* pixel = buf + (x + y * width) * 4; + std::memcpy(pixel, c.data(), 4); } void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y, const std::uint8_t* line, std::size_t len) { - auto offset = &buf[PX(0)]; - if(x + y * width + len > width * height) + if(x >= width || y >= height) { - return; // out of bounds + return; } + + if(x + len > width) + { + len = width - x; + } + + auto offset = buf + (x + y * width) * 4; + std::memcpy(offset, line, len * 4); } @@ -276,13 +271,18 @@ void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y, void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, const std::uint8_t* line, std::size_t len) { - if(x + y * width + len > width * height) + if(x >= width || y >= height) { - return; // out of bounds + return; + } + + if(x + len > width) + { + len = width - x; } int a, b; - std::uint8_t* target = &buf[PX(0)]; + std::uint8_t* target = buf + (x + y * width) * 4; while(len) { if(line[3] == 0xff) @@ -293,7 +293,7 @@ void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, end += 4; } auto chunk_len = end - line; - memcpy(target, line, chunk_len); + std::memcpy(target, line, chunk_len); line += chunk_len; target += chunk_len; len -= chunk_len / 4; @@ -322,6 +322,11 @@ void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) { + if(x >= width || y >= height) + { + return; // out of bounds + } + const std::uint8_t* colour = c.data(); if(colour[3] == 0) @@ -330,11 +335,11 @@ void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) } int a, b; - std::uint8_t* target = &buf[PX(0)]; + std::uint8_t* target = buf + (x + y * width) * 4; if(colour[3] == 0xff) { - memcpy(target, colour, 4); + std::memcpy(target, colour, 4); } else { @@ -351,13 +356,13 @@ void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) const Colour& PixelBufferAlpha::pixel(std::size_t x, std::size_t y) const { static Colour c; - memcpy(c.data(), &buf[PX(0)], 4); + std::memcpy(c.data(), buf + (x + y * width) * 4, 4); return c; } const std::uint8_t* PixelBufferAlpha::getLine(std::size_t x, std::size_t y) const { - return &buf[PX(0)]; + return buf + (x + y * width) * 4; } } // GUI:: diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h index 5078ed6..5c11d14 100644 --- a/plugingui/pixelbuffer.h +++ b/plugingui/pixelbuffer.h @@ -29,6 +29,7 @@ #include "colour.h" #include +#include #include #include "guievent.h" @@ -49,6 +50,7 @@ public: Rect updateBuffer(std::vector& pixel_buffers); + std::vector buf_data; std::uint8_t* buf{nullptr}; std::size_t width{0}; std::size_t height{0}; @@ -78,7 +80,7 @@ public: const std::uint8_t* getLine(std::size_t x, std::size_t y) const; - bool managed{false}; + std::vector buf_data; std::uint8_t* buf{nullptr}; std::size_t width{0}; std::size_t height{0}; diff --git a/plugingui/widget.cc b/plugingui/widget.cc index 5a76af9..da6b1e2 100644 --- a/plugingui/widget.cc +++ b/plugingui/widget.cc @@ -201,7 +201,7 @@ Point Widget::position() const return { _x, _y }; } -PixelBufferAlpha& Widget::GetPixelBuffer() +PixelBufferAlpha& Widget::getPixelBuffer() { return pixbuf; } diff --git a/plugingui/widget.h b/plugingui/widget.h index fbf3f5b..b9436b7 100644 --- a/plugingui/widget.h +++ b/plugingui/widget.h @@ -81,7 +81,7 @@ public: Point position() const; // From Canvas - PixelBufferAlpha& GetPixelBuffer() override; + PixelBufferAlpha& getPixelBuffer() override; virtual bool isFocusable() { return false; } virtual bool catchMouse() { return false; } -- cgit v1.2.3