vcl/inc/openglgdiimpl.hxx | 5 vcl/opengl/gdiimpl.cxx | 304 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 272 insertions(+), 37 deletions(-)
New commits: commit 05ac44e7e6c16bfb093c19630da67ac42ae913bf Author: László Németh <[email protected]> Date: Thu May 19 20:12:41 2016 +0200 default subset, calculate all, format change Also revert "opengl: use line shader for all line drawing not just polylines" This reverts commit 860f19365264aaf192dd6e2464efa02123a2cd91. and 808a4cdc7e19823b15123f8037173a7dd43e5727 Change-Id: Ifed8f1a4f5b4880a5fb24e2db8708f7d14b0b869 diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index da0fe69..6dfa73c 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -114,12 +114,17 @@ public: bool UseSolid( SalColor nColor, sal_uInt8 nTransparency ); bool UseSolid( SalColor nColor, double fTransparency ); bool UseSolid( SalColor nColor ); + bool UseSolidAA( SalColor nColor, double fTransparency ); + bool UseSolidAA( SalColor nColor ); bool UseLine(SalColor nColor, double fTransparency, GLfloat fLineWidth, bool bUseAA); bool UseInvert50(); bool UseInvert(SalInvert nFlags); void DrawPoint( long nX, long nY ); void DrawLine( double nX1, double nY1, double nX2, double nY2 ); + void DrawLineAA( double nX1, double nY1, double nX2, double nY2 ); + void DrawLinesAA( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose ); + void DrawEdgeAA( double nX1, double nY1, double nX2, double nY2 ); void DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, bool blockAA = false ); void DrawConvexPolygon( const tools::Polygon& rPolygon, bool blockAA = false ); void DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoid, bool blockAA = false ); diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 42a62fc..2beb5fe 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -581,6 +581,25 @@ bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor ) return UseSolid( nColor, 0.0f ); } +// Like UseSolid(), but sets up for AA drawing, which uses gradients to create the AA. +bool OpenGLSalGraphicsImpl::UseSolidAA( SalColor nColor, double fTransparency ) +{ + if( nColor == SALCOLOR_NONE ) + return false; + if( !mrParent.getAntiAliasB2DDraw()) + return UseSolid( nColor ); + if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) ) + return false; + mpProgram->SetColorf( "start_color", nColor, fTransparency ); + mpProgram->SetColorf( "end_color", nColor, 1.0f ); + return true; +} + +bool OpenGLSalGraphicsImpl::UseSolidAA( SalColor nColor ) +{ + return UseSolidAA( nColor, 0.0 ); +} + bool OpenGLSalGraphicsImpl::UseInvert( SalInvert nFlags ) { OpenGLZone aZone; @@ -696,7 +715,7 @@ void OpenGLSalGraphicsImpl::DrawLineCap(float x1, float y1, float x2, float y2, addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f); } - ApplyProgramMatrices(0.5f); + ApplyProgramMatrices(0.0f); mpProgram->SetExtrusionVectors(aExtrusionVectors.data()); mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aVertices); @@ -708,6 +727,9 @@ void OpenGLSalGraphicsImpl::DrawLineSegment(float x1, float y1, float x2, float glm::vec2 p1(x1, y1); glm::vec2 p2(x2, y2); + if (p1.x == p2.x && p1.y == p2.y) + return; + std::vector<GLfloat> aPoints; std::vector<GLfloat> aExtrusionVectors; @@ -719,7 +741,7 @@ void OpenGLSalGraphicsImpl::DrawLineSegment(float x1, float y1, float x2, float addVertexPair(aPoints, aExtrusionVectors, p1, normal, 1.0f); addVertexPair(aPoints, aExtrusionVectors, p2, normal, 1.0f); - ApplyProgramMatrices(0.5f); + ApplyProgramMatrices(0.0f); mpProgram->SetExtrusionVectors(aExtrusionVectors.data()); mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aPoints); @@ -913,7 +935,7 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f); } - ApplyProgramMatrices(0.5f); + ApplyProgramMatrices(0.0f); mpProgram->SetExtrusionVectors(aExtrusionVectors.data()); mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aVertices); @@ -942,6 +964,179 @@ bool OpenGLSalGraphicsImpl::UseLine(SalColor nColor, double fTransparency, GLflo return true; } +void OpenGLSalGraphicsImpl::DrawLineAA( double nX1, double nY1, double nX2, double nY2 ) +{ + OpenGLZone aZone; + + if( !mrParent.getAntiAliasB2DDraw()) + return DrawLine( nX1, nY1, nX2, nY2 ); + + if( nX1 == nX2 || nY1 == nY2 ) + { // Horizontal/vertical, no need for AA, both points have normal color. + + // Still set up for the trivial "gradients", because presumably UseSolidAA() has been called. + GLfloat aTexCoord[4] = { 0, 1, 1, 1 }; + mpProgram->SetTextureCoord( aTexCoord ); + DrawLine(nX1, nY1, nX2, nY2); + + return; + } + ImplDrawLineAA( nX1, nY1, nX2, nY2 ); +} + +void OpenGLSalGraphicsImpl::ImplDrawLineAA( double nX1, double nY1, double nX2, double nY2, bool edge ) +{ + // Draw the line anti-aliased. Based on code with the following notice: + /* Drawing nearly perfect 2D line segments in OpenGL + * You can use this code however you want. + * I just hope you to cite my name and the page of this technique: + * http://artgrammer.blogspot.com/2011/05/drawing-nearly-perfect-2d-line-segments.html + * http://www.codeproject.com/KB/openGL/gllinedraw.aspx + * + * Enjoy. Chris Tsang.*/ + + double x1 = nX1; + double y1 = nY1; + double x2 = nX2; + double y2 = nY2; + + // A special hack for drawing lines that are in fact AA edges of a shape. Make the line somewhat + // wider, but (done further below) draw the entire width as a gradient. This would be wrong for a line + // (too wide and seemingly less straight), but it makes the edges look smoother and the width difference + // is almost unnoticeable. + const double w = edge ? 1.4 : 1.0; + + double t(0.0); + double R(0.0); + double f = w - static_cast<int>(w); + //determine parameters t,R + if ( w>=0.0 && w<1.0 ) + { + t=0.05; + R=0.48+0.32*f; + } + else if ( w>=1.0 && w<2.0 ) + { + t=0.05+f*0.33; + R=0.768+0.312*f; + } + else if ( w>=2.0 && w<3.0 ) + { + t=0.38+f*0.58; + R=1.08; + } + else if ( w>=3.0 && w<4.0 ) + { + t=0.96+f*0.48; + R=1.08; + } + else if ( w>=4.0 && w<5.0 ) + { + t=1.44+f*0.46; + R=1.08; + } + else if ( w>=5.0 && w<6.0 ) + { + t=1.9+f*0.6; + R=1.08; + } + else if ( w>=6.0 ) + { + double ff=w-6.0; + t=2.5+ff*0.50; + R=1.08; + } + + //determine angle of the line to horizontal + double tx=0,ty=0; //core thinkness of a line + double Rx=0,Ry=0; //fading edge of a line + double dx=x2-x1; + double dy=y2-y1; + if ( w < 3 ) + { //approximate to make things even faster + double m=dy/dx; + //and calculate tx,ty,Rx,Ry + if ( m>-0.4142 && m<=0.4142) + { + // -22.5< angle <= 22.5, approximate to 0 (degree) + tx=t*0.1; ty=t; + Rx=R*0.6; Ry=R; + } + else if ( m>0.4142 && m<=2.4142) + { + // 22.5< angle <= 67.5, approximate to 45 (degree) + tx=t*-0.7071; ty=t*0.7071; + Rx=R*-0.7071; Ry=R*0.7071; + } + else if ( m>2.4142 || m<=-2.4142) + { + // 67.5 < angle <=112.5, approximate to 90 (degree) + tx=t; ty=t*0.1; + Rx=R; Ry=R*0.6; + } + else if ( m>-2.4142 && m<-0.4142) + { + // 112.5 < angle < 157.5, approximate to 135 (degree) + tx=t*0.7071; ty=t*0.7071; + Rx=R*0.7071; Ry=R*0.7071; + } + else + assert( false ); + } + else + { //calculate to exact + dx=y1-y2; + dy=x2-x1; + double L=sqrt(dx*dx+dy*dy); + dx/=L; + dy/=L; + tx=t*dx; ty=t*dy; + Rx=R*dx; Ry=R*dy; + } + + if( edge ) + { // See above. + Rx += tx; + Ry += ty; + tx = ty = 0; + } + + std::vector<GLfloat> vertices + { + GLfloat(x1-tx-Rx), GLfloat(y1-ty-Ry), //fading edge1 + GLfloat(x2-tx-Rx), GLfloat(y2-ty-Ry), + GLfloat(x1-tx), GLfloat(y1-ty), //core + GLfloat(x2-tx), GLfloat(y2-ty), + GLfloat(x1+tx), GLfloat(y1+ty), + GLfloat(x2+tx), GLfloat(y2+ty), + GLfloat(x1+tx+Rx), GLfloat(y1+ty+Ry), //fading edge2 + GLfloat(x2+tx+Rx), GLfloat(y2+ty+Ry) + }; + + ApplyProgramMatrices(0.0f); + GLfloat aTexCoord[16] = { 0, 0, 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 0, 7, 0 }; + mpProgram->SetTextureCoord( aTexCoord ); + mpProgram->DrawArrays(GL_TRIANGLE_STRIP, vertices); + CHECK_GL_ERROR(); +} + + +void OpenGLSalGraphicsImpl::DrawLinesAA( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose ) +{ + for( int i = 0; i < int(nPoints) - 1; ++i ) + DrawLineAA( pPtAry[ i ].mnX, pPtAry[ i ].mnY, pPtAry[ i + 1 ].mnX, pPtAry[ i + 1 ].mnY ); + if( bClose ) + DrawLineAA( pPtAry[ nPoints - 1 ].mnX, pPtAry[ nPoints - 1 ].mnY, pPtAry[ 0 ].mnX, pPtAry[ 0 ].mnY ); +} + +void OpenGLSalGraphicsImpl::DrawEdgeAA( double nX1, double nY1, double nX2, double nY2 ) +{ + assert( mrParent.getAntiAliasB2DDraw()); + if( nX1 == nX2 || nY1 == nY2 ) + return; //horizontal/vertical, no need for AA + ImplDrawLineAA( nX1, nY1, nX2, nY2, true ); +} + void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, bool blockAA ) { OpenGLZone aZone; @@ -970,13 +1165,13 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoin #endif SalColor lastSolidColor = mProgramSolidColor; double lastSolidTransparency = mProgramSolidTransparency; - if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true)) + if( UseSolidAA( lastSolidColor, lastSolidTransparency )) { for( i = 0; i < nPoints; ++i ) { const SalPoint& rPt1 = pPtAry[ i ]; const SalPoint& rPt2 = pPtAry[ ( i + 1 ) % nPoints ]; - DrawLineSegment(rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY); + DrawEdgeAA( rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY ); } UseSolid( lastSolidColor, lastSolidTransparency ); } @@ -1013,13 +1208,13 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( const tools::Polygon& rPolygon, b #endif SalColor lastSolidColor = mProgramSolidColor; double lastSolidTransparency = mProgramSolidTransparency; - if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true)) + if( UseSolidAA( lastSolidColor, lastSolidTransparency )) { for( i = 0; i < nPoints; ++i ) { const Point& rPt1 = rPolygon.GetPoint( i ); const Point& rPt2 = rPolygon.GetPoint(( i + 1 ) % nPoints ); - DrawLineSegment(rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY()); + DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY()); } UseSolid( lastSolidColor, lastSolidTransparency ); } @@ -1063,13 +1258,13 @@ void OpenGLSalGraphicsImpl::DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoi #endif SalColor lastSolidColor = mProgramSolidColor; double lastSolidTransparency = mProgramSolidTransparency; - if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true)) + if( UseSolidAA( lastSolidColor, lastSolidTransparency )) { for( i = 0; i < nPoints; ++i ) { const basegfx::B2DPoint& rPt1 = rPolygon.getB2DPoint( i ); const basegfx::B2DPoint& rPt2 = rPolygon.getB2DPoint(( i + 1 ) % nPoints ); - DrawLineSegment(rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY()); + DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY()); } UseSolid( lastSolidColor, lastSolidTransparency ); } @@ -1691,8 +1886,8 @@ void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 ) if( mnLineColor != SALCOLOR_NONE ) { PreDraw( XOROption::IMPLEMENT_XOR ); - if (UseLine(mnLineColor, 0.0, 1.0f, mrParent.getAntiAliasB2DDraw())) - DrawLineSegment(nX1, nY1, nX2, nY2); + if( UseSolidAA( mnLineColor ) ) + DrawLineAA( nX1, nY1, nX2, nY2 ); PostDraw(); } } @@ -1729,45 +1924,80 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) { - basegfx::B2DPolygon aPoly; - aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints); - for (sal_uInt32 i = 1; i < nPoints; ++i) - aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY)); - aPoly.setClosed(false); + VCL_GL_INFO( "::drawPolyLine" ); - drawPolyLine(aPoly, 0.0, basegfx::B2DVector(1.0, 1.0), basegfx::B2DLineJoin::Miter, - css::drawing::LineCap_BUTT, 15.0 * F_PI180 /*default*/); + if( mnLineColor != SALCOLOR_NONE && nPoints > 1 ) + { + PreDraw( XOROption::IMPLEMENT_XOR ); + if( UseSolidAA( mnLineColor ) ) + DrawLinesAA( nPoints, pPtAry, false ); + PostDraw(); + } } void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) { - basegfx::B2DPolygon aPoly; - aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints); - for (sal_uInt32 i = 1; i < nPoints; ++i) - aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY)); + VCL_GL_INFO( "::drawPolygon" ); + if( nPoints == 0 ) + return; + if( nPoints == 1 ) + { + drawPixel( pPtAry[0].mnX, pPtAry[0].mnY ); + return; + } + if( nPoints == 2 ) + { + drawLine( pPtAry[0].mnX, pPtAry[0].mnY, + pPtAry[1].mnX, pPtAry[1].mnY ); + return; + } + + PreDraw( XOROption::IMPLEMENT_XOR ); - drawPolyPolygon(basegfx::B2DPolyPolygon(aPoly), 0.0); + if( UseSolid( mnFillColor ) ) + DrawPolygon( nPoints, pPtAry ); + + if( UseSolidAA( mnLineColor ) ) + DrawLinesAA( nPoints, pPtAry, true ); + + PostDraw(); } -void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPointCounts, PCONSTSALPOINT* pPtAry ) +void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) { - basegfx::B2DPolyPolygon aPolyPoly; - for(sal_uInt32 nPolygon = 0; nPolygon < nPoly; ++nPolygon) + VCL_GL_INFO( "::drawPolyPolygon" ); + if( nPoly <= 0 ) + return; + + PreDraw( XOROption::IMPLEMENT_XOR ); + + if( UseSolid( mnFillColor ) ) { - sal_uInt32 nPoints = pPointCounts[nPolygon]; - if (nPoints) + if( nPoly == 1 ) + DrawPolygon( pPoints[ 0 ], pPtAry[ 0 ] ); + else { - PCONSTSALPOINT pPoints = pPtAry[nPolygon]; - basegfx::B2DPolygon aPoly; - aPoly.append( basegfx::B2DPoint(pPoints->mnX, pPoints->mnY), nPoints); - for (sal_uInt32 i = 1; i < nPoints; ++i) - aPoly.setB2DPoint(i, basegfx::B2DPoint( pPoints[i].mnX, pPoints[i].mnY)); - - aPolyPoly.append(aPoly); + basegfx::B2DPolyPolygon polyPolygon; + for( sal_uInt32 i = 0; i < nPoly; ++i ) + { + basegfx::B2DPolygon polygon; + for( sal_uInt32 j = 0; j < pPoints[ i ]; ++j ) + polygon.append( basegfx::B2DPoint( pPtAry[i][j].mnX, pPtAry[i][j].mnY ) ); + polygon.setClosed( true ); + polyPolygon.append( polygon ); + } + DrawPolyPolygon( polyPolygon ); } } - drawPolyPolygon(aPolyPoly, 0.0); + if( mnLineColor != mnFillColor && UseSolidAA( mnLineColor ) ) + { + // TODO Use glMultiDrawElements or primitive restart + for( sal_uInt32 i = 0; i < nPoly; i++ ) + DrawLinesAA( pPoints[i], pPtAry[i], true ); + } + + PostDraw(); } bool OpenGLSalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency ) @@ -1810,7 +2040,7 @@ bool OpenGLSalGraphicsImpl::drawPolyLine( PreDraw(XOROption::IMPLEMENT_XOR); - if (UseLine(mnLineColor, 0.0f, fLineWidth, mrParent.getAntiAliasB2DDraw())) + if (UseLine(mnLineColor, 0.0f, fLineWidth, true)) { basegfx::B2DPolygon aPolygon(rPolygon);
_______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
