[Libreoffice-commits] core.git: 9 commits - drawinglayer/source include/svtools sc/qa svtools/source

Kohei Yoshida kohei.yoshida at collabora.com
Mon Jan 20 11:36:08 PST 2014


 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx |  319 +++++++++++++++-
 drawinglayer/source/processor2d/vclpixelprocessor2d.hxx |    2 
 include/svtools/borderhelper.hxx                        |    2 
 sc/qa/unit/data/xls/cell-borders.xls                    |binary
 svtools/source/control/ctrlbox.cxx                      |   10 
 5 files changed, 331 insertions(+), 2 deletions(-)

New commits:
commit 4b2b4133c2bd750a4b71230433dba0e41ced0abe
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 12:30:11 2014 -0500

    Handle double lines for screen rendering.
    
    Double lines are always drawn as 2 parallel hair lines that are 1 pixel
    apart, at any zoom level.
    
    Change-Id: I2796477d0ea45c9880aa8057bd1a10104df96673

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 439ce61..61145f5 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -297,11 +297,14 @@ namespace drawinglayer
             switch (rSource.getStyle())
             {
                 case table::BorderLineStyle::SOLID:
+                case table::BorderLineStyle::DOUBLE:
                 {
                     const basegfx::BColor aLineColor =
                         maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
                     double nThick = rtl::math::round(rSource.getLeftWidth());
 
+                    bool bDouble = rSource.getStyle() == table::BorderLineStyle::DOUBLE;
+
                     basegfx::B2DPolygon aTarget;
 
                     if (bHorizontal)
@@ -314,12 +317,20 @@ namespace drawinglayer
                         basegfx::B2DRange aRange = aTarget.getB2DRange();
                         double fH = aRange.getHeight();
 
-                        if (fH <= 1.0)
+                        if (fH <= 1.0 || bDouble)
                         {
                             // Draw it as a line.
                             drawHairLine(
                                 mpOutputDevice, aRange.getMinX(), aRange.getMinY(), aRange.getMaxX(), aRange.getMinY(),
                                 aLineColor);
+
+                            if (bDouble)
+                            {
+                                drawHairLine(
+                                    mpOutputDevice, aRange.getMinX(), aRange.getMinY()+2.0, aRange.getMaxX(), aRange.getMinY()+2.0,
+                                    aLineColor);
+                            }
+
                             return true;
                         }
                     }
@@ -333,12 +344,19 @@ namespace drawinglayer
                         basegfx::B2DRange aRange = aTarget.getB2DRange();
                         double fW = aRange.getWidth();
 
-                        if (fW <= 1.0)
+                        if (fW <= 1.0 || bDouble)
                         {
                             // Draw it as a line.
                             drawHairLine(
                                 mpOutputDevice, aRange.getMinX(), aRange.getMinY(), aRange.getMinX(), aRange.getMaxY(),
                                 aLineColor);
+
+                            if (bDouble)
+                            {
+                                drawHairLine(
+                                    mpOutputDevice, aRange.getMinX()+2.0, aRange.getMinY(), aRange.getMinX()+2.0, aRange.getMaxY(),
+                                    aLineColor);
+                            }
                             return true;
                         }
                     }
commit 01104522ef890bb535994311e627ba1bbfff023c
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 12:03:39 2014 -0500

    Ensure that the pixel line is at least 1 pixel wide.
    
    Without this, some dashed lines may not get drawn at all at some zoom levels.
    
    Change-Id: I273c1548325d14f56618df8ca4166aac58a3ff3f

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index ce22687..439ce61 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -430,7 +430,12 @@ namespace drawinglayer
                                 if (fX + fBlockW > fX2)
                                     // Clip the right end in case it spills over the range.
                                     fBlockW = fX2 - fX + 1;
-                                aTarget.append(makeRectPolygon(fX, fY1, fBlockW, aRange.getHeight()));
+
+                                double fH = aRange.getHeight();
+                                if (basegfx::fTools::equalZero(fH))
+                                    fH = 1.0;
+
+                                aTarget.append(makeRectPolygon(fX, fY1, fBlockW, fH));
                             }
 
                             bLine = !bLine; // line and blank alternate.
@@ -497,7 +502,12 @@ namespace drawinglayer
                                 if (fY + fBlockH > fY2)
                                     // Clip the bottom end in case it spills over the range.
                                     fBlockH = fY2 - fY + 1;
-                                aTarget.append(makeRectPolygon(fX1, fY, aRange.getWidth(), fBlockH));
+
+                                double fW = aRange.getWidth();
+                                if (basegfx::fTools::equalZero(fW))
+                                    fW = 1.0;
+
+                                aTarget.append(makeRectPolygon(fX1, fY, fW, fBlockH));
                             }
 
                             bLine = !bLine; // line and blank alternate.
commit 41bee5b83102760a6da7eaca3b770e4c4e310d4d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 11:48:36 2014 -0500

    Do the same when the pixel thickness is zero.
    
    Change-Id: Icfbb295abb19cf58477f4f14f4a7294a540151c2

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 68abfa4..ce22687 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -378,6 +378,13 @@ namespace drawinglayer
                     {
                         // Horizontal line.
 
+                        if (basegfx::fTools::equalZero(nThick))
+                        {
+                            // Dash line segment too small to draw.  Substitute it with a solid line.
+                            drawHairLine(mpOutputDevice, fX1, fY1, fX2, fY1, aLineColor);
+                            return true;
+                        }
+
                         // Create a dash unit polygon set.
                         basegfx::B2DPolyPolygon aDashes;
                         std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end();
@@ -438,6 +445,13 @@ namespace drawinglayer
                     {
                         // Vertical line.
 
+                        if (basegfx::fTools::equalZero(nThick))
+                        {
+                            // Dash line segment too small to draw.  Substitute it with a solid line.
+                            drawHairLine(mpOutputDevice, fX1, fY1, fX1, fY2, aLineColor);
+                            return true;
+                        }
+
                         // Create a dash unit polygon set.
                         basegfx::B2DPolyPolygon aDashes;
                         std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end();
commit 30f97564f86ff2fff3e682a14191db0d841df0cf
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 11:41:41 2014 -0500

    Substitute dashed line with a solid line at lower zoom levels.
    
    Change-Id: I0437409b6a5d6163fadf777df5c028950727e786

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 06ca763..68abfa4 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -73,6 +73,19 @@ basegfx::B2DPolygon makeRectPolygon( double fX, double fY, double fW, double fH
     return aPoly;
 }
 
+void drawHairLine(
+    OutputDevice* pOutDev, double fX1, double fY1, double fX2, double fY2,
+    const basegfx::BColor& rColor )
+{
+    basegfx::B2DPolygon aTarget;
+    aTarget.append(basegfx::B2DPoint(fX1, fY1));
+    aTarget.append(basegfx::B2DPoint(fX2, fY2));
+
+    pOutDev->SetFillColor();
+    pOutDev->SetLineColor(Color(rColor));
+    pOutDev->DrawPolyLine(aTarget);
+}
+
 }
 
 namespace drawinglayer
@@ -289,7 +302,6 @@ namespace drawinglayer
                         maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
                     double nThick = rtl::math::round(rSource.getLeftWidth());
 
-                    bool bAsLine = false;
                     basegfx::B2DPolygon aTarget;
 
                     if (bHorizontal)
@@ -305,10 +317,10 @@ namespace drawinglayer
                         if (fH <= 1.0)
                         {
                             // Draw it as a line.
-                            aTarget.clear();
-                            aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
-                            aTarget.append(basegfx::B2DPoint(aRange.getMaxX(), aRange.getMinY()));
-                            bAsLine = true;
+                            drawHairLine(
+                                mpOutputDevice, aRange.getMinX(), aRange.getMinY(), aRange.getMaxX(), aRange.getMinY(),
+                                aLineColor);
+                            return true;
                         }
                     }
                     else
@@ -324,25 +336,16 @@ namespace drawinglayer
                         if (fW <= 1.0)
                         {
                             // Draw it as a line.
-                            aTarget.clear();
-                            aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
-                            aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMaxY()));
-                            bAsLine = true;
+                            drawHairLine(
+                                mpOutputDevice, aRange.getMinX(), aRange.getMinY(), aRange.getMinX(), aRange.getMaxY(),
+                                aLineColor);
+                            return true;
                         }
                     }
 
-                    if (bAsLine)
-                    {
-                        mpOutputDevice->SetFillColor();
-                        mpOutputDevice->SetLineColor(Color(aLineColor));
-                        mpOutputDevice->DrawPolyLine(aTarget);
-                    }
-                    else
-                    {
-                        mpOutputDevice->SetFillColor(Color(aLineColor));
-                        mpOutputDevice->SetLineColor();
-                        mpOutputDevice->DrawPolygon(aTarget);
-                    }
+                    mpOutputDevice->SetFillColor(Color(aLineColor));
+                    mpOutputDevice->SetLineColor();
+                    mpOutputDevice->DrawPolygon(aTarget);
                     return true;
                 }
                 break;
@@ -358,6 +361,8 @@ namespace drawinglayer
                         return false;
 
                     double nThick = rtl::math::round(rSource.getLeftWidth());
+                    const basegfx::BColor aLineColor =
+                        maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
 
                     // Transform the current line range before using it for rendering.
                     basegfx::B2DRange aRange(fX1, fY1, fX2, fY2);
@@ -391,6 +396,13 @@ namespace drawinglayer
                             basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i);
                             aRange = aPoly.getB2DRange();
                             double fW = rtl::math::round(aRange.getWidth());
+                            if (basegfx::fTools::equalZero(fW))
+                            {
+                                // Dash line segment too small to draw.  Substitute it with a solid line.
+                                drawHairLine(mpOutputDevice, fX1, fY1, fX2, fY1, aLineColor);
+                                return true;
+                            }
+
                             if (rtl::math::isNan(nThick))
                                 nThick = rtl::math::round(aRange.getHeight());
 
@@ -444,6 +456,13 @@ namespace drawinglayer
                             basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i);
                             aRange = aPoly.getB2DRange();
                             double fH = rtl::math::round(aRange.getHeight());
+                            if (basegfx::fTools::equalZero(fH))
+                            {
+                                // Dash line segment too small to draw.  Substitute it with a solid line.
+                                drawHairLine(mpOutputDevice, fX1, fY1, fX1, fY2, aLineColor);
+                                return true;
+                            }
+
                             if (rtl::math::isNan(nThick))
                                 nThick = rtl::math::round(aRange.getWidth());
 
@@ -476,8 +495,6 @@ namespace drawinglayer
                         }
                     }
 
-                    const basegfx::BColor aLineColor =
-                        maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
                     mpOutputDevice->SetFillColor(Color(aLineColor));
                     mpOutputDevice->SetLineColor();
                     mpOutputDevice->DrawPolyPolygon(aTarget);
commit ae22838d2ff4d388e97c30317a6a9f83e652a06a
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 11:10:52 2014 -0500

    Better on-screen drawing of vertical dashed lines.
    
    Change-Id: I53d5f8b0278d1228cd941221a07cd360943c5ce6

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index d037d0c..06ca763 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -267,6 +267,20 @@ namespace drawinglayer
             double fX2 = rE.getX();
             double fY2 = rE.getY();
 
+            bool bHorizontal = false;
+            if (fX1 == fX2)
+            {
+                // Vertical line.
+            }
+            else if (fY1 == fY2)
+            {
+                // Horizontal line.
+                bHorizontal = true;
+            }
+            else
+                // Neither.  Bail out.
+                return false;
+
             switch (rSource.getStyle())
             {
                 case table::BorderLineStyle::SOLID:
@@ -275,14 +289,12 @@ namespace drawinglayer
                         maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
                     double nThick = rtl::math::round(rSource.getLeftWidth());
 
-                    bool bDraw = false;
                     bool bAsLine = false;
                     basegfx::B2DPolygon aTarget;
 
-                    if (fY1 == fY2)
+                    if (bHorizontal)
                     {
                         // Horizontal line.  Draw it as a rectangle.
-                        bDraw = true;
 
                         aTarget = makeRectPolygon(fX1, fY1, fX2-fX1, nThick);
                         aTarget.transform(maCurrentTransformation);
@@ -299,10 +311,9 @@ namespace drawinglayer
                             bAsLine = true;
                         }
                     }
-                    else if (fX1 == fX2)
+                    else
                     {
                         // Vertical line.  Draw it as a rectangle.
-                        bDraw = true;
 
                         aTarget = makeRectPolygon(fX1, fY1, nThick, fY2-fY1);
                         aTarget.transform(maCurrentTransformation);
@@ -320,9 +331,6 @@ namespace drawinglayer
                         }
                     }
 
-                    if (!bDraw)
-                        return false;
-
                     if (bAsLine)
                     {
                         mpOutputDevice->SetFillColor();
@@ -342,30 +350,37 @@ namespace drawinglayer
                 case table::BorderLineStyle::DASHED:
                 case table::BorderLineStyle::FINE_DASHED:
                 {
-                    double fH = rtl::math::round(rSource.getLeftWidth());
+                    std::vector<double> aPattern =
+                        svtools::GetLineDashing(rSource.getStyle(), rSource.getPatternScale()*10.0);
 
-                    if (fY1 == fY2)
-                    {
-                        // Horizontal line.
+                    if (aPattern.empty())
+                        // Failed to get pattern values.
+                        return false;
 
-                        basegfx::B2DPolyPolygon aDashes;
-                        std::vector<double> aPattern =
-                            svtools::GetLineDashing(rSource.getStyle(), rSource.getPatternScale()*10.0);
+                    double nThick = rtl::math::round(rSource.getLeftWidth());
+
+                    // Transform the current line range before using it for rendering.
+                    basegfx::B2DRange aRange(fX1, fY1, fX2, fY2);
+                    aRange.transform(maCurrentTransformation);
+                    fX1 = aRange.getMinX();
+                    fX2 = aRange.getMaxX();
+                    fY1 = aRange.getMinY();
+                    fY2 = aRange.getMaxY();
 
-                        if (aPattern.empty())
-                            // Failed to get pattern values.
-                            return false;
+                    basegfx::B2DPolyPolygon aTarget;
+
+                    if (bHorizontal)
+                    {
+                        // Horizontal line.
 
                         // Create a dash unit polygon set.
+                        basegfx::B2DPolyPolygon aDashes;
                         std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end();
                         for (; it != itEnd; ++it)
-                        {
-                            double fW = *it;
-                            aDashes.append(makeRectPolygon(0, 0, fW, fH));
-                        }
+                            aDashes.append(makeRectPolygon(0, 0, *it, nThick));
 
                         aDashes.transform(maCurrentTransformation);
-                        rtl::math::setNan(&fH);
+                        rtl::math::setNan(&nThick);
 
                         // Pixelize the dash unit.  We use the same height for
                         // all dash polygons.
@@ -374,24 +389,15 @@ namespace drawinglayer
                         for (sal_uInt32 i = 0, n = aDashes.count(); i < n; ++i)
                         {
                             basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i);
-                            basegfx::B2DRange aRange = aPoly.getB2DRange();
+                            aRange = aPoly.getB2DRange();
                             double fW = rtl::math::round(aRange.getWidth());
-                            if (rtl::math::isNan(fH))
-                                fH = rtl::math::round(aRange.getHeight());
+                            if (rtl::math::isNan(nThick))
+                                nThick = rtl::math::round(aRange.getHeight());
 
-                            aDashesPix.append(makeRectPolygon(0, 0, fW, fH));
+                            aDashesPix.append(makeRectPolygon(0, 0, fW, nThick));
                         }
 
-                        // Transform the current line range before using it for rendering.
-                        basegfx::B2DRange aRange(fX1, fY1, fX2, fY2);
-                        aRange.transform(maCurrentTransformation);
-                        fX1 = aRange.getMinX();
-                        fX2 = aRange.getMaxX();
-                        fY1 = aRange.getMinY();
-                        fY2 = aRange.getMaxY();
-
                         // Make all dash polygons and render them.
-                        basegfx::B2DPolyPolygon aTarget;
                         double fX = fX1;
                         bool bLine = true;
                         sal_uInt32 i = 0, n = aDashesPix.count();
@@ -415,16 +421,68 @@ namespace drawinglayer
                             if (i >= n)
                                 i = 0;
                         }
+                    }
+                    else
+                    {
+                        // Vertical line.
 
-                        const basegfx::BColor aLineColor =
-                            maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
-                        mpOutputDevice->SetFillColor(Color(aLineColor));
-                        mpOutputDevice->SetLineColor();
+                        // Create a dash unit polygon set.
+                        basegfx::B2DPolyPolygon aDashes;
+                        std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end();
+                        for (; it != itEnd; ++it)
+                            aDashes.append(makeRectPolygon(0, 0, nThick, *it));
 
-                        mpOutputDevice->DrawPolyPolygon(aTarget);
+                        aDashes.transform(maCurrentTransformation);
+                        rtl::math::setNan(&nThick);
 
-                        return true;
+                        // Pixelize the dash unit.  We use the same width for
+                        // all dash polygons.
+                        basegfx::B2DPolyPolygon aDashesPix;
+
+                        for (sal_uInt32 i = 0, n = aDashes.count(); i < n; ++i)
+                        {
+                            basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i);
+                            aRange = aPoly.getB2DRange();
+                            double fH = rtl::math::round(aRange.getHeight());
+                            if (rtl::math::isNan(nThick))
+                                nThick = rtl::math::round(aRange.getWidth());
+
+                            aDashesPix.append(makeRectPolygon(0, 0, nThick, fH));
+                        }
+
+                        // Make all dash polygons and render them.
+                        double fY = fY1;
+                        bool bLine = true;
+                        sal_uInt32 i = 0, n = aDashesPix.count();
+                        while (fY <= fY2)
+                        {
+                            basegfx::B2DPolygon aPoly = aDashesPix.getB2DPolygon(i);
+                            aRange = aPoly.getB2DRange();
+                            if (bLine)
+                            {
+                                double fBlockH = aRange.getHeight();
+                                if (fY + fBlockH > fY2)
+                                    // Clip the bottom end in case it spills over the range.
+                                    fBlockH = fY2 - fY + 1;
+                                aTarget.append(makeRectPolygon(fX1, fY, aRange.getWidth(), fBlockH));
+                            }
+
+                            bLine = !bLine; // line and blank alternate.
+                            fY += aRange.getHeight();
+
+                            ++i;
+                            if (i >= n)
+                                i = 0;
+                        }
                     }
+
+                    const basegfx::BColor aLineColor =
+                        maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
+                    mpOutputDevice->SetFillColor(Color(aLineColor));
+                    mpOutputDevice->SetLineColor();
+                    mpOutputDevice->DrawPolyPolygon(aTarget);
+
+                    return true;
                 }
                 break;
                 default:
commit b3b57c7a3a43a056217c72716d18bdeced029b66
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 10:12:53 2014 -0500

    Same solid line treatment for vertical lines during on-screen drawing.
    
    Change-Id: Idb352dc2afeb2ee7b48620c972c2a186209228ea

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index f1429a1..d037d0c 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -271,15 +271,20 @@ namespace drawinglayer
             {
                 case table::BorderLineStyle::SOLID:
                 {
+                    const basegfx::BColor aLineColor =
+                        maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
+                    double nThick = rtl::math::round(rSource.getLeftWidth());
+
+                    bool bDraw = false;
+                    bool bAsLine = false;
+                    basegfx::B2DPolygon aTarget;
+
                     if (fY1 == fY2)
                     {
                         // Horizontal line.  Draw it as a rectangle.
+                        bDraw = true;
 
-                        const basegfx::BColor aLineColor =
-                            maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
-                        double nThick = rtl::math::round(rSource.getLeftWidth());
-
-                        basegfx::B2DPolygon aTarget = makeRectPolygon(fX1, fY1, fX2-fX1, nThick);
+                        aTarget = makeRectPolygon(fX1, fY1, fX2-fX1, nThick);
                         aTarget.transform(maCurrentTransformation);
 
                         basegfx::B2DRange aRange = aTarget.getB2DRange();
@@ -291,20 +296,46 @@ namespace drawinglayer
                             aTarget.clear();
                             aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
                             aTarget.append(basegfx::B2DPoint(aRange.getMaxX(), aRange.getMinY()));
+                            bAsLine = true;
+                        }
+                    }
+                    else if (fX1 == fX2)
+                    {
+                        // Vertical line.  Draw it as a rectangle.
+                        bDraw = true;
+
+                        aTarget = makeRectPolygon(fX1, fY1, nThick, fY2-fY1);
+                        aTarget.transform(maCurrentTransformation);
 
-                            mpOutputDevice->SetFillColor();
-                            mpOutputDevice->SetLineColor(Color(aLineColor));
+                        basegfx::B2DRange aRange = aTarget.getB2DRange();
+                        double fW = aRange.getWidth();
 
-                            mpOutputDevice->DrawPolyLine(aTarget);
-                            return true;
+                        if (fW <= 1.0)
+                        {
+                            // Draw it as a line.
+                            aTarget.clear();
+                            aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
+                            aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMaxY()));
+                            bAsLine = true;
                         }
+                    }
+
+                    if (!bDraw)
+                        return false;
 
+                    if (bAsLine)
+                    {
+                        mpOutputDevice->SetFillColor();
+                        mpOutputDevice->SetLineColor(Color(aLineColor));
+                        mpOutputDevice->DrawPolyLine(aTarget);
+                    }
+                    else
+                    {
                         mpOutputDevice->SetFillColor(Color(aLineColor));
                         mpOutputDevice->SetLineColor();
-
                         mpOutputDevice->DrawPolygon(aTarget);
-                        return true;
                     }
+                    return true;
                 }
                 break;
                 case table::BorderLineStyle::DOTTED:
commit 82599357ae6066b002ca2bd2b7060b26e51ba00f
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Jan 20 10:04:26 2014 -0500

    Add vertical lines for testing.
    
    Change-Id: I93d3613547b74a37cebbb6e791e0d23ea405401b

diff --git a/sc/qa/unit/data/xls/cell-borders.xls b/sc/qa/unit/data/xls/cell-borders.xls
index 87d6cf9..5bdf57f 100644
Binary files a/sc/qa/unit/data/xls/cell-borders.xls and b/sc/qa/unit/data/xls/cell-borders.xls differ
commit ec1a3157c1851dcb481f402ec25aa38fa9e7c51c
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Sat Jan 18 23:02:05 2014 -0500

    Better pixelization of dashed lines for screen rendering.
    
    Now the dashed lines are evenly placed on screen.  For now, horizontal lines
    only.  I'll work on vertical lines later.
    
    Change-Id: I474e9c8214e5f079ea2cfca12b35381d8fcf2ae1

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 97a6791..f1429a1 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -52,6 +52,7 @@
 #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
 #include <toolkit/helper/vclunohelper.hxx>
 #include <vcl/window.hxx>
+#include <svtools/borderhelper.hxx>
 
 #include <com/sun/star/table/BorderLineStyle.hpp>
 
@@ -59,7 +60,20 @@
 
 using namespace com::sun::star;
 
-//////////////////////////////////////////////////////////////////////////////
+namespace {
+
+basegfx::B2DPolygon makeRectPolygon( double fX, double fY, double fW, double fH )
+{
+    basegfx::B2DPolygon aPoly;
+    aPoly.append(basegfx::B2DPoint(fX, fY));
+    aPoly.append(basegfx::B2DPoint(fX+fW, fY));
+    aPoly.append(basegfx::B2DPoint(fX+fW, fY+fH));
+    aPoly.append(basegfx::B2DPoint(fX, fY+fH));
+    aPoly.setClosed(true);
+    return aPoly;
+}
+
+}
 
 namespace drawinglayer
 {
@@ -245,56 +259,145 @@ namespace drawinglayer
         bool VclPixelProcessor2D::tryDrawBorderLinePrimitive2DDirect(
             const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource)
         {
-            if (rSource.getStyle() == table::BorderLineStyle::SOLID)
-            {
-                const basegfx::B2DPoint& rS = rSource.getStart();
-                const basegfx::B2DPoint& rE = rSource.getEnd();
+            const basegfx::B2DPoint& rS = rSource.getStart();
+            const basegfx::B2DPoint& rE = rSource.getEnd();
 
-                double nX1 = rS.getX();
-                double nY1 = rS.getY();
-                double nX2 = rE.getX();
-                double nY2 = rE.getY();
+            double fX1 = rS.getX();
+            double fY1 = rS.getY();
+            double fX2 = rE.getX();
+            double fY2 = rE.getY();
 
-                if (nY1 == nY2)
+            switch (rSource.getStyle())
+            {
+                case table::BorderLineStyle::SOLID:
                 {
-                    // Horizontal line.  Draw it as a rectangle.
-                    basegfx::B2DPolygon aTarget;
+                    if (fY1 == fY2)
+                    {
+                        // Horizontal line.  Draw it as a rectangle.
 
-                    const basegfx::BColor aLineColor =
-                        maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
-                    double nThick = rtl::math::round(rSource.getLeftWidth());
+                        const basegfx::BColor aLineColor =
+                            maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
+                        double nThick = rtl::math::round(rSource.getLeftWidth());
 
-                    aTarget.append(basegfx::B2DPoint(nX1, nY1));
-                    aTarget.append(basegfx::B2DPoint(nX2, nY1));
-                    aTarget.append(basegfx::B2DPoint(nX2, nY1+nThick));
-                    aTarget.append(basegfx::B2DPoint(nX1, nY1+nThick));
-                    aTarget.setClosed(true);
-                    aTarget.transform(maCurrentTransformation);
+                        basegfx::B2DPolygon aTarget = makeRectPolygon(fX1, fY1, fX2-fX1, nThick);
+                        aTarget.transform(maCurrentTransformation);
 
-                    basegfx::B2DRange aRange = aTarget.getB2DRange();
-                    double fH = aRange.getHeight();
+                        basegfx::B2DRange aRange = aTarget.getB2DRange();
+                        double fH = aRange.getHeight();
 
-                    if (fH <= 1.0)
-                    {
-                        // Draw it as a line.
-                        aTarget.clear();
-                        aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
-                        aTarget.append(basegfx::B2DPoint(aRange.getMaxX(), aRange.getMinY()));
+                        if (fH <= 1.0)
+                        {
+                            // Draw it as a line.
+                            aTarget.clear();
+                            aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
+                            aTarget.append(basegfx::B2DPoint(aRange.getMaxX(), aRange.getMinY()));
 
-                        mpOutputDevice->SetFillColor();
-                        mpOutputDevice->SetLineColor(Color(aLineColor));
+                            mpOutputDevice->SetFillColor();
+                            mpOutputDevice->SetLineColor(Color(aLineColor));
 
-                        mpOutputDevice->DrawPolyLine(aTarget);
+                            mpOutputDevice->DrawPolyLine(aTarget);
+                            return true;
+                        }
+
+                        mpOutputDevice->SetFillColor(Color(aLineColor));
+                        mpOutputDevice->SetLineColor();
+
+                        mpOutputDevice->DrawPolygon(aTarget);
                         return true;
                     }
+                }
+                break;
+                case table::BorderLineStyle::DOTTED:
+                case table::BorderLineStyle::DASHED:
+                case table::BorderLineStyle::FINE_DASHED:
+                {
+                    double fH = rtl::math::round(rSource.getLeftWidth());
 
-                    mpOutputDevice->SetFillColor(Color(aLineColor));
-                    mpOutputDevice->SetLineColor();
+                    if (fY1 == fY2)
+                    {
+                        // Horizontal line.
 
-                    mpOutputDevice->DrawPolygon(aTarget);
-                    return true;
-                }
+                        basegfx::B2DPolyPolygon aDashes;
+                        std::vector<double> aPattern =
+                            svtools::GetLineDashing(rSource.getStyle(), rSource.getPatternScale()*10.0);
+
+                        if (aPattern.empty())
+                            // Failed to get pattern values.
+                            return false;
+
+                        // Create a dash unit polygon set.
+                        std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end();
+                        for (; it != itEnd; ++it)
+                        {
+                            double fW = *it;
+                            aDashes.append(makeRectPolygon(0, 0, fW, fH));
+                        }
+
+                        aDashes.transform(maCurrentTransformation);
+                        rtl::math::setNan(&fH);
+
+                        // Pixelize the dash unit.  We use the same height for
+                        // all dash polygons.
+                        basegfx::B2DPolyPolygon aDashesPix;
+
+                        for (sal_uInt32 i = 0, n = aDashes.count(); i < n; ++i)
+                        {
+                            basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i);
+                            basegfx::B2DRange aRange = aPoly.getB2DRange();
+                            double fW = rtl::math::round(aRange.getWidth());
+                            if (rtl::math::isNan(fH))
+                                fH = rtl::math::round(aRange.getHeight());
 
+                            aDashesPix.append(makeRectPolygon(0, 0, fW, fH));
+                        }
+
+                        // Transform the current line range before using it for rendering.
+                        basegfx::B2DRange aRange(fX1, fY1, fX2, fY2);
+                        aRange.transform(maCurrentTransformation);
+                        fX1 = aRange.getMinX();
+                        fX2 = aRange.getMaxX();
+                        fY1 = aRange.getMinY();
+                        fY2 = aRange.getMaxY();
+
+                        // Make all dash polygons and render them.
+                        basegfx::B2DPolyPolygon aTarget;
+                        double fX = fX1;
+                        bool bLine = true;
+                        sal_uInt32 i = 0, n = aDashesPix.count();
+                        while (fX <= fX2)
+                        {
+                            basegfx::B2DPolygon aPoly = aDashesPix.getB2DPolygon(i);
+                            aRange = aPoly.getB2DRange();
+                            if (bLine)
+                            {
+                                double fBlockW = aRange.getWidth();
+                                if (fX + fBlockW > fX2)
+                                    // Clip the right end in case it spills over the range.
+                                    fBlockW = fX2 - fX + 1;
+                                aTarget.append(makeRectPolygon(fX, fY1, fBlockW, aRange.getHeight()));
+                            }
+
+                            bLine = !bLine; // line and blank alternate.
+                            fX += aRange.getWidth();
+
+                            ++i;
+                            if (i >= n)
+                                i = 0;
+                        }
+
+                        const basegfx::BColor aLineColor =
+                            maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
+                        mpOutputDevice->SetFillColor(Color(aLineColor));
+                        mpOutputDevice->SetLineColor();
+
+                        mpOutputDevice->DrawPolyPolygon(aTarget);
+
+                        return true;
+                    }
+                }
+                break;
+                default:
+                    ;
             }
             return false;
         }
diff --git a/include/svtools/borderhelper.hxx b/include/svtools/borderhelper.hxx
index a1eb77b..5e4328d 100644
--- a/include/svtools/borderhelper.hxx
+++ b/include/svtools/borderhelper.hxx
@@ -29,6 +29,8 @@
 
 namespace svtools {
 
+SVT_DLLPUBLIC std::vector<double> GetLineDashing( sal_uInt16 nDashing, double fScale );
+
 SVT_DLLPUBLIC basegfx::B2DPolyPolygon ApplyLineDashing(
     const basegfx::B2DPolygon& rPolygon, sal_uInt16 nDashing, double fScale );
 
diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx
index b77b737..47012cd 100644
--- a/svtools/source/control/ctrlbox.cxx
+++ b/svtools/source/control/ctrlbox.cxx
@@ -586,6 +586,9 @@ void lclDrawPolygon( OutputDevice& rDev, const basegfx::B2DPolygon& rPolygon, lo
 
 namespace svtools {
 
+/**
+ * Dashing array must start with a line width and end with a blank width.
+ */
 std::vector<double> GetDashing( sal_uInt16 nDashing )
 {
     std::vector<double> aPattern;
@@ -625,6 +628,13 @@ public:
 
 }
 
+std::vector<double> GetLineDashing( sal_uInt16 nDashing, double fScale )
+{
+    std::vector<double> aPattern = GetDashing(nDashing);
+    std::for_each(aPattern.begin(), aPattern.end(), ApplyScale(fScale));
+    return aPattern;
+}
+
 basegfx::B2DPolyPolygon ApplyLineDashing( const basegfx::B2DPolygon& rPolygon, sal_uInt16 nDashing, double fScale )
 {
     std::vector<double> aPattern = GetDashing(nDashing);
commit 6a3fb868b2b8af21f7b6140424b6f8377599a786
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Sat Jan 18 18:17:52 2014 -0500

    Draw horizontal solid border lines directly in the pixel processor.
    
    This makes slightly skinnier solid lines which look better on screen.
    
    Change-Id: Ia7764be4a53d1dd6bb60ecb3ba5c8966403e4e6c

diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 9b020f7..97a6791 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -34,6 +34,7 @@
 #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
 #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
+#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
 #include <com/sun/star/awt/XWindow2.hpp>
 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
 #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
@@ -52,6 +53,8 @@
 #include <toolkit/helper/vclunohelper.hxx>
 #include <vcl/window.hxx>
 
+#include <com/sun/star/table/BorderLineStyle.hpp>
+
 //////////////////////////////////////////////////////////////////////////////
 
 using namespace com::sun::star;
@@ -239,6 +242,63 @@ namespace drawinglayer
             return bTryWorked;
         }
 
+        bool VclPixelProcessor2D::tryDrawBorderLinePrimitive2DDirect(
+            const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource)
+        {
+            if (rSource.getStyle() == table::BorderLineStyle::SOLID)
+            {
+                const basegfx::B2DPoint& rS = rSource.getStart();
+                const basegfx::B2DPoint& rE = rSource.getEnd();
+
+                double nX1 = rS.getX();
+                double nY1 = rS.getY();
+                double nX2 = rE.getX();
+                double nY2 = rE.getY();
+
+                if (nY1 == nY2)
+                {
+                    // Horizontal line.  Draw it as a rectangle.
+                    basegfx::B2DPolygon aTarget;
+
+                    const basegfx::BColor aLineColor =
+                        maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft());
+                    double nThick = rtl::math::round(rSource.getLeftWidth());
+
+                    aTarget.append(basegfx::B2DPoint(nX1, nY1));
+                    aTarget.append(basegfx::B2DPoint(nX2, nY1));
+                    aTarget.append(basegfx::B2DPoint(nX2, nY1+nThick));
+                    aTarget.append(basegfx::B2DPoint(nX1, nY1+nThick));
+                    aTarget.setClosed(true);
+                    aTarget.transform(maCurrentTransformation);
+
+                    basegfx::B2DRange aRange = aTarget.getB2DRange();
+                    double fH = aRange.getHeight();
+
+                    if (fH <= 1.0)
+                    {
+                        // Draw it as a line.
+                        aTarget.clear();
+                        aTarget.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()));
+                        aTarget.append(basegfx::B2DPoint(aRange.getMaxX(), aRange.getMinY()));
+
+                        mpOutputDevice->SetFillColor();
+                        mpOutputDevice->SetLineColor(Color(aLineColor));
+
+                        mpOutputDevice->DrawPolyLine(aTarget);
+                        return true;
+                    }
+
+                    mpOutputDevice->SetFillColor(Color(aLineColor));
+                    mpOutputDevice->SetLineColor();
+
+                    mpOutputDevice->DrawPolygon(aTarget);
+                    return true;
+                }
+
+            }
+            return false;
+        }
+
         void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
         {
             switch(rCandidate.getPrimitive2DID())
@@ -851,7 +911,11 @@ namespace drawinglayer
                     sal_uInt16 nAntiAliasing = mpOutputDevice->GetAntialiasing();
                     mpOutputDevice->SetAntialiasing(nAntiAliasing & ~ANTIALIASING_ENABLE_B2DDRAW);
 
-                    process(rCandidate.get2DDecomposition(getViewInformation2D()));
+                    const drawinglayer::primitive2d::BorderLinePrimitive2D& rBorder =
+                        static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D&>(rCandidate);
+
+                    if (!tryDrawBorderLinePrimitive2DDirect(rBorder))
+                        process(rCandidate.get2DDecomposition(getViewInformation2D()));
 
                     mpOutputDevice->SetAntialiasing(nAntiAliasing);
                     break;
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
index a55962d..c9c2d742 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
@@ -34,6 +34,7 @@ namespace drawinglayer { namespace primitive2d {
     class PolyPolygonColorPrimitive2D;
     class PolygonHairlinePrimitive2D;
     class PolygonStrokePrimitive2D;
+    class BorderLinePrimitive2D;
 }}
 
 //////////////////////////////////////////////////////////////////////////////
@@ -64,6 +65,7 @@ namespace drawinglayer
             bool tryDrawPolyPolygonColorPrimitive2DDirect(const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D& rSource, double fTransparency);
             bool tryDrawPolygonHairlinePrimitive2DDirect(const drawinglayer::primitive2d::PolygonHairlinePrimitive2D& rSource, double fTransparency);
             bool tryDrawPolygonStrokePrimitive2DDirect(const drawinglayer::primitive2d::PolygonStrokePrimitive2D& rSource, double fTransparency);
+            bool tryDrawBorderLinePrimitive2DDirect(const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource);
 
         public:
             /// constructor/destructor


More information about the Libreoffice-commits mailing list