[Libreoffice-commits] core.git: Branch 'feature/calc-cell-borders' - drawinglayer/source include/svtools svtools/source

Kohei Yoshida kohei.yoshida at collabora.com
Sat Jan 18 20:00:56 PST 2014


Rebased ref, commits from common ancestor:
commit 0c89bc6aec5204cb7a7ce2d725ff60e6dea0c9e2
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 80de8e5..3e2021b 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);


More information about the Libreoffice-commits mailing list