diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2015-11-09 21:26:57 +0100 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2015-11-09 21:26:57 +0100 | 
| commit | c18090169d6bb49e877956701e77e8af338ed675 (patch) | |
| tree | 7a18b46d809fc839acc56c4b0fd2e1938614513c /plugingui | |
| parent | 74ab9aea168bb5706e9c36aa6252f366926f5b41 (diff) | |
Refactor PixelBuffer, and remove unnecessary calls to setPixel and addPixel.
Diffstat (limited to 'plugingui')
| -rw-r--r-- | plugingui/painter.cc | 95 | ||||
| -rw-r--r-- | plugingui/painter.h | 28 | ||||
| -rw-r--r-- | plugingui/pixelbuffer.cc | 199 | ||||
| -rw-r--r-- | plugingui/pixelbuffer.h | 94 | ||||
| -rw-r--r-- | plugingui/window.cc | 16 | 
5 files changed, 235 insertions, 197 deletions
| 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 <stdio.h> +#include <cassert> -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 <stdlib.h> +#pragma once  #include "colour.h" +#include <stdlib.h> +  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<PixelBufferAlpha *>::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); | 
