Kaydet (Commit) c44ee2be authored tarafından Luboš Luňák's avatar Luboš Luňák

when drawing a transformed bitmap in opengl backend, scale it better

The plain scaling is rather rough, and in fact drawing a scaled bitmap
the normal way gives much better results (because OutputDevice pre-scales
the bitmap before it's drawn). This one may be a bit slow perhaps,
but hopefully nobody there's no code that'd extensively use bitmap
drawing with custom transformations (wishful thinking).

Change-Id: I83e05307adfaeac0ed0757f1a0b2603f64caf8f8
üst df290c63
......@@ -18,6 +18,12 @@ uniform float ratio; // = 1.0/(xscale*yscale)
varying vec2 tex_coord;
// This mode makes the scaling work like maskedTextureFragmentShader.glsl
// (instead of like plain textureVertexShader.glsl).
#ifdef MASKED
uniform sampler2D mask;
#endif
/*
Just make the resulting color the average of all the source pixels
(which is an area (xscale)x(yscale) ).
......@@ -30,7 +36,14 @@ void main(void)
{
for( int x = 0; x < xscale; ++x )
{
#ifndef MASKED
sum += texture2D( sampler, tex_coord.st + offset );
#else
vec4 texel;
texel = texture2D( sampler, tex_coord.st + offset );
texel.a = 1.0 - texture2D( mask, tex_coord.st + offset ).r;
sum += texel;
#endif
offset.x += xstep;
}
offset.y += ystep;
......
......@@ -27,6 +27,12 @@ uniform float ydestconvert;
varying vec2 tex_coord;
// This mode makes the scaling work like maskedTextureFragmentShader.glsl
// (instead of like plain textureVertexShader.glsl).
#ifdef MASKED
uniform sampler2D mask;
#endif
void main(void)
{
// Convert to pixel coordinates again.
......@@ -126,7 +132,14 @@ void main(void)
for( int x = xstart; x <= xend; ++x, ++xpos )
{
vec2 offset = vec2( x * xsrcconvert, y * ysrcconvert );
#ifndef MASKED
tmp += texture2D( sampler, offset ) * xratio[ xpos ];
#else
vec4 texel;
texel = texture2D( sampler, offset );
texel.a = 1.0 - texture2D( mask, offset ).r;
tmp += texel * xratio[ xpos ];
#endif
}
sum += tmp * yratio[ ypos ];
}
......
......@@ -894,9 +894,34 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
(float) rTexture.GetWidth(), 0, (float) rTexture.GetWidth(), (float) rTexture.GetHeight() };
GLfloat aTexCoord[8];
// If downscaling at a higher scale ratio, use the area scaling algorithm rather
// than plain OpenGL's scaling, for better results.
// See OpenGLSalBitmap::ImplScaleArea().
double ixscale = rTexture.GetWidth() / fabs( rX.getX() - rNull.getX());
double iyscale = rTexture.GetHeight() / fabs( rY.getY() - rNull.getY());
bool areaScaling = false;
bool fastAreaScaling = false;
OUString textureFragmentShader;
if( ixscale >= 2 && iyscale >= 2 ) // Downscaling to 50% or less? (inverted scale ratios)
{
areaScaling = true;
fastAreaScaling = ( ixscale == int( ixscale ) && iyscale == int( iyscale ));
// The generic case has arrays only up to 100 ratio downscaling, which is hopefully enough
// in practice, but protect against buffer overflows in case such an extreme case happens
// (and in such case the precision of the generic algorithm probably doesn't matter anyway).
if( ixscale > 100 || iyscale > 100 )
fastAreaScaling = true;
if( fastAreaScaling )
textureFragmentShader = "areaScaleFastFragmentShader";
else
textureFragmentShader = "areaScaleFragmentShader";
}
if( rMask )
{
if( !UseProgram( "transformedTextureVertexShader", "maskedTextureFragmentShader" ) )
if( !UseProgram( "transformedTextureVertexShader",
textureFragmentShader.isEmpty() ? "maskedTextureFragmentShader" : textureFragmentShader,
"#define MASKED" ) )
return;
mpProgram->SetTexture( "mask", rMask );
rMask.SetFilter( GL_LINEAR );
......@@ -904,10 +929,40 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
}
else
{
if( !UseProgram( "transformedTextureVertexShader", "textureFragmentShader" ) )
if( !UseProgram( "transformedTextureVertexShader",
textureFragmentShader.isEmpty() ? "textureFragmentShader" : textureFragmentShader ) )
return;
}
if( areaScaling )
{
// From OpenGLSalBitmap::ImplScaleArea().
if( fastAreaScaling )
{
int mnWidth = rTexture.GetWidth();
int mnHeight = rTexture.GetHeight();
mpProgram->SetUniform1i( "xscale", ixscale );
mpProgram->SetUniform1i( "yscale", iyscale );
mpProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
mpProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
mpProgram->SetUniform1f( "ratio", 1.0 / ( ixscale * iyscale ));
}
else
{
int mnWidth = rTexture.GetWidth();
int mnHeight = rTexture.GetHeight();
mpProgram->SetUniform1f( "xscale", ixscale );
mpProgram->SetUniform1f( "yscale", iyscale );
mpProgram->SetUniform1i( "swidth", mnWidth );
mpProgram->SetUniform1i( "sheight", mnHeight );
// For converting between <0,mnWidth-1> and <0.0,1.0> coordinate systems.
mpProgram->SetUniform1f( "xsrcconvert", 1.0 / ( mnWidth - 1 ));
mpProgram->SetUniform1f( "ysrcconvert", 1.0 / ( mnHeight - 1 ));
mpProgram->SetUniform1f( "xdestconvert", 1.0 * (( mnWidth / ixscale ) - 1 ));
mpProgram->SetUniform1f( "ydestconvert", 1.0 * (( mnHeight / iyscale ) - 1 ));
}
}
mpProgram->SetUniform2f( "viewport", GetWidth(), GetHeight() );
mpProgram->SetTransform( "transform", rTexture, rNull, rX, rY );
rTexture.GetWholeCoord( aTexCoord );
......
......@@ -225,6 +225,7 @@ bool OpenGLSalBitmap::ImplScaleArea( double rScaleX, double rScaleY )
OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, nNewHeight );
OpenGLFramebuffer* pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex );
// NOTE: This setup is also done in OpenGLSalGraphicsImpl::DrawTransformedTexture().
if( fast )
{
pProgram->SetUniform1i( "xscale", ixscale );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment