[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-4.1' - drawinglayer/source include/drawinglayer include/svtools svtools/source
Kohei Yoshida
kohei.yoshida at collabora.com
Mon Jan 20 11:13:56 PST 2014
drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 319 ++++++++++++++-
include/drawinglayer/processor2d/vclpixelprocessor2d.hxx | 4
include/svtools/borderhelper.hxx | 2
svtools/source/control/ctrlbox.cxx | 7
4 files changed, 330 insertions(+), 2 deletions(-)
New commits:
commit ac40f13eebde508cce14b67d59dd36c2c18ccf7b
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Sat Jan 18 18:17:52 2014 -0500
fdo#73487: Better pixelization of lines for on-screen rendering.
Conflicts:
drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
Change-Id: I95d087a1f4841bfb7f665bcfebecd4c22c817958
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 85e17d9..bb21cf2 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>
@@ -51,12 +52,41 @@
#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>
//////////////////////////////////////////////////////////////////////////////
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;
+}
+
+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
{
@@ -126,6 +156,287 @@ namespace drawinglayer
return true;
}
+ bool VclPixelProcessor2D::tryDrawBorderLinePrimitive2DDirect(
+ const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource)
+ {
+ const basegfx::B2DPoint& rS = rSource.getStart();
+ const basegfx::B2DPoint& rE = rSource.getEnd();
+
+ double fX1 = rS.getX();
+ double fY1 = rS.getY();
+ 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:
+ 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)
+ {
+ // Horizontal line. Draw it as a rectangle.
+
+ aTarget = makeRectPolygon(fX1, fY1, fX2-fX1, nThick);
+ aTarget.transform(maCurrentTransformation);
+
+ basegfx::B2DRange aRange = aTarget.getB2DRange();
+ double fH = aRange.getHeight();
+
+ 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;
+ }
+ }
+ else
+ {
+ // Vertical line. Draw it as a rectangle.
+
+ aTarget = makeRectPolygon(fX1, fY1, nThick, fY2-fY1);
+ aTarget.transform(maCurrentTransformation);
+
+ basegfx::B2DRange aRange = aTarget.getB2DRange();
+ double fW = aRange.getWidth();
+
+ 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;
+ }
+ }
+
+ 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:
+ {
+ std::vector<double> aPattern =
+ svtools::GetLineDashing(rSource.getStyle(), rSource.getPatternScale()*10.0);
+
+ if (aPattern.empty())
+ // Failed to get pattern values.
+ 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);
+ aRange.transform(maCurrentTransformation);
+ fX1 = aRange.getMinX();
+ fX2 = aRange.getMaxX();
+ fY1 = aRange.getMinY();
+ fY2 = aRange.getMaxY();
+
+ basegfx::B2DPolyPolygon aTarget;
+
+ if (bHorizontal)
+ {
+ // 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();
+ for (; it != itEnd; ++it)
+ aDashes.append(makeRectPolygon(0, 0, *it, nThick));
+
+ aDashes.transform(maCurrentTransformation);
+ rtl::math::setNan(&nThick);
+
+ // 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);
+ 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());
+
+ aDashesPix.append(makeRectPolygon(0, 0, fW, nThick));
+ }
+
+ // Make all dash polygons and render them.
+ 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;
+
+ 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.
+ fX += aRange.getWidth();
+
+ ++i;
+ if (i >= n)
+ i = 0;
+ }
+ }
+ else
+ {
+ // 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();
+ for (; it != itEnd; ++it)
+ aDashes.append(makeRectPolygon(0, 0, nThick, *it));
+
+ aDashes.transform(maCurrentTransformation);
+ rtl::math::setNan(&nThick);
+
+ // 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 (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());
+
+ 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;
+
+ 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.
+ fY += aRange.getHeight();
+
+ ++i;
+ if (i >= n)
+ i = 0;
+ }
+ }
+
+ mpOutputDevice->SetFillColor(Color(aLineColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolyPolygon(aTarget);
+
+ return true;
+ }
+ break;
+ default:
+ ;
+ }
+ return false;
+ }
+
void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
{
switch(rCandidate.getPrimitive2DID())
@@ -665,7 +976,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/include/drawinglayer/processor2d/vclpixelprocessor2d.hxx b/include/drawinglayer/processor2d/vclpixelprocessor2d.hxx
index ecd91b6..7e10de4 100644
--- a/include/drawinglayer/processor2d/vclpixelprocessor2d.hxx
+++ b/include/drawinglayer/processor2d/vclpixelprocessor2d.hxx
@@ -31,8 +31,11 @@
namespace drawinglayer
{
+ namespace primitive2d { class BorderLinePrimitive2D; }
+
namespace processor2d
{
+
/** VclPixelProcessor2D class
This processor derived from VclProcessor2D is the base class for rendering
@@ -53,6 +56,7 @@ namespace drawinglayer
// some helpers to try direct paints (shortcuts)
bool tryDrawPolyPolygonColorPrimitive2DDirect(const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D& rSource, double fTransparency);
+ bool tryDrawBorderLinePrimitive2DDirect(const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource);
public:
/// constructor/destructor
diff --git a/include/svtools/borderhelper.hxx b/include/svtools/borderhelper.hxx
index dac540c..c405ba5 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 67336bd..ab78c4b 100644
--- a/svtools/source/control/ctrlbox.cxx
+++ b/svtools/source/control/ctrlbox.cxx
@@ -638,6 +638,13 @@ namespace svtools
return aPattern;
}
+ 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