[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