vcl: Add DrawAlphaTexture to directly render Cairo surface

Change-Id: I7aa824578b14999d0ef667a5bcfccd731f1d3b64
This commit is contained in:
Louis-Francis Ratté-Boulianne
2014-11-13 22:24:35 -05:00
committed by Markus Mohrhard
parent fbe77f453c
commit b190ffe587
4 changed files with 29 additions and 42 deletions

View File

@@ -84,6 +84,7 @@ protected:
bool CreateLinearGradientProgram( void );
bool CreateRadialGradientProgram( void );
public:
void BeginSolid( SalColor nColor, sal_uInt8 nTransparency );
void BeginSolid( SalColor nColor, double fTransparency );
void BeginSolid( SalColor nColor );
@@ -102,12 +103,13 @@ protected:
void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon );
void DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false );
void DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false );
void DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false, bool pPremultiplied = false );
void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry );
void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry );
void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect );
void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect );
protected:
public:
// get the width of the device
virtual GLfloat GetWidth() const = 0;

View File

@@ -670,6 +670,17 @@ void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRe
CHECK_GL_ERROR();
}
void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted, bool bPremultiplied )
{
glEnable( GL_BLEND );
if( bPremultiplied )
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
else
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
DrawTexture( rTexture, rPosAry, bInverted );
glDisable( GL_BLEND );
}
void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& pPosAry )
{
if( mnMaskedTextureProgram == 0 )
@@ -1301,10 +1312,7 @@ bool OpenGLSalGraphicsImpl::drawAlphaBitmap(
SAL_INFO( "vcl.opengl", "::drawAlphaBitmap" );
PreDraw();
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
DrawTexture( rTexture, rPosAry );
glDisable( GL_BLEND );
DrawAlphaTexture( rTexture, rPosAry );
PostDraw();
CHECK_GL_ERROR();

View File

@@ -9,6 +9,7 @@
#include "openglx11cairotextrender.hxx"
#include "openglgdiimpl.hxx"
#include "salbmp.hxx"
#include <vcl/salbtype.hxx>
@@ -33,40 +34,8 @@ void OpenGLX11CairoTextRender::drawSurface(cairo_t* cr)
cairo_surface_t* pSurface = cairo_get_target(cr);
int nWidth = cairo_image_surface_get_width( pSurface );
int nHeight = cairo_image_surface_get_height( pSurface );
SalBitmap* pBitmap = ImplGetSVData()->mpDefInst->CreateSalBitmap();
pBitmap->Create(Size(nWidth, nHeight), 32, BitmapPalette());
cairo_surface_flush( pSurface );
BitmapBuffer* pBuffer = pBitmap->AcquireBuffer(false);
unsigned char *pSrc = cairo_image_surface_get_data( pSurface );
unsigned int nSrcStride = cairo_image_surface_get_stride( pSurface );
unsigned int nDestStride = pBuffer->mnScanlineSize;
for( unsigned long y = 0; y < (unsigned long) nHeight; y++ )
{
// Cairo surface is y-inverse
sal_uInt32 *pSrcPix = (sal_uInt32 *)(pSrc + nSrcStride * (nHeight - y - 1));
sal_uInt32 *pDestPix = (sal_uInt32 *)(pBuffer->mpBits + nDestStride * y);
for( unsigned long x = 0; x < (unsigned long) nWidth; x++ )
{
sal_uInt8 nAlpha = (*pSrcPix >> 24);
sal_uInt8 nR = (*pSrcPix >> 16) & 0xff;
sal_uInt8 nG = (*pSrcPix >> 8) & 0xff;
sal_uInt8 nB = *pSrcPix & 0xff;
if( nAlpha != 0 && nAlpha != 255 )
{
// Cairo uses pre-multiplied alpha - we do not => re-multiply
nR = (sal_uInt8) MinMax( ((sal_uInt32)nR * 255) / nAlpha, 0, 255 );
nG = (sal_uInt8) MinMax( ((sal_uInt32)nG * 255) / nAlpha, 0, 255 );
nB = (sal_uInt8) MinMax( ((sal_uInt32)nB * 255) / nAlpha, 0, 255 );
}
// FIXME: lfrb: depends on endianness (use BitmapWriteAccess)
*pDestPix = (nAlpha << 24) + (nB << 16) + (nG << 8) + nR;
pSrcPix++;
pDestPix++;
}
}
pBitmap->ReleaseBuffer(pBuffer, false);
SalTwoRect aRect;
aRect.mnSrcX = 0;
@@ -78,8 +47,16 @@ void OpenGLX11CairoTextRender::drawSurface(cairo_t* cr)
aRect.mnDestWidth = nWidth;
aRect.mnDestHeight = nHeight;
mrParent.drawAlphaBitmap(aRect, *pBitmap);
delete pBitmap;
// XXX: lfrb: GLES 2.0 doesn't support GL_UNSIGNED_INT_8_8_8_8_REV
OpenGLSalGraphicsImpl *pImpl = dynamic_cast< OpenGLSalGraphicsImpl* >(mrParent.GetImpl());
if( pImpl )
{
// Cairo surface data is ARGB with premultiplied alpha and is Y-inverted
OpenGLTexture aTexture( nWidth, nHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pSrc );
pImpl->PreDraw();
pImpl->DrawAlphaTexture( aTexture, aRect, true, true );
pImpl->PostDraw();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -202,9 +202,9 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
aRects.mnDestWidth = width;
aRects.mnDestHeight = height;
// FIXME We don't have a method that could paint a texture with
// transparency yet, use it when we have it
pImpl->DrawTexture(aTexture, aRects);
pImpl->PreDraw();
pImpl->DrawAlphaTexture(aTexture, aRects);
pImpl->PostDraw();
}
DeleteObject(hBitmap);