[Libreoffice-commits] core.git: vcl/backendtest vcl/inc vcl/qa vcl/skia

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Tue May 26 13:56:14 UTC 2020


 vcl/backendtest/VisualBackendTest.cxx   |    9 ++-
 vcl/backendtest/outputdevice/common.cxx |    5 +
 vcl/backendtest/outputdevice/line.cxx   |   87 ++++++++++++++++++++++++++++++++
 vcl/inc/skia/gdiimpl.hxx                |    6 +-
 vcl/inc/test/outputdevice.hxx           |    4 +
 vcl/qa/cppunit/BackendTest.cxx          |   12 ++++
 vcl/skia/gdiimpl.cxx                    |   41 ++++-----------
 7 files changed, 131 insertions(+), 33 deletions(-)

New commits:
commit 3a93748c9c4faadeb9ab4eb21706d187677549fa
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue May 26 11:03:06 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue May 26 15:55:37 2020 +0200

    use Skia to do dashed lines, no need to do it manually (tdf#130431)
    
    Change-Id: Id5efe7227f3c2bcb5ef6f1b990327e72014e8c47
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94857
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/vcl/backendtest/VisualBackendTest.cxx b/vcl/backendtest/VisualBackendTest.cxx
index 5daa9a642d55..08efc1d381a3 100644
--- a/vcl/backendtest/VisualBackendTest.cxx
+++ b/vcl/backendtest/VisualBackendTest.cxx
@@ -576,7 +576,7 @@ public:
         }
         else if (mnTest % gnNumberOfTests == 7)
         {
-            std::vector<tools::Rectangle> aRegions = setupRegions(3, 1, nWidth, nHeight);
+            std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight);
 
             aRectangle = aRegions[index++];
             {
@@ -586,6 +586,13 @@ public:
                 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
             }
             aRectangle = aRegions[index++];
+            {
+                vcl::test::OutputDeviceTestLine aOutDevTest;
+                Bitmap aBitmap = aOutDevTest.setupDashedLine();
+                assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkDashedLine(aBitmap), aRectangle, rRenderContext);
+                drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+            }
+            aRectangle = aRegions[index++];
             {
                 vcl::test::OutputDeviceTestGradient aOutDevTest;
                 Bitmap aBitmap = aOutDevTest.setupLinearGradient();
diff --git a/vcl/backendtest/outputdevice/common.cxx b/vcl/backendtest/outputdevice/common.cxx
index f9052fb77201..a5d032315474 100644
--- a/vcl/backendtest/outputdevice/common.cxx
+++ b/vcl/backendtest/outputdevice/common.cxx
@@ -416,6 +416,11 @@ TestResult OutputDeviceTestCommon::checkRectangles(Bitmap& aBitmap, std::vector<
     return aReturnValue;
 }
 
+TestResult OutputDeviceTestCommon::checkRectangle(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor)
+{
+    return checkRect(rBitmap, aLayerNumber, aExpectedColor);
+}
+
 tools::Rectangle OutputDeviceTestCommon::alignToCenter(tools::Rectangle aRect1, tools::Rectangle aRect2)
 {
     Point aPoint((aRect1.GetWidth()  / 2.0) - (aRect2.GetWidth()  / 2.0),
diff --git a/vcl/backendtest/outputdevice/line.cxx b/vcl/backendtest/outputdevice/line.cxx
index b9236dcc210d..5b5d73261135 100644
--- a/vcl/backendtest/outputdevice/line.cxx
+++ b/vcl/backendtest/outputdevice/line.cxx
@@ -10,6 +10,11 @@
 
 #include <test/outputdevice.hxx>
 
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <vcl/bitmapaccess.hxx>
+
+#include <list>
+
 namespace vcl::test {
 
 namespace
@@ -108,6 +113,88 @@ Bitmap OutputDeviceTestLine::setupAALines()
     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
 }
 
+Bitmap OutputDeviceTestLine::setupDashedLine()
+{
+    initialSetup(13, 13, constBackgroundColor);
+
+    mpVirtualDevice->SetLineColor(constLineColor);
+    mpVirtualDevice->SetFillColor();
+
+    tools::Rectangle rectangle = maVDRectangle;
+    rectangle.shrink(2);
+
+    std::vector stroke({ 2.0, 1.0 });
+    mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(),
+        basegfx::B2DPolygon{
+            basegfx::B2DPoint(rectangle.getX(), rectangle.getY()),
+            basegfx::B2DPoint(rectangle.getX(), rectangle.getY() + rectangle.getHeight()),
+            basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(),
+                              rectangle.getY() + rectangle.getHeight()),
+            basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(), rectangle.getY()),
+            basegfx::B2DPoint(rectangle.getX(), rectangle.getY())},
+        1, 0, &stroke, basegfx::B2DLineJoin::NONE, css::drawing::LineCap_BUTT, basegfx::deg2rad(15.0), true );
+
+    return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+TestResult OutputDeviceTestLine::checkDashedLine(Bitmap& rBitmap)
+{
+    TestResult returnValue = TestResult::Passed;
+    for (int i = 0; i < 7; i++)
+    {
+        TestResult eResult = TestResult::Passed;
+        if( i == 2 )
+        {
+            // Build a sequence of pixels for the drawn rectangle border,
+            // check that they alternate appropriately (there should be
+            // normally 2 line, 1 background).
+            std::list< bool > dash; // true - line color, false - background
+            const int width = rBitmap.GetSizePixel().Width();
+            const int height = rBitmap.GetSizePixel().Height();
+            BitmapReadAccess access(rBitmap);
+            for( int x = 2; x < width - 2; ++x )
+                dash.push_back( access.GetPixel( 2, x ) == constLineColor );
+            for( int y = 3; y < height - 3; ++y )
+                dash.push_back( access.GetPixel( y, width - 3 ) == constLineColor );
+            for( int x = width - 3; x >= 2; --x )
+                dash.push_back( access.GetPixel( height - 3, x ) == constLineColor );
+            for( int y = height - 4; y >= 3; --y )
+                dash.push_back( access.GetPixel( y, 2 ) == constLineColor );
+            for( int x = 2; x < width - 2; ++x ) // repeat, to check also the corner
+                dash.push_back( access.GetPixel( 2, x ) == constLineColor );
+            bool last = false;
+            int lastCount = 0;
+            while( !dash.empty())
+            {
+                if( dash.front() == last )
+                {
+                    ++lastCount;
+                    if( lastCount > ( last ? 4 : 3 ))
+                        eResult = TestResult::Failed;
+                    else if( lastCount > ( last ? 3 : 2 ) && eResult != TestResult::Failed)
+                        eResult = TestResult::PassedWithQuirks;
+                }
+                else
+                {
+                    last = dash.front();
+                    lastCount = 1;
+                }
+                dash.pop_front();
+            }
+        }
+        else
+        {
+            eResult = OutputDeviceTestCommon::checkRectangle(rBitmap, i, constBackgroundColor);
+        }
+
+        if (eResult == TestResult::Failed)
+            returnValue = TestResult::Failed;
+        if (eResult == TestResult::PassedWithQuirks && returnValue != TestResult::Failed)
+            returnValue = TestResult::PassedWithQuirks;
+    }
+    return returnValue;
+}
+
 } // end namespace vcl::test
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index c78845fe6ffa..eb5fbdbdcbf8 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -104,9 +104,9 @@ public:
 
     virtual bool drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
                               const basegfx::B2DPolygon&, double fTransparency, double fLineWidth,
-                              const std::vector<double>* pStroke, // MM01
-                              basegfx::B2DLineJoin, css::drawing::LineCap,
-                              double fMiterMinimumAngle, bool bPixelSnapHairline) override;
+                              const std::vector<double>* pStroke, basegfx::B2DLineJoin,
+                              css::drawing::LineCap, double fMiterMinimumAngle,
+                              bool bPixelSnapHairline) override;
 
     virtual bool drawPolyLineBezier(sal_uInt32 nPoints, const SalPoint* pPtAry,
                                     const PolyFlags* pFlgAry) override;
diff --git a/vcl/inc/test/outputdevice.hxx b/vcl/inc/test/outputdevice.hxx
index b6cf70c22bd0..b8ad0b67fc6b 100644
--- a/vcl/inc/test/outputdevice.hxx
+++ b/vcl/inc/test/outputdevice.hxx
@@ -60,6 +60,7 @@ public:
     static TestResult checkInvertTrackFrameRectangle(Bitmap& aBitmap);
 
     static TestResult checkRectangles(Bitmap& rBitmap, std::vector<Color>& aExpectedColors);
+    static TestResult checkRectangle(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor);
 
     static TestResult checkFilled(Bitmap& rBitmap, tools::Rectangle aRectangle, Color aExpectedColor);
     static TestResult checkChecker(Bitmap& rBitmap, sal_Int32 nStartX, sal_Int32 nEndX,
@@ -125,6 +126,9 @@ public:
     Bitmap setupDiamond();
     Bitmap setupLines();
     Bitmap setupAALines();
+
+    Bitmap setupDashedLine();
+    static TestResult checkDashedLine(Bitmap& rBitmap);
 };
 
 class VCL_DLLPUBLIC OutputDeviceTestPolyLine : public OutputDeviceTestCommon
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx
index b34dda5262ec..ff4ed0d87251 100644
--- a/vcl/qa/cppunit/BackendTest.cxx
+++ b/vcl/qa/cppunit/BackendTest.cxx
@@ -495,6 +495,16 @@ public:
             CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
     }
 
+    void testDashedLine()
+    {
+        vcl::test::OutputDeviceTestLine aOutDevTest;
+        Bitmap aBitmap = aOutDevTest.setupDashedLine();
+        auto eResult = vcl::test::OutputDeviceTestLine::checkDashedLine(aBitmap);
+        exportImage("10-01_dashed_line_test.png", aBitmap);
+        if (SHOULD_ASSERT)
+            CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+    }
+
     void testTdf124848()
     {
         ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
@@ -575,6 +585,8 @@ public:
     CPPUNIT_TEST(testClipPolyPolygon);
     CPPUNIT_TEST(testClipB2DPolyPolygon);
 
+    CPPUNIT_TEST(testDashedLine);
+
     CPPUNIT_TEST(testTdf124848);
 
     CPPUNIT_TEST_SUITE_END();
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index a2ccb12d406d..b5b9aad6ae22 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -644,10 +644,8 @@ void SkiaSalGraphicsImpl::drawPolyLine(sal_uInt32 nPoints, const SalPoint* pPtAr
         aPolygon.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY));
     aPolygon.setClosed(false);
 
-    drawPolyLine(basegfx::B2DHomMatrix(), aPolygon, 0.0, 1.0,
-                 nullptr, // MM01
-                 basegfx::B2DLineJoin::Miter, css::drawing::LineCap_BUTT,
-                 basegfx::deg2rad(15.0) /*default*/, false);
+    drawPolyLine(basegfx::B2DHomMatrix(), aPolygon, 0.0, 1.0, nullptr, basegfx::B2DLineJoin::Miter,
+                 css::drawing::LineCap_BUTT, basegfx::deg2rad(15.0) /*default*/, false);
 }
 
 void SkiaSalGraphicsImpl::drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry)
@@ -736,13 +734,11 @@ bool SkiaSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectTo
 
 bool SkiaSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
                                        const basegfx::B2DPolygon& rPolyLine, double fTransparency,
-                                       double fLineWidth,
-                                       const std::vector<double>* pStroke, // MM01
+                                       double fLineWidth, const std::vector<double>* pStroke,
                                        basegfx::B2DLineJoin eLineJoin,
                                        css::drawing::LineCap eLineCap, double fMiterMinimumAngle,
                                        bool bPixelSnapHairline)
 {
-    // MM01 check done for simple reasons
     if (!rPolyLine.count() || fTransparency < 0.0 || fTransparency > 1.0
         || mLineColor == SALCOLOR_NONE)
     {
@@ -758,29 +754,9 @@ bool SkiaSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDev
     else // Adjust line width for object-to-device scale.
         fLineWidth = (rObjectToDevice * basegfx::B2DVector(fLineWidth, 0)).getLength();
 
-    // MM01 need to do line dashing as fallback stuff here now
-    const double fDotDashLength(
-        nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
-    const bool bStrokeUsed(0.0 != fDotDashLength);
-    assert(!bStrokeUsed || (bStrokeUsed && pStroke));
-    basegfx::B2DPolyPolygon aPolyPolygonLine;
-
-    if (bStrokeUsed)
-    {
-        // apply LineStyle
-        basegfx::utils::applyLineDashing(rPolyLine, // source
-                                         *pStroke, // pattern
-                                         &aPolyPolygonLine, // target for lines
-                                         nullptr, // target for gaps
-                                         fDotDashLength); // full length if available
-    }
-    else
-    {
-        // no line dashing, just copy
-        aPolyPolygonLine.append(rPolyLine);
-    }
-
     // Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
+    basegfx::B2DPolyPolygon aPolyPolygonLine;
+    aPolyPolygonLine.append(rPolyLine);
     aPolyPolygonLine.transform(rObjectToDevice);
     if (bPixelSnapHairline)
     {
@@ -831,6 +807,13 @@ bool SkiaSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDev
     aPaint.setStrokeWidth(fLineWidth);
     aPaint.setAntiAlias(mParent.getAntiAliasB2DDraw());
 
+    if (pStroke && std::accumulate(pStroke->begin(), pStroke->end(), 0.0) != 0)
+    {
+        std::vector<SkScalar> intervals;
+        intervals.assign(pStroke->begin(), pStroke->end());
+        aPaint.setPathEffect(SkDashPathEffect::Make(intervals.data(), intervals.size(), 0));
+    }
+
     // Skia does not support basegfx::B2DLineJoin::NONE, so in that case batch only if lines
     // are not wider than a pixel.
     if (eLineJoin != basegfx::B2DLineJoin::NONE || fLineWidth <= 1.0)


More information about the Libreoffice-commits mailing list