diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-01-18 23:02:05 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-01-20 14:37:02 -0500 |
commit | ec1a3157c1851dcb481f402ec25aa38fa9e7c51c (patch) | |
tree | 8f5deeb7c3a636a79106c0de4054d202368c64ac /drawinglayer | |
parent | 6a3fb868b2b8af21f7b6140424b6f8377599a786 (diff) |
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
Diffstat (limited to 'drawinglayer')
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 177 |
1 files changed, 140 insertions, 37 deletions
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 97a67910f7e7..f1429a1e4384 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; } |