diff options
Diffstat (limited to 'plugingui')
| -rw-r--r-- | plugingui/nativewindow_x11.cc | 1 | ||||
| -rw-r--r-- | plugingui/painter.cc | 14 | ||||
| -rw-r--r-- | plugingui/pixelbuffer.cc | 78 | ||||
| -rw-r--r-- | plugingui/texture.cc | 2 | 
4 files changed, 58 insertions, 37 deletions
| diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc index de215c2..33dde7b 100644 --- a/plugingui/nativewindow_x11.cc +++ b/plugingui/nativewindow_x11.cc @@ -680,7 +680,6 @@ void NativeWindowX11::updateImageFromBuffer(std::size_t x1, std::size_t y1,  	if(depth >= 24) // RGB 888 format  	{  		std::uint32_t* shm_addr = (std::uint32_t*)shm_info.shmaddr; -  		for(std::size_t y = y1; y < y2; ++y)  		{  			for(std::size_t x = x1; x < x2; ++x) diff --git a/plugingui/painter.cc b/plugingui/painter.cc index 761fe9b..7f8acba 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -65,7 +65,11 @@ static void plot(PixelBufferAlpha& pixbuf, const Colour& colour,  	}  	// plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) -	Colour col(colour.red(), colour.green(), colour.blue(), (std::uint8_t)(colour.alpha() * c)); +	Colour col(colour); +	if(c != 1) +	{ +		col.data()[3] *= c; +	}  	pixbuf.addPixel(x, y, col);  } @@ -369,7 +373,7 @@ void Painter::drawImage(int x0, int y0, const Drawable& image)  	if(image.hasAlpha())  	{ -		if(true || !image.line(0)) +		if(!image.line(0))  		{  			for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y)  			{ @@ -398,7 +402,8 @@ void Painter::drawImage(int x0, int y0, const Drawable& image)  			std::size_t x = -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), image.width()); +				pixbuf.blendLine(x + x0, y + y0, image.line(y), +				                 std::min((int)image.width(), fw - (int)x));  			}  		}  	} @@ -407,7 +412,8 @@ void Painter::drawImage(int x0, int y0, const Drawable& image)  		std::size_t x = -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), image.width()); +			pixbuf.writeLine(x + x0, y + y0, image.line(y), +			                 std::min((int)image.width(), fw - (int)x));  		}  	}  } diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index fd02703..918298b 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -269,7 +269,9 @@ void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y,  	std::memcpy(offset, line, len * 4);  } +  // SIMD: https://github.com/WojciechMula/toys/blob/master/blend_32bpp/blend_32bpp.c +// Alpha blending: http://en.wikipedia.org/wiki/Alpha_compositing  void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y,                                   const std::uint8_t* line, std::size_t len) @@ -279,56 +281,70 @@ void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y,  		return; // out of bounds  	} +	int a, b;  	std::uint8_t* target = &buf[PX(0)]; -	for(std::size_t x = 0; x < len; ++x) +	while(len)  	{ -		unsigned int a = line[3]; -		unsigned int b = 255 - a; +		if(line[3] == 0xff) +		{ +			const std::uint8_t* end = line; +			while(end[3] == 0xff && end < line + len * 4) +			{ +				end += 4; +			} +			auto chunk_len = end - line; +			memcpy(target, line, chunk_len); +			line += chunk_len; +			target += chunk_len; +			len -= chunk_len / 4; +			continue; +		} +		else if(line[3] == 0) +		{ +			// Do nothing +		} +		else +		{ +			a = line[3]; +			b = target[3] * (255 - a) / 255; + +			target[0] = (line[0] * a + target[0] * b) / (a + b); +			target[1] = (line[1] * a + target[1] * b) / (a + b); +			target[2] = (line[2] * a + target[2] * b) / (a + b); +			target[3] = (int)target[3] + line[3] * (255 - target[3]) / 255; +		} -		target[0] = (std::uint8_t)((line[0] * a + target[0] * b) / 255); -		target[1] = (std::uint8_t)((line[1] * a + target[1] * b) / 255); -		target[2] = (std::uint8_t)((line[2] * a + target[2] * b) / 255); -		target[3] = a * b / 255;  		line += 4;  		target += 4; +		--len;  	}  } - -// http://en.wikipedia.org/wiki/Alpha_compositing -static inline void getAlpha(std::uint8_t _a, std::uint8_t _b, -                            float &a, float &b) -{ -	a = _a / 255.0; -	b = _b / 255.0; -	b *= (1 - a); -} -  void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c)  { -	if(c.alpha() == 0) +	const std::uint8_t* colour = c.data(); + +	if(colour[3] == 0)  	{  		return;  	} -	std::uint8_t* pixel = &buf[PX(0)]; +	int a, b; +	std::uint8_t* target = &buf[PX(0)]; -	if(c.alpha() < 255) +	if(colour[3] == 0xff)  	{ -		float a, b; -		getAlpha(c.alpha(), buf[PX(3)], a, b); - -		*pixel = (std::uint8_t)((c.red()   * a + *pixel * b) / (a + b)); -		++pixel; -		*pixel = (std::uint8_t)((c.green() * a + *pixel * b) / (a + b)); -		++pixel; -		*pixel = (std::uint8_t)((c.blue()  * a + *pixel * b) / (a + b)); -		++pixel; -		*pixel = (a + b) * 255; +		memcpy(target, colour, 4);  	}  	else  	{ -		memcpy(pixel, c.data(), 4); +		a = colour[3]; +		b = target[3] * (255 - a) / 255; + +		target[0] = (colour[0] * a + target[0] * b) / (a + b); +		target[1] = (colour[1] * a + target[1] * b) / (a + b); +		target[2] = (colour[2] * a + target[2] * b) / (a + b); +		target[3] = (int)target[3] + colour[3] * (255 - target[3]) / 255;  	}  } diff --git a/plugingui/texture.cc b/plugingui/texture.cc index 39d417d..a5908cb 100644 --- a/plugingui/texture.cc +++ b/plugingui/texture.cc @@ -61,7 +61,7 @@ const Colour& Texture::getPixel(size_t x, size_t y) const  const std::uint8_t* Texture::line(std::size_t y) const  { -	return image.line(y + _y); +	return image.line(y + _y) + _x * 4;  }  bool Texture::hasAlpha() const | 
