summaryrefslogtreecommitdiff
path: root/vcl/opengl
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2014-11-11 15:54:03 -0500
committerMarkus Mohrhard <markus.mohrhard@collabora.co.uk>2014-11-12 04:07:31 +0100
commite1e787d5e418a328f8023d3b777384b98441a9de (patch)
tree1021452c507f2a5cb5fbe5b581c3e51c94597717 /vcl/opengl
parent74c3dbe87e7256f8f8b3eac3a34415780035f465 (diff)
vcl: Add support for radial gradients in OpenGL backend
Change-Id: Ie47fb18ae7d5286fe7559c7dffbc54b0856d4d8e
Diffstat (limited to 'vcl/opengl')
-rw-r--r--vcl/opengl/gdiimpl.cxx118
-rw-r--r--vcl/opengl/radialGradientFragmentShader.glsl23
2 files changed, 123 insertions, 18 deletions
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 65c4f3089017..744aa7fa541b 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -75,6 +75,13 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
, mnMaskProgram(0)
, mnMaskUniform(0)
, mnMaskColorUniform(0)
+ , mnLinearGradientProgram(0)
+ , mnLinearGradientStartColorUniform(0)
+ , mnLinearGradientEndColorUniform(0)
+ , mnRadialGradientProgram(0)
+ , mnRadialGradientStartColorUniform(0)
+ , mnRadialGradientEndColorUniform(0)
+ , mnRadialGradientCenterUniform(0)
{
}
@@ -295,7 +302,20 @@ bool OpenGLSalGraphicsImpl::CreateLinearGradientProgram( void )
glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" );
mnLinearGradientStartColorUniform = glGetUniformLocation( mnLinearGradientProgram, "start_color" );
mnLinearGradientEndColorUniform = glGetUniformLocation( mnLinearGradientProgram, "end_color" );
- mnLinearGradientTransformUniform = glGetUniformLocation( mnLinearGradientProgram, "transform" );
+ return true;
+}
+
+bool OpenGLSalGraphicsImpl::CreateRadialGradientProgram( void )
+{
+ mnRadialGradientProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "radialGradientFragmentShader" );
+ if( mnRadialGradientProgram == 0 )
+ return false;
+
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" );
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" );
+ mnRadialGradientStartColorUniform = glGetUniformLocation( mnRadialGradientProgram, "start_color" );
+ mnRadialGradientEndColorUniform = glGetUniformLocation( mnRadialGradientProgram, "end_color" );
+ mnRadialGradientCenterUniform = glGetUniformLocation( mnRadialGradientProgram, "center" );
return true;
}
@@ -455,6 +475,18 @@ void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, long nHeigh
DrawConvexPolygon( 4, aPoints );
}
+void OpenGLSalGraphicsImpl::DrawRect( const Rectangle& rRect )
+{
+ long nX1( rRect.Left() );
+ long nY1( GetHeight() - rRect.Top() );
+ long nX2( rRect.Right() );
+ long nY2( GetHeight() - rRect.Bottom() );
+ const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
+ { nX2, nY1 }, { nX2, nY2 }};
+
+ DrawConvexPolygon( 4, aPoints );
+}
+
void OpenGLSalGraphicsImpl::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
{
::basegfx::B2DPolygon aPolygon;
@@ -601,18 +633,6 @@ void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const S
void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect )
{
- if( rGradient.GetBorder() >= 100.0 )
- {
- // border >= 100%, draw solid rectangle
- Color aCol = rGradient.GetStartColor();
- long nF = rGradient.GetStartIntensity();
- BeginSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100,
- aCol.GetGreen() * nF / 100,
- aCol.GetBlue() * nF / 100 ) );
- DrawRect( rRect.Left(), rRect.Top(), rRect.GetWidth(), rRect.GetHeight() );
- EndSolid();
- return;
- }
if( mnLinearGradientProgram == 0 )
{
@@ -632,10 +652,6 @@ void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const
Rectangle aBoundRect;
Point aCenter;
rGradient.GetBoundRect( rRect, aBoundRect, aCenter );
- aBoundRect.Left()--;
- aBoundRect.Top()--;
- aBoundRect.Right()++;
- aBoundRect.Bottom()++;
Polygon aPoly( aBoundRect );
aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 );
@@ -653,6 +669,43 @@ void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const
glUseProgram( 0 );
}
+void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect )
+{
+ if( mnRadialGradientProgram == 0 )
+ {
+ if( !CreateRadialGradientProgram() )
+ return;
+ }
+
+ glUseProgram( mnRadialGradientProgram );
+
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nFactor = rGradient.GetStartIntensity();
+ glUniformColorIntensity( mnRadialGradientStartColorUniform, aStartCol, nFactor );
+ nFactor = rGradient.GetEndIntensity();
+ glUniformColorIntensity( mnRadialGradientEndColorUniform, aEndCol, nFactor );
+
+ Rectangle aRect;
+ Point aCenter;
+ rGradient.GetBoundRect( rRect, aRect, aCenter );
+
+ // adjust coordinates so that radius has distance equals to 1.0
+ double fRadius = aRect.GetWidth() / 2.0f;
+ GLfloat fWidth = rRect.GetWidth() / fRadius;
+ GLfloat fHeight = rRect.GetHeight() / fRadius;
+ glUniform2f( mnRadialGradientCenterUniform, (aCenter.X() -rRect.Left()) / fRadius, (aCenter.Y() - rRect.Top()) / fRadius );
+
+ GLfloat aTexCoord[8] = { 0, 0, 0, fHeight, fWidth, fHeight, fWidth, 0 };
+ glEnableVertexAttribArray( GL_ATTRIB_TEX );
+ glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord );
+
+ DrawRect( rRect );
+
+ glDisableVertexAttribArray( GL_ATTRIB_TEX );
+ glUseProgram( 0 );
+}
+
// draw --> LineColor and FillColor and RasterOp and ClipRegion
void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
@@ -1189,11 +1242,33 @@ bool OpenGLSalGraphicsImpl::drawAlphaRect(
bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
const Gradient& rGradient)
{
- const Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
+ Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
+
+ SAL_INFO( "vcl.opengl", "::drawGradient" );
if( aBoundRect.IsEmpty() )
return true;
+ aBoundRect.Left()--;
+ aBoundRect.Top()--;
+ aBoundRect.Right()++;
+ aBoundRect.Bottom()++;
+
+ // if border >= 100%, draw solid rectangle with start color
+ if( rGradient.GetBorder() >= 100.0 )
+ {
+ Color aCol = rGradient.GetStartColor();
+ long nF = rGradient.GetStartIntensity();
+ PreDraw();
+ BeginSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100,
+ aCol.GetGreen() * nF / 100,
+ aCol.GetBlue() * nF / 100 ) );
+ DrawRect( aBoundRect );
+ EndSolid();
+ PostDraw();
+ return true;
+ }
+
//TODO: lfrb: some missing transformation with the polygon in outdev
if( rGradient.GetStyle() == GradientStyle_LINEAR )
{
@@ -1202,6 +1277,13 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
PostDraw();
return true;
}
+ else if( rGradient.GetStyle() == GradientStyle_RADIAL )
+ {
+ PreDraw();
+ DrawRadialGradient( rGradient, aBoundRect );
+ PostDraw();
+ return true;
+ }
return false;
}
diff --git a/vcl/opengl/radialGradientFragmentShader.glsl b/vcl/opengl/radialGradientFragmentShader.glsl
new file mode 100644
index 000000000000..94a86eb9510f
--- /dev/null
+++ b/vcl/opengl/radialGradientFragmentShader.glsl
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#version 120
+
+uniform vec4 start_color;
+uniform vec4 end_color;
+uniform vec2 center;
+varying vec2 tex_coord;
+
+void main(void)
+{
+ gl_FragColor = mix(end_color, start_color,
+ clamp(distance(tex_coord, center), 0.0, 1.0));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */