diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2016-06-19 10:13:28 +0800 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2016-11-16 11:10:27 +0100 |
commit | 40a336b4b2334ec9d892668d130959204e95ffca (patch) | |
tree | 3cdeaacd51936ef406bc96b6b616e6dc9122e5bf | |
parent | cf60e28a1295de44f21cbe4490bebbcd529fed94 (diff) |
svp: premultiply the buffer when drawing a 32-bit bitmap
Cairo uses premultiplied alpha for RGBA bitmap buffers. As our
bitmap buffer doesn't currently do this, we have to do it just
before we draw a bitmap.
Change-Id: I551ba6d589b7339b2e081452c2720b39e7278b68
-rw-r--r-- | vcl/headless/svpgdi.cxx | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index f2abf303162f..75183db0533f 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -83,6 +83,16 @@ namespace aDamageRect.intersect(getClipBox(cr)); return aDamageRect; } + + static sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a) + { + return (a > 0) ? (c * 255 + a / 2) / a : 0; + } + + static sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a) + { + return (c * a + 127) / 255; + } } bool SvpSalGraphics::blendBitmap( const SalTwoRect&, const SalBitmap& /*rBitmap*/ ) @@ -99,6 +109,28 @@ bool SvpSalGraphics::blendAlphaBitmap( const SalTwoRect&, const SalBitmap&, cons namespace { + void premultiplyBuffer(int width, int height, int stride, unsigned char* data) + { + for (int y = 0; y < height; ++y) + { + unsigned int* row = reinterpret_cast<unsigned int*>(data + y * stride); + for (int x = 0; x < width; ++x) + { + unsigned int px = row[x]; + unsigned char a = (px & 0xff000000) >> 24; + unsigned char r = (px & 0x00ff0000) >> 16; + unsigned char g = (px & 0x0000ff00) >> 8; + unsigned char b = (px & 0x000000ff); + + r = premultiply(r, a); + g = premultiply(g, a); + b = premultiply(b, a); + + row[x] = (a << 24) | (r << 16) | (g << 8) | b; + } + } + } + class SourceHelper { public: @@ -123,7 +155,25 @@ namespace source = SvpSalGraphics::createCairoSurface(aTmpBmp.GetBuffer()); } else - source = SvpSalGraphics::createCairoSurface(rSrcBmp.GetBuffer()); + { + const BitmapBuffer* pSrc = rSrcBmp.GetBuffer(); + if (pSrc->mnColorChannelBitCount == 32) + { + aTmpBmp.Create(rSrcBmp); + source = SvpSalGraphics::createCairoSurface(aTmpBmp.GetBuffer()); + cairo_surface_flush(source); + int w = cairo_image_surface_get_width(source); + int h = cairo_image_surface_get_height(source); + int stride = cairo_image_surface_get_stride(source); + unsigned char* data = cairo_image_surface_get_data(source); + premultiplyBuffer(w, h, stride, data); + cairo_surface_mark_dirty(source); + } + else + { + source = SvpSalGraphics::createCairoSurface(rSrcBmp.GetBuffer()); + } + } } ~SourceHelper() { @@ -1026,16 +1076,6 @@ void SvpSalGraphics::drawBitmap( const SalTwoRect& rTR, drawAlphaBitmap(rTR, rSourceBitmap, rTransparentBitmap); } -static sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a) -{ - return (a > 0) ? (c * 255 + a / 2) / a : 0; -} - -static sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a) -{ - return (c * a + 127) / 255; -} - void SvpSalGraphics::drawMask( const SalTwoRect& rTR, const SalBitmap& rSalBitmap, SalColor nMaskColor ) |