[Libreoffice-commits] core.git: Branch 'feature/fixes22' - 4 commits - basegfx/source include/basegfx vcl/inc vcl/opengl vcl/source

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Wed May 25 16:25:47 UTC 2016


 basegfx/source/polygon/b2dlinegeometry.cxx  |   29 -
 basegfx/source/polygon/b2dpolygon.cxx       |    2 
 include/basegfx/polygon/b2dlinegeometry.hxx |    5 
 vcl/inc/opengl/RenderState.hxx              |   27 +
 vcl/inc/opengl/program.hxx                  |    5 
 vcl/inc/openglgdiimpl.hxx                   |    5 
 vcl/opengl/gdiimpl.cxx                      |  419 +++++-----------------------
 vcl/opengl/program.cxx                      |   45 +--
 vcl/source/opengl/OpenGLContext.cxx         |    6 
 9 files changed, 151 insertions(+), 392 deletions(-)

New commits:
commit 79498ea619d6e8954aea68396c5a5b2c0e0fd025
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu May 19 21:35:28 2016 +0900

    opengl: use line shader for all line drawing not just polylines
    
    Change-Id: I9c2d5c5ca4761867a0a38cb3bc3c4973454ee992

diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 284a233..da0fe69 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -114,16 +114,12 @@ 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 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 d5e6b71..48871d5 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -581,25 +581,6 @@ 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;
@@ -715,7 +696,7 @@ void OpenGLSalGraphicsImpl::DrawLineCap(float x1, float y1, float x2, float y2,
         addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
     }
 
-    ApplyProgramMatrices(0.0f);
+    ApplyProgramMatrices(0.5f);
     mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
     mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aVertices);
 
@@ -727,9 +708,6 @@ 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;
 
@@ -741,7 +719,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.0f);
+    ApplyProgramMatrices(0.5f);
     mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
     mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aPoints);
 
@@ -935,7 +913,7 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
             addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
         }
 
-        ApplyProgramMatrices(0.0f);
+        ApplyProgramMatrices(0.5f);
         mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
         mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aVertices);
 
@@ -964,170 +942,6 @@ 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::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;
@@ -1156,13 +970,13 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoin
 #endif
         SalColor lastSolidColor = mProgramSolidColor;
         double lastSolidTransparency = mProgramSolidTransparency;
-        if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
+        if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true))
         {
             for( i = 0; i < nPoints; ++i )
             {
                 const SalPoint& rPt1 = pPtAry[ i ];
                 const SalPoint& rPt2 = pPtAry[ ( i + 1 ) % nPoints ];
-                DrawEdgeAA( rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY );
+                DrawLineSegment(rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY);
             }
             UseSolid( lastSolidColor, lastSolidTransparency );
         }
@@ -1199,13 +1013,13 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( const tools::Polygon& rPolygon, b
 #endif
         SalColor lastSolidColor = mProgramSolidColor;
         double lastSolidTransparency = mProgramSolidTransparency;
-        if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
+        if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true))
         {
             for( i = 0; i < nPoints; ++i )
             {
                 const Point& rPt1 = rPolygon.GetPoint( i );
                 const Point& rPt2 = rPolygon.GetPoint(( i + 1 ) % nPoints );
-                DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
+                DrawLineSegment(rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
             }
             UseSolid( lastSolidColor, lastSolidTransparency );
         }
@@ -1249,13 +1063,13 @@ void OpenGLSalGraphicsImpl::DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoi
 #endif
         SalColor lastSolidColor = mProgramSolidColor;
         double lastSolidTransparency = mProgramSolidTransparency;
-        if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
+        if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true))
         {
             for( i = 0; i < nPoints; ++i )
             {
                 const basegfx::B2DPoint& rPt1 = rPolygon.getB2DPoint( i );
                 const basegfx::B2DPoint& rPt2 = rPolygon.getB2DPoint(( i + 1 ) % nPoints );
-                DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
+                DrawLineSegment(rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
             }
             UseSolid( lastSolidColor, lastSolidTransparency );
         }
@@ -1877,8 +1691,8 @@ void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
     if( mnLineColor != SALCOLOR_NONE )
     {
         PreDraw( XOROption::IMPLEMENT_XOR );
-        if( UseSolidAA( mnLineColor ) )
-            DrawLineAA( nX1, nY1, nX2, nY2 );
+        if (UseLine(mnLineColor, 0.0, 1.0f, mrParent.getAntiAliasB2DDraw()))
+            DrawLineSegment(nX1, nY1, nX2, nY2);
         PostDraw();
     }
 }
@@ -1995,7 +1809,7 @@ bool OpenGLSalGraphicsImpl::drawPolyLine(
 
     PreDraw(XOROption::IMPLEMENT_XOR);
 
-    if (UseLine(mnLineColor, 0.0f, fLineWidth, true))
+    if (UseLine(mnLineColor, 0.0f, fLineWidth, mrParent.getAntiAliasB2DDraw()))
     {
         basegfx::B2DPolygon aPolygon(rPolygon);
 
commit c9d0e1e7eef6870e34eff7b056ab23acab23d910
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed May 18 18:47:48 2016 +0900

    opengl: use existing code for "legacy" polyline, polygon render.
    
    Rendering polylines, polygons, polypolygons which take an array
    as parameter ("legacy" code) can re-use the other, already
    existing code paths (same thing as "headless" svp backend does).
    
    Change-Id: Ie45812d7fce6bc70484e9f0c05cc81e995800bcb

diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 6dfa73c..284a233 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -123,7 +123,6 @@ public:
     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 );
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 2beb5fe..d5e6b71 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -1120,15 +1120,6 @@ void OpenGLSalGraphicsImpl::ImplDrawLineAA( double nX1, double nY1, double nX2,
     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());
@@ -1924,80 +1915,44 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh
 
 void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
-    VCL_GL_INFO( "::drawPolyLine" );
+    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);
 
-    if( mnLineColor != SALCOLOR_NONE && nPoints > 1 )
-    {
-        PreDraw( XOROption::IMPLEMENT_XOR );
-        if( UseSolidAA( mnLineColor ) )
-            DrawLinesAA( nPoints, pPtAry, false );
-        PostDraw();
-    }
+    drawPolyLine(aPoly, 0.0, basegfx::B2DVector(1.0, 1.0), basegfx::B2DLineJoin::Miter, css::drawing::LineCap_BUTT);
 }
 
 void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
-    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 );
+    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));
 
-    if( UseSolid( mnFillColor ) )
-        DrawPolygon( nPoints, pPtAry );
-
-    if( UseSolidAA( mnLineColor ) )
-        DrawLinesAA( nPoints, pPtAry, true );
-
-    PostDraw();
+    drawPolyPolygon(basegfx::B2DPolyPolygon(aPoly), 0.0);
 }
 
-void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
+void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPointCounts, PCONSTSALPOINT* pPtAry )
 {
-    VCL_GL_INFO( "::drawPolyPolygon" );
-    if( nPoly <= 0 )
-        return;
-
-    PreDraw( XOROption::IMPLEMENT_XOR );
-
-    if( UseSolid( mnFillColor ) )
+    basegfx::B2DPolyPolygon aPolyPoly;
+    for(sal_uInt32 nPolygon = 0; nPolygon < nPoly; ++nPolygon)
     {
-        if( nPoly == 1 )
-            DrawPolygon( pPoints[ 0 ], pPtAry[ 0 ] );
-        else
+        sal_uInt32 nPoints = pPointCounts[nPolygon];
+        if (nPoints)
         {
-            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 );
-        }
-    }
+            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));
 
-    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 );
+            aPolyPoly.append(aPoly);
+        }
     }
 
-    PostDraw();
+    drawPolyPolygon(aPolyPoly, 0.0);
 }
 
 bool OpenGLSalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency )
commit 666b662363c841579f6448a8436f814bae5d36dd
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon May 16 22:25:15 2016 +0900

    tdf#99130 use subdivision on B2DPolygon, angle based subdivision
    
    Remove the subdivider we used until now as there is a better
    way to subdivide a polygon with getDefaultAdaptiveSubdivision,
    which in additiona also caches the result. The subdivider used in
    getDefaultAdaptiveSubdivision was a limited count based subdivider
    so this exchanges that with an angle based one which gives much
    better results.
    
    Change-Id: I95c009ccf3d54305df0d8eef177cab0df0a23bea

diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx
index a3095ca..c259fef 100644
--- a/basegfx/source/polygon/b2dlinegeometry.cxx
+++ b/basegfx/source/polygon/b2dlinegeometry.cxx
@@ -779,35 +779,6 @@ namespace basegfx
 
     namespace tools
     {
-        B2DPolygon polygonSubdivide(const B2DPolygon& rCandidate, double fMaxAllowedAngle, double fMaxPartOfEdge)
-        {
-            if(fMaxAllowedAngle > F_PI2)
-            {
-                fMaxAllowedAngle = F_PI2;
-            }
-            else if(fMaxAllowedAngle < 0.01 * F_PI2)
-            {
-                fMaxAllowedAngle = 0.01 * F_PI2;
-            }
-
-            if(fMaxPartOfEdge > 1.0)
-            {
-                fMaxPartOfEdge = 1.0;
-            }
-            else if(fMaxPartOfEdge < 0.01)
-            {
-                fMaxPartOfEdge = 0.01;
-            }
-
-            B2DPolygon aCandidate(rCandidate);
-            const double fMaxCos(cos(fMaxAllowedAngle));
-
-            aCandidate.removeDoublePoints();
-            aCandidate = subdivideToSimple(aCandidate, fMaxCos * fMaxCos, fMaxPartOfEdge * fMaxPartOfEdge);
-
-            return aCandidate;
-        }
-
         B2DPolyPolygon createAreaGeometry(
             const B2DPolygon& rCandidate,
             double fHalfLineWidth,
diff --git a/basegfx/source/polygon/b2dpolygon.cxx b/basegfx/source/polygon/b2dpolygon.cxx
index f46c377..5ad06ea 100644
--- a/basegfx/source/polygon/b2dpolygon.cxx
+++ b/basegfx/source/polygon/b2dpolygon.cxx
@@ -483,7 +483,7 @@ public:
     {
         if(!mpDefaultSubdivision)
         {
-            const_cast< ImplBufferedData* >(this)->mpDefaultSubdivision.reset(new basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByCount(rSource, 9)));
+            const_cast< ImplBufferedData* >(this)->mpDefaultSubdivision.reset(new basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByAngle(rSource)));
         }
 
         return *mpDefaultSubdivision;
diff --git a/include/basegfx/polygon/b2dlinegeometry.hxx b/include/basegfx/polygon/b2dlinegeometry.hxx
index 0c9b7b1..cdcd322 100644
--- a/include/basegfx/polygon/b2dlinegeometry.hxx
+++ b/include/basegfx/polygon/b2dlinegeometry.hxx
@@ -139,11 +139,6 @@ namespace basegfx
             double fMaxPartOfEdge = 0.4,
             double fMiterMinimumAngle = (15.0 * F_PI180));
 
-        BASEGFX_DLLPUBLIC B2DPolygon polygonSubdivide(
-            const B2DPolygon& rCandidate,
-            double fMaxAllowedAngle = (12.5 * F_PI180),
-            double fMaxPartOfEdge = 0.4);
-
     } // end of namespace tools
 } // end of namespace basegfx
 
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 424f4be..2beb5fe 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -2045,9 +2045,7 @@ bool OpenGLSalGraphicsImpl::drawPolyLine(
         basegfx::B2DPolygon aPolygon(rPolygon);
 
         if (aPolygon.areControlPointsUsed())
-            aPolygon = basegfx::tools::polygonSubdivide(aPolygon, 7.5 * F_PI180);
-        else
-            aPolygon.removeDoublePoints();
+            aPolygon = aPolygon.getDefaultAdaptiveSubdivision();
 
         DrawPolyLine(aPolygon, fLineWidth, eLineJoin, eLineCap);
     }
commit 40b21ac06917976998d00dc4dd62b76628d1727b
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu May 12 13:37:11 2016 +0900

    opengl: track the state of blend, DrawArrays on OpenGLProgram
    
    This adds tracking of GL_BLEND and glBlendFunc which are usually
    set when setting up the current draw call on OpenGLProgram with
    SetBlendFunc method.
    
    Until now the final draw call (glDrawArrays) was called outside
    of OpenGLProgram. This is a problem because we need to know if
    we did call SetBlendFunc or not between when we used or reused
    the current program. So we added DrawArrays to OpenGLProgram and
    refactored all draw calls in OpenGLSalGraphicsImpl to use this.
    
    From now on glDrawArrays should not be called directly but always
    through OpenGLProgram.
    
    Change-Id: I530b4b948af8a962669a3751e1a95ff3986ffec9

diff --git a/vcl/inc/opengl/RenderState.hxx b/vcl/inc/opengl/RenderState.hxx
index ac215a8..2930ff1 100644
--- a/vcl/inc/opengl/RenderState.hxx
+++ b/vcl/inc/opengl/RenderState.hxx
@@ -117,11 +117,36 @@ public:
     static std::string className() { return std::string("StencilState"); }
 };
 
+class BlendState : public GenericCapabilityState<GL_BLEND, BlendState>
+{
+    GLenum mnSourceMode;
+    GLenum mnDestinationMode;
+public:
+    BlendState()
+        : mnSourceMode(GL_ZERO)
+        , mnDestinationMode(GL_ZERO)
+    {}
+
+    static std::string className() { return std::string("BlendState"); }
+
+    void func(GLenum nSource, GLenum nDestination)
+    {
+        if (mnSourceMode != nSource || mnDestinationMode != nDestination)
+        {
+            glBlendFunc(nSource, nDestination);
+            CHECK_GL_ERROR();
+            mnSourceMode = nSource;
+            mnDestinationMode = nDestination;
+        }
+    }
+};
+
 class RenderState
 {
     TextureState maTexture;
     ScissorState maScissor;
     StencilState maStencil;
+    BlendState   maBlend;
 
     Rectangle maCurrentViewport;
 
@@ -142,12 +167,14 @@ public:
     TextureState& texture() { return maTexture; }
     ScissorState& scissor() { return maScissor; }
     StencilState& stencil() { return maStencil; }
+    BlendState&   blend()   { return maBlend; }
 
     void sync()
     {
         VCL_GL_INFO("RenderState::sync");
         maScissor.sync();
         maStencil.sync();
+        maBlend.sync();
     }
 };
 
diff --git a/vcl/inc/opengl/program.hxx b/vcl/inc/opengl/program.hxx
index 780cba7..5944c72 100644
--- a/vcl/inc/opengl/program.hxx
+++ b/vcl/inc/opengl/program.hxx
@@ -51,9 +51,12 @@ public:
     OpenGLProgram();
     ~OpenGLProgram();
 
+    GLuint Id() { return mnId; }
+
     bool Load( const OUString& rVertexShader, const OUString& rFragmentShader,
                const rtl::OString& preamble = "", const rtl::OString& rDigest = "" );
     bool Use();
+    void Reuse();
     bool Clean();
 
     void SetVertices( const GLvoid* pData );
@@ -81,6 +84,8 @@ public:
 
     bool DrawTexture( const OpenGLTexture& rTexture );
 
+    void DrawArrays(GLenum GLenum, std::vector<GLfloat>& aVertices);
+
 protected:
     void SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData, GLint nSize = 2 );
     GLuint GetUniformLocation( const OString& rName );
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index c6139e8..424f4be 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -626,14 +626,12 @@ void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY )
 {
     OpenGLZone aZone;
 
-    GLfloat pPoint[2];
-
-    pPoint[0] = GLfloat(nX);
-    pPoint[1] = GLfloat(nY);
+    std::vector<GLfloat> pPoint {
+        GLfloat(nX), GLfloat(nY)
+    };
 
     ApplyProgramMatrices(0.5f);
-    mpProgram->SetVertices( pPoint );
-    glDrawArrays( GL_POINTS, 0, 1 );
+    mpProgram->DrawArrays(GL_POINTS, pPoint);
     CHECK_GL_ERROR();
 }
 
@@ -641,16 +639,13 @@ void OpenGLSalGraphicsImpl::DrawLine( double nX1, double nY1, double nX2, double
 {
     OpenGLZone aZone;
 
-    GLfloat pPoints[4];
-
-    pPoints[0] = GLfloat(nX1);
-    pPoints[1] = GLfloat(nY1);
-    pPoints[2] = GLfloat(nX2);
-    pPoints[3] = GLfloat(nY2);
+    std::vector<GLfloat> pPoint {
+        GLfloat(nX1), GLfloat(nY1),
+        GLfloat(nX2), GLfloat(nY2)
+    };
 
     ApplyProgramMatrices(0.5f);
-    mpProgram->SetVertices( pPoints );
-    glDrawArrays( GL_LINES, 0, 2 );
+    mpProgram->DrawArrays(GL_LINES, pPoint);
     CHECK_GL_ERROR();
 }
 
@@ -722,8 +717,7 @@ void OpenGLSalGraphicsImpl::DrawLineCap(float x1, float y1, float x2, float y2,
 
     ApplyProgramMatrices(0.0f);
     mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
-    mpProgram->SetVertices(aVertices.data());
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, aVertices.size() / 2);
+    mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aVertices);
 
     CHECK_GL_ERROR();
 }
@@ -749,8 +743,7 @@ void OpenGLSalGraphicsImpl::DrawLineSegment(float x1, float y1, float x2, float
 
     ApplyProgramMatrices(0.0f);
     mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
-    mpProgram->SetVertices(aPoints.data());
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, aPoints.size() / 2);
+    mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aPoints);
 
     CHECK_GL_ERROR();
 }
@@ -944,8 +937,7 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
 
         ApplyProgramMatrices(0.0f);
         mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
-        mpProgram->SetVertices(aVertices.data());
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, aVertices.size() / 2);
+        mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aVertices);
 
         CHECK_GL_ERROR();
     }
@@ -1109,7 +1101,7 @@ void OpenGLSalGraphicsImpl::ImplDrawLineAA( double nX1, double nY1, double nX2,
         tx = ty = 0;
     }
 
-    GLfloat vertices[]=
+    std::vector<GLfloat> vertices
     {
         GLfloat(x1-tx-Rx), GLfloat(y1-ty-Ry), //fading edge1
         GLfloat(x2-tx-Rx), GLfloat(y2-ty-Ry),
@@ -1124,8 +1116,7 @@ void OpenGLSalGraphicsImpl::ImplDrawLineAA( double nX1, double nY1, double nX2,
     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->SetVertices( vertices );
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+    mpProgram->DrawArrays(GL_TRIANGLE_STRIP, vertices);
     CHECK_GL_ERROR();
 }
 
@@ -1160,8 +1151,7 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoin
     }
 
     ApplyProgramMatrices();
-    mpProgram->SetVertices( &aVertices[0] );
-    glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
+    mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
     CHECK_GL_ERROR();
 
     if( !blockAA && mrParent.getAntiAliasB2DDraw())
@@ -1204,8 +1194,7 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( const tools::Polygon& rPolygon, b
     }
 
     ApplyProgramMatrices();
-    mpProgram->SetVertices( &aVertices[0] );
-    glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
+    mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
     CHECK_GL_ERROR();
 
     if( !blockAA && mrParent.getAntiAliasB2DDraw())
@@ -1255,8 +1244,7 @@ void OpenGLSalGraphicsImpl::DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoi
     }
 
     ApplyProgramMatrices();
-    mpProgram->SetVertices( &aVertices[0] );
-    glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
+    mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
     CHECK_GL_ERROR();
 
     if( !blockAA && mrParent.getAntiAliasB2DDraw())
@@ -1369,8 +1357,7 @@ void OpenGLSalGraphicsImpl::DrawRegionBand( const RegionBand& rRegion )
 #undef ADD_VERTICE
 
     ApplyProgramMatrices();
-    mpProgram->SetVertices( &aVertices[0] );
-    glDrawArrays( GL_TRIANGLES, 0, aVertices.size() / 2 );
+    mpProgram->DrawArrays(GL_TRIANGLES, aVertices);
     CHECK_GL_ERROR();
 }
 
@@ -1449,9 +1436,13 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
 {
     OpenGLZone aZone;
 
-    GLfloat aVertices[8] = {
-        0, (float) rTexture.GetHeight(), 0, 0,
-        (float) rTexture.GetWidth(), 0, (float) rTexture.GetWidth(), (float) rTexture.GetHeight() };
+    std::vector<GLfloat> aVertices = {
+        0, GLfloat(rTexture.GetHeight()),
+        0, 0,
+        GLfloat(rTexture.GetWidth()), 0,
+        GLfloat(rTexture.GetWidth()), GLfloat(rTexture.GetHeight())
+    };
+
     GLfloat aTexCoord[8];
 
     const long nDestWidth = basegfx::fround(basegfx::B2DVector(rX - rNull).getLength());
@@ -1587,8 +1578,7 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
     mpProgram->SetTexture("sampler", aInTexture);
     aInTexture.SetFilter(GL_LINEAR);
     mpProgram->SetTextureCoord( aTexCoord );
-    mpProgram->SetVertices( aVertices );
-    glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
+    mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
 
     CHECK_GL_ERROR();
     mpProgram->Clean();
@@ -1729,8 +1719,7 @@ void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
             TextureDrawParameters& rParameters = rColorTwoRectPair.second;
             ApplyProgramMatrices();
             mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
-            mpProgram->SetVertices(rParameters.maVertices.data());
-            glDrawArrays(GL_TRIANGLES, 0, rParameters.getNumberOfVertices());
+            mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
         }
     }
 #endif
@@ -1750,8 +1739,7 @@ void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
             TextureDrawParameters& rParameters = rColorTwoRectPair.second;
             ApplyProgramMatrices();
             mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
-            mpProgram->SetVertices(rParameters.maVertices.data());
-            glDrawArrays(GL_TRIANGLES, 0, rParameters.getNumberOfVertices());
+            mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
         }
     }
     mpProgram->Clean();
@@ -1919,20 +1907,15 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh
         GLfloat fX2(nX + nWidth - 1);
         GLfloat fY2(nY + nHeight - 1);
 
-        GLfloat pPoints[8];
-
-        pPoints[0] = fX1;
-        pPoints[1] = fY1;
-        pPoints[2] = fX2;
-        pPoints[3] = fY1;
-        pPoints[4] = fX2;
-        pPoints[5] = fY2;
-        pPoints[6] = fX1;
-        pPoints[7] = fY2;
+        std::vector<GLfloat> pPoints {
+            fX1, fY1,
+            fX2, fY1,
+            fX2, fY2,
+            fX1, fY2
+        };
 
         ApplyProgramMatrices(0.5f);
-        mpProgram->SetVertices(pPoints);
-        glDrawArrays(GL_LINE_LOOP, 0, 4);
+        mpProgram->DrawArrays(GL_LINE_LOOP, pPoints);
         CHECK_GL_ERROR();
     }
 
@@ -2288,13 +2271,15 @@ bool OpenGLSalGraphicsImpl::blendBitmap(
 
     VCL_GL_INFO( "::blendBitmap" );
     PreDraw();
-    glEnable( GL_BLEND );
-    CHECK_GL_ERROR();
-    glBlendFunc( GL_ZERO, GL_SRC_COLOR );
-    CHECK_GL_ERROR();
-    DrawTexture( rTexture, rPosAry );
-    glDisable( GL_BLEND );
-    CHECK_GL_ERROR();
+
+    if (!UseProgram("textureVertexShader", "textureFragmentShader"))
+        return true;
+
+    mpProgram->SetBlendMode(GL_ZERO, GL_SRC_COLOR);
+    mpProgram->SetTexture("sampler", rTexture);
+    DrawTextureRect(rTexture, rPosAry, false);
+    mpProgram->Clean();
+
     PostDraw();
     return true;
 }
@@ -2577,14 +2562,15 @@ void OpenGLSalGraphicsImpl::doFlush()
 
         GLfloat fWidth( maOffscreenTex.GetWidth() );
         GLfloat fHeight( maOffscreenTex.GetHeight() );
-        const GLfloat aVertices[] = { 0, fHeight,
-                                      0, 0,
-                                      fWidth, 0,
-                                      fWidth, fHeight };
+        std::vector<GLfloat> aVertices {
+            0, fHeight,
+            0, 0,
+            fWidth, 0,
+            fWidth, fHeight
+        };
 
         pProgram->ApplyMatrix(GetWidth(), GetHeight(), 0.0);
-        pProgram->SetVertices( &aVertices[0] );
-        glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
+        pProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
 
         pProgram->Clean();
 
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx
index eafd0c6..c095ad4 100644
--- a/vcl/opengl/program.cxx
+++ b/vcl/opengl/program.cxx
@@ -51,13 +51,19 @@ bool OpenGLProgram::Load( const OUString& rVertexShader,
     return ( mnId != 0 );
 }
 
+void OpenGLProgram::Reuse()
+{
+    mbBlending = false;
+}
+
 bool OpenGLProgram::Use()
 {
-    if( !mnId )
+    if (!mnId)
         return false;
 
-    glUseProgram( mnId );
+    glUseProgram(mnId);
     CHECK_GL_ERROR();
+    Reuse();
     return true;
 }
 
@@ -84,14 +90,6 @@ bool OpenGLProgram::Clean()
         mnEnabledAttribs = 0;
     }
 
-    // disable blending if enabled
-    if( mbBlending )
-    {
-        mbBlending = false;
-        glDisable( GL_BLEND );
-        CHECK_GL_ERROR();
-    }
-
     return true;
 }
 
@@ -151,6 +149,15 @@ GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
     return it->second;
 }
 
+void OpenGLProgram::DrawArrays(GLenum aMode, std::vector<GLfloat>& aVertices)
+{
+    if (!mbBlending)
+        OpenGLContext::getVCLContext()->state()->blend().disable();
+
+    SetVertices(aVertices.data());
+    glDrawArrays(aMode, 0, aVertices.size() / 2);
+}
+
 void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 )
 {
     GLuint nUniform = GetUniformLocation( rName );
@@ -301,12 +308,10 @@ void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset)
     CHECK_GL_ERROR();
 }
 
-void OpenGLProgram::SetBlendMode( GLenum nSFactor, GLenum nDFactor )
+void OpenGLProgram::SetBlendMode(GLenum nSFactor, GLenum nDFactor)
 {
-    glEnable( GL_BLEND );
-    CHECK_GL_ERROR();
-    glBlendFunc( nSFactor, nDFactor );
-    CHECK_GL_ERROR();
+    OpenGLContext::getVCLContext()->state()->blend().enable();
+    OpenGLContext::getVCLContext()->state()->blend().func(nSFactor, nDFactor);
     mbBlending = true;
 }
 
@@ -323,14 +328,18 @@ bool OpenGLProgram::DrawTexture( const OpenGLTexture& rTexture )
     float fMinY = 0.0f;
     float fMaxY = fHeight;
 
-    GLfloat aPosition[8] = { fMinX, fMaxY, fMinX, fMinY, fMaxX, fMinY, fMaxX, fMaxY };
+    std::vector<GLfloat> aPosition {
+        fMinX, fMaxY,
+        fMinX, fMinY,
+        fMaxX, fMinY,
+        fMaxX, fMaxY
+    };
     GLfloat aTexCoord[8];
 
     rTexture.GetWholeCoord( aTexCoord );
-    SetVertices( aPosition );
     SetTextureCoord( aTexCoord );
     ApplyMatrix(fWidth, fHeight);
-    glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
+    DrawArrays(GL_TRIANGLE_FAN, aPosition);
     CHECK_GL_ERROR();
 
     return true;
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 1ac5f4d..03d0a5d 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -1789,8 +1789,12 @@ OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const O
 
     OpenGLProgram* pProgram = GetProgram( rVertexShader, rFragmentShader, preamble );
 
-    if( pProgram == mpCurrentProgram )
+    if (pProgram == mpCurrentProgram)
+    {
+        VCL_GL_INFO("Context::UseProgram: Reusing existing program " << pProgram->Id());
+        pProgram->Reuse();
         return pProgram;
+    }
 
     mpCurrentProgram = pProgram;
 


More information about the Libreoffice-commits mailing list