From c18090169d6bb49e877956701e77e8af338ed675 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Mon, 9 Nov 2015 21:26:57 +0100 Subject: Refactor PixelBuffer, and remove unnecessary calls to setPixel and addPixel. --- plugingui/painter.cc | 95 ++++++++++++++++------ plugingui/painter.h | 28 +++---- plugingui/pixelbuffer.cc | 199 ++++++++++++++++++++++------------------------- plugingui/pixelbuffer.h | 94 +++++++++++----------- plugingui/window.cc | 16 +++- 5 files changed, 235 insertions(+), 197 deletions(-) (limited to 'plugingui') diff --git a/plugingui/painter.cc b/plugingui/painter.cc index c1ab811..38f960d 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -59,8 +59,14 @@ void Painter::setColour(const Colour& colour) this->colour = colour; } -void Painter::plot(int x, int y, double c) +static void plot(PixelBufferAlpha* pixbuf, const Colour& colour, + int x, int y, double c) { + if((x >= (int)pixbuf->width) || (y >= (int)pixbuf->height)) + { + return; + } + // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) pixbuf->addPixel(x, y, (unsigned char)(colour.red * 255.0), @@ -70,12 +76,12 @@ void Painter::plot(int x, int y, double c) } -double Painter::fpart(double x) +static inline double fpart(double x) { return x - std::floor(x);// fractional part of x } -double Painter::rfpart(double x) +static inline double rfpart(double x) { return 1 - fpart(x); // reverse fractional part of x } @@ -108,11 +114,11 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) if(steep) { - plot(ypxl1, xpxl1, 1); + plot(pixbuf, colour, ypxl1, xpxl1, 1); } else { - plot(xpxl1, ypxl1, 1); + plot(pixbuf, colour, xpxl1, ypxl1, 1); } double intery = yend + gradient; // first y-intersection for the main loop @@ -126,11 +132,11 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) if(steep) { - plot(ypxl2, xpxl2, 1); + plot(pixbuf, colour, ypxl2, xpxl2, 1); } else { - plot(xpxl2, ypxl2, 1); + plot(pixbuf, colour, xpxl2, ypxl2, 1); } // main loop @@ -138,13 +144,13 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) { if(steep) { - plot(std::floor(intery) , x, rfpart(intery)); - plot(std::floor(intery)+1, x, fpart(intery)); + plot(pixbuf, colour, std::floor(intery) , x, rfpart(intery)); + plot(pixbuf, colour, std::floor(intery)+1, x, fpart(intery)); } else { - plot(x, std::floor(intery), rfpart(intery)); - plot(x, std::floor(intery)+1, fpart(intery)); + plot(pixbuf, colour, x, std::floor(intery), rfpart(intery)); + plot(pixbuf, colour, x, std::floor(intery)+1, fpart(intery)); } intery += gradient; } @@ -182,27 +188,48 @@ void Painter::drawText(int x0, int y0, const Font &font, { PixelBufferAlpha* textbuf = font.render(text); + y0 -= textbuf->height; // The y0 offset (baseline) is the bottom of the text. + + // If the text offset is outside the buffer; skip it. + if((x0 > (int)pixbuf->width) || (y0 > (int)pixbuf->height)) + { + return; + } + + // Make sure we don't try to draw outside the pixbuf. + int renderWidth = textbuf->width; + if(renderWidth > (int)(pixbuf->width - x0)) + { + renderWidth = pixbuf->width - x0; + } + + int renderHeight = textbuf->height; + if(renderHeight > ((int)pixbuf->height - y0)) + { + renderHeight = ((int)pixbuf->height - y0); + } + if(nocolour) { - for(size_t x = 0; x < textbuf->width; ++x) + for(int y = 0; y < renderHeight; ++y) { - for(size_t y = 0; y < textbuf->height; ++y) + for(int x = 0; x < renderWidth; ++x) { unsigned char r, g, b, a; textbuf->pixel(x, y, &r, &g, &b, &a); - pixbuf->addPixel(x + x0, y + y0 - textbuf->height, r, g, b, a); + pixbuf->addPixel(x + x0, y + y0, r, g, b, a); } } } else { - for(size_t x = 0; x < textbuf->width; ++x) + for(int y = 0; y < renderHeight; ++y) { - for(size_t y = 0; y < textbuf->height; ++y) + for(int x = 0; x < renderWidth; ++x) { unsigned char r,g,b,a; textbuf->pixel(x, y, &r, &g, &b, &a); - pixbuf->addPixel(x + x0, y + y0 - textbuf->height, + pixbuf->addPixel(x + x0, y + y0, colour.red * 255, colour.green * 255, colour.blue * 255, @@ -322,6 +349,17 @@ void Painter::drawImage(int x0, int y0, const Image& image) size_t fw = image.width(); size_t fh = image.height(); + // Make sure we don't try to draw outside the pixbuf. + if(fw > (pixbuf->width - x0)) + { + fw = (pixbuf->width - x0); + } + + if(fh > (pixbuf->height - y0)) + { + fh = (pixbuf->height - y0); + } + for(size_t y = 0; y < fh; ++y) { for(size_t x = 0; x < fw; ++x) @@ -333,9 +371,9 @@ void Painter::drawImage(int x0, int y0, const Image& image) } void Painter::drawImageStretched(int x0, int y0, const Image& image, - int w, int h) + int width, int height) { - if((w < 1) || (h < 1)) + if((width < 1) || (height < 1)) { return; } @@ -343,12 +381,23 @@ void Painter::drawImageStretched(int x0, int y0, const Image& image, float fw = image.width(); float fh = image.height(); - for(int y = 0; y < h; ++y) + // Make sure we don't try to draw outside the pixbuf. + if(width > (int)(pixbuf->width - x0)) + { + width = pixbuf->width - x0; + } + + if(height > (int)(pixbuf->height - y0)) + { + height = pixbuf->height - y0; + } + + for(int y = 0; y < height; ++y) { - for(int x = 0; x < w; ++x) + for(int x = 0; x < width; ++x) { - int lx = ((float)x / (float)w) * fw; - int ly = ((float)y / (float)h) * fh; + int lx = ((float)x / (float)width) * fw; + int ly = ((float)y / (float)height) * fh; Colour c = image.getPixel(lx, ly); pixbuf->addPixel(x0 + x, y0 + y, c); } diff --git a/plugingui/painter.h b/plugingui/painter.h index 40747a7..009ebde 100644 --- a/plugingui/painter.h +++ b/plugingui/painter.h @@ -58,32 +58,28 @@ public: int width, int height); typedef struct { - Image *topLeft; - Image *top; - Image *topRight; - Image *left; - Image *right; - Image *bottomLeft; - Image *bottom; - Image *bottomRight; - Image *center; + Image* topLeft; + Image* top; + Image* topRight; + Image* left; + Image* right; + Image* bottomLeft; + Image* bottom; + Image* bottomRight; + Image* center; } Box; void drawBox(int x, int y, const Box& box, int width, int height); typedef struct { - Image *left; - Image *right; - Image *center; + Image* left; + Image* right; + Image* center; } Bar; void drawBar(int x, int y, const Bar& bar, int width, int height); void clear(); private: - void plot(int x, int y, double c); - double fpart(double x); - double rfpart(double x); - Widget& widget; PixelBufferAlpha* pixbuf; Colour colour; diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index 2a6bf6f..962091e 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -26,155 +26,140 @@ */ #include "pixelbuffer.h" -#include +#include -GUI::PixelBuffer::PixelBuffer(size_t width, size_t height) +namespace GUI { + +PixelBuffer::PixelBuffer(size_t width, size_t height) + : buf(nullptr) { - buf = NULL; - realloc(width, height); + realloc(width, height); } -GUI::PixelBuffer::~PixelBuffer() +PixelBuffer::~PixelBuffer() { - if(buf) free(buf); + free(buf); } -void GUI::PixelBuffer::realloc(size_t width, size_t height) +void PixelBuffer::realloc(size_t width, size_t height) { - if(buf) free(buf); - buf = (unsigned char *)calloc(width * height, 3); - this->width = width; - this->height = height; + free(buf); + buf = (unsigned char *)calloc(width * height, 3); + this->width = width; + this->height = height; } -#define PX(k) (x + y * width) * 3 + k -void GUI::PixelBuffer::setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha) +#define PX(k) ((x + y * width) * 3 + k) +void PixelBuffer::setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) { - if(x >= width || y >= height) return; - /* - float a,b; - getAlpha(alpha, 255, a, b); - - buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b); - buf[PX(0)] /= (a + b); - buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b); - buf[PX(1)] /= (a + b); - buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b); - buf[PX(2)] /= (a + b); - */ - unsigned int a = alpha; - unsigned int b = 255 - alpha; - - buf[PX(0)] = (unsigned char)(((int)red * a + (int)buf[PX(0)] * b) / 255); - buf[PX(1)] = (unsigned char)(((int)green * a + (int)buf[PX(1)] * b) / 255); - buf[PX(2)] = (unsigned char)(((int)blue * a + (int)buf[PX(2)] * b) / 255); + assert(x < width); + assert(y < height); + + unsigned int a = alpha; + unsigned int b = 255 - alpha; + + buf[PX(0)] = (unsigned char)(((int)red * a + (int)buf[PX(0)] * b) / 255); + buf[PX(1)] = (unsigned char)(((int)green * a + (int)buf[PX(1)] * b) / 255); + buf[PX(2)] = (unsigned char)(((int)blue * a + (int)buf[PX(2)] * b) / 255); } -static int idx = 0; -GUI::PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height) +PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height) + : buf(nullptr) + , x(0) + , y(0) { - this->idx = ::idx++; - buf = NULL; - x = y = 10; - realloc(width, height); + realloc(width, height); } -GUI::PixelBufferAlpha::~PixelBufferAlpha() +PixelBufferAlpha::~PixelBufferAlpha() { - if(buf) free(buf); + free(buf); } -void GUI::PixelBufferAlpha::realloc(size_t width, size_t height) +void PixelBufferAlpha::realloc(size_t width, size_t height) { - if(buf) free(buf); - buf = (unsigned char *)calloc(width * height, 4); - this->width = width; - this->height = height; + free(buf); + buf = (unsigned char *)calloc(width * height, 4); + this->width = width; + this->height = height; } #undef PX -#define PX(k) (x + y * width) * 4 + k -void GUI::PixelBufferAlpha::setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha) +#define PX(k) ((x + y * width) * 4 + k) +void PixelBufferAlpha::setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) { - if(x >= width || y >= height) return; + assert(x < width); + assert(y < height); - buf[PX(0)] = red; - buf[PX(1)] = green; - buf[PX(2)] = blue; - buf[PX(3)] = alpha; + buf[PX(0)] = red; + buf[PX(1)] = green; + buf[PX(2)] = blue; + buf[PX(3)] = alpha; } // http://en.wikipedia.org/wiki/Alpha_compositing -static void getAlpha(unsigned char _a, unsigned char _b, float &a, float &b) +static inline void getAlpha(unsigned char _a, unsigned char _b, + float &a, float &b) { - a = _a / 255.0; - b = _b / 255.0; - b *= (1-a); + a = _a / 255.0; + b = _b / 255.0; + b *= (1 - a); } -void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha) +void PixelBufferAlpha::addPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) { - if(x >= width || y >= height) return; + assert(x < width); + assert(y < height); - if(alpha == 0) return; + if(alpha == 0) + { + return; + } - float a,b; - getAlpha(alpha, buf[PX(3)], a, b); + float a, b; + getAlpha(alpha, buf[PX(3)], a, b); - buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b); - buf[PX(0)] /= (a + b); - buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b); - buf[PX(1)] /= (a + b); - buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b); - buf[PX(2)] /= (a + b); + buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b); + buf[PX(0)] /= (a + b); + buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b); + buf[PX(1)] /= (a + b); + buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b); + buf[PX(2)] /= (a + b); - buf[PX(3)] = (a + b) * 255; + buf[PX(3)] = (a + b) * 255; } -void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y, GUI::Colour c) +void PixelBufferAlpha::addPixel(size_t x, size_t y, Colour c) { - addPixel(x, y, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); + addPixel(x, y, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); } -void GUI::PixelBufferAlpha::pixel(size_t x, size_t y, - unsigned char *red, - unsigned char *green, - unsigned char *blue, - unsigned char *alpha) +void PixelBufferAlpha::pixel(size_t x, size_t y, + unsigned char* red, + unsigned char* green, + unsigned char* blue, + unsigned char* alpha) { - if(x >= width || y >= height) return; - *red = buf[PX(0)]; - *green = buf[PX(1)]; - *blue = buf[PX(2)]; - *alpha = buf[PX(3)]; -} - -#ifdef TEST_PIXELBUFFER -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; + assert(x < width); + assert(y < height); -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; + *red = buf[PX(0)]; + *green = buf[PX(1)]; + *blue = buf[PX(2)]; + *alpha = buf[PX(3)]; +} -#endif/*TEST_PIXELBUFFER*/ +} // GUI:: diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h index 2785eb1..d955c1a 100644 --- a/plugingui/pixelbuffer.h +++ b/plugingui/pixelbuffer.h @@ -24,68 +24,64 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PIXELBUFFER_H__ -#define __DRUMGIZMO_PIXELBUFFER_H__ - -#include +#pragma once #include "colour.h" +#include + namespace GUI { class PixelBuffer { public: - PixelBuffer(size_t width, size_t height); - ~PixelBuffer(); + PixelBuffer(size_t width, size_t height); + ~PixelBuffer(); - void realloc(size_t width, size_t height); + void realloc(size_t width, size_t height); - void setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha); + void setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); - unsigned char *buf; - size_t width; - size_t height; + unsigned char* buf; + size_t width; + size_t height; }; class PixelBufferAlpha { public: - PixelBufferAlpha(size_t width, size_t height); - ~PixelBufferAlpha(); - - int idx; - size_t x, y; - - void realloc(size_t width, size_t height); - - void setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha); - - void addPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha); - - void addPixel(size_t x, size_t y, Colour c); - - void pixel(size_t x, size_t y, - unsigned char *red, - unsigned char *green, - unsigned char *blue, - unsigned char *alpha); - - unsigned char *buf; - size_t width; - size_t height; -}; - + PixelBufferAlpha(size_t width, size_t height); + ~PixelBufferAlpha(); + + void realloc(size_t width, size_t height); + + void setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); + + void addPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); + + void addPixel(size_t x, size_t y, Colour c); + + void pixel(size_t x, size_t y, + unsigned char* red, + unsigned char* green, + unsigned char* blue, + unsigned char* alpha); + + unsigned char* buf; + size_t width; + size_t height; + size_t x; + size_t y; }; -#endif/*__DRUMGIZMO_PIXELBUFFER_H__*/ +} // GUI:: diff --git a/plugingui/window.cc b/plugingui/window.cc index afbcb21..a7e220e 100644 --- a/plugingui/window.cc +++ b/plugingui/window.cc @@ -178,8 +178,20 @@ void GUI::Window::updateBuffer() std::vector::iterator pli = pl.begin(); while(pli != pl.end()) { PixelBufferAlpha *pb = *pli; - for(size_t x = 0; x < pb->width; x++) { - for(size_t y = 0; y < pb->height; y++) { + size_t updateWidth = pb->width; + size_t updateHeight = pb->height; + if(updateWidth > (wpixbuf.width - pb->x)) + { + updateWidth = (wpixbuf.width - pb->x); + } + + if(updateHeight > (wpixbuf.height - pb->y)) + { + updateHeight = (wpixbuf.height - pb->y); + } + + for(size_t x = 0; x < updateWidth; x++) { + for(size_t y = 0; y < updateHeight; y++) { unsigned char r,g,b,a; pb->pixel(x,y,&r,&g,&b,&a); wpixbuf.setPixel(x + pb->x, y + pb->y, r, g, b, a); -- cgit v1.2.3