summaryrefslogtreecommitdiffstats
path: root/vcl
diff options
context:
space:
mode:
authorArmin Le Grand (Collabora) <Armin.Le.Grand@me.com>2020-02-06 18:53:12 +0100
committerTor Lillqvist <tml@collabora.com>2020-02-11 07:19:01 +0100
commitc069861bf9a32c826cbc86a086a774eba49c4e6f (patch)
treeaa4e543b4f8fe795daaee315694e18b10b848e99 /vcl
parenttdf#129519 Fix crash during WebDAV lock refresh (diff)
downloadcore-c069861bf9a32c826cbc86a086a774eba49c4e6f.tar.gz
core-c069861bf9a32c826cbc86a086a774eba49c4e6f.zip
tdf#130478 Enhance Dashed line drawing on all systems
For more info and explanation including state of process information and discussion(s) see task please. Adding corrections for gerrit build Cherry-picked 5f61c9fe99ac93087b898adddbb4d4733f1fcd07: Adaptions made and checked that Caio fat line draw works as expected. Surprisingly some new files were created which I removed here again. Also needs to be cherry-picked is: 9c9f76dd5b6fb115e521ac6568673c7a10879192 which will enable direct dash paint for Cairo. Not done here due to not sure if I can do two cherry-picks in one run and it's lust a view lines, so -compared to this one- should be not difficult. Change-Id: Ie10fb8093a86459dee80db5ab4355b47e46c1f8c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88130 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88284 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Tor Lillqvist <tml@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/headless/svpgdi.cxx172
-rw-r--r--vcl/inc/headless/svpgdi.hxx2
-rw-r--r--vcl/inc/openglgdiimpl.hxx1
-rwxr-xr-x[-rw-r--r--]vcl/inc/qt5/Qt5Graphics.hxx7
-rw-r--r--vcl/inc/quartz/salgdi.h1
-rw-r--r--vcl/inc/salgdi.hxx2
-rw-r--r--vcl/inc/salgdiimpl.hxx1
-rw-r--r--vcl/inc/unx/genpspgraphics.h1
-rw-r--r--vcl/inc/unx/salgdi.h1
-rw-r--r--vcl/inc/win/salgdi.h1
-rw-r--r--vcl/opengl/gdiimpl.cxx70
-rwxr-xr-x[-rw-r--r--]vcl/qt5/Qt5Graphics_GDI.cxx50
-rw-r--r--vcl/quartz/salgdicommon.cxx66
-rwxr-xr-x[-rw-r--r--]vcl/source/gdi/FileDefinitionWidgetDraw.cxx4
-rw-r--r--vcl/source/gdi/salgdilayout.cxx4
-rw-r--r--vcl/source/outdev/line.cxx2
-rw-r--r--vcl/source/outdev/polygon.cxx3
-rw-r--r--vcl/source/outdev/polyline.cxx5
-rw-r--r--vcl/source/outdev/transparent.cxx2
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.cxx84
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.hxx1
-rw-r--r--vcl/unx/generic/gdi/salgdi.cxx3
-rw-r--r--vcl/unx/generic/print/genpspgraphics.cxx1
-rw-r--r--vcl/win/gdi/gdiimpl.cxx103
-rw-r--r--vcl/win/gdi/gdiimpl.hxx1
-rw-r--r--vcl/win/gdi/salgdi_gdiplus.cxx2
26 files changed, 456 insertions, 134 deletions
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index c4453c7f4560..8dcdcc5df44c 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -20,6 +20,8 @@
#include <config_features.h>
#include <memory>
+#include <numeric>
+
#ifndef IOS
#include <headless/svpgdi.hxx>
#endif
@@ -789,6 +791,7 @@ void SvpSalGraphics::drawPolyLine(sal_uInt32 nPoints, const SalPoint* pPtAry)
aPoly,
0.0,
basegfx::B2DVector(1.0, 1.0),
+ nullptr, // MM01
basegfx::B2DLineJoin::Miter,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0) /*default*/,
@@ -1057,18 +1060,22 @@ private:
// need to be compared with to check for data validity
bool mbNoJoin;
bool mbAntiAliasB2DDraw;
+ std::vector< double > maStroke;
public:
SystemDependentData_CairoPath(
basegfx::SystemDependentDataManager& rSystemDependentDataManager,
cairo_path_t* pCairoPath,
bool bNoJoin,
- bool bAntiAliasB2DDraw);
+ bool bAntiAliasB2DDraw,
+ const std::vector< double >* pStroke); // MM01
virtual ~SystemDependentData_CairoPath() override;
+ // read access
cairo_path_t* getCairoPath() { return mpCairoPath; }
bool getNoJoin() const { return mbNoJoin; }
bool getAntiAliasB2DDraw() const { return mbAntiAliasB2DDraw; }
+ const std::vector< double >& getStroke() const { return maStroke; }
virtual sal_Int64 estimateUsageInBytes() const override;
};
@@ -1077,12 +1084,18 @@ SystemDependentData_CairoPath::SystemDependentData_CairoPath(
basegfx::SystemDependentDataManager& rSystemDependentDataManager,
cairo_path_t* pCairoPath,
bool bNoJoin,
- bool bAntiAliasB2DDraw)
+ bool bAntiAliasB2DDraw,
+ const std::vector< double >* pStroke)
: basegfx::SystemDependentData(rSystemDependentDataManager),
mpCairoPath(pCairoPath),
mbNoJoin(bNoJoin),
- mbAntiAliasB2DDraw(bAntiAliasB2DDraw)
+ mbAntiAliasB2DDraw(bAntiAliasB2DDraw),
+ maStroke()
{
+ if(nullptr != pStroke)
+ {
+ maStroke = *pStroke;
+ }
}
SystemDependentData_CairoPath::~SystemDependentData_CairoPath()
@@ -1114,7 +1127,8 @@ bool SvpSalGraphics::drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon& rPolyLine,
double fTransparency,
- const basegfx::B2DVector& rLineWidths,
+ const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -1145,7 +1159,8 @@ bool SvpSalGraphics::drawPolyLine(
rObjectToDevice,
rPolyLine,
fTransparency,
- rLineWidths,
+ rLineWidth,
+ pStroke, // MM01
eLineJoin,
eLineCap,
fMiterMinimumAngle,
@@ -1167,7 +1182,8 @@ bool SvpSalGraphics::drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon& rPolyLine,
double fTransparency,
- const basegfx::B2DVector& rLineWidths,
+ const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -1180,10 +1196,10 @@ bool SvpSalGraphics::drawPolyLine(
}
// need to check/handle LineWidth when ObjectToDevice transformation is used
- basegfx::B2DVector aLineWidths(rLineWidths);
+ basegfx::B2DVector aLineWidth(rLineWidth);
const bool bObjectToDeviceIsIdentity(rObjectToDevice.isIdentity());
- const basegfx::B2DVector aDeviceLineWidths(bObjectToDeviceIsIdentity ? rLineWidths : rObjectToDevice * rLineWidths);
- const bool bCorrectLineWidth(!bObjectToDeviceIsIdentity && aDeviceLineWidths.getX() < 1.0 && aLineWidths.getX() >= 1.0);
+ const basegfx::B2DVector aDeviceLineWidth(bObjectToDeviceIsIdentity ? rLineWidth : rObjectToDevice * rLineWidth);
+ const bool bCorrectLineWidth(!bObjectToDeviceIsIdentity && aDeviceLineWidth.getX() < 1.0 && aLineWidth.getX() >= 1.0);
// on-demand inverse of ObjectToDevice transformation
basegfx::B2DHomMatrix aObjectToDeviceInv;
@@ -1197,7 +1213,7 @@ bool SvpSalGraphics::drawPolyLine(
}
// calculate-back logical LineWidth for a hairline
- aLineWidths = aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0);
+ aLineWidth = aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0);
}
// PixelOffset used: Need to reflect in linear transformation
@@ -1227,8 +1243,6 @@ bool SvpSalGraphics::drawPolyLine(
// set linear transformation
cairo_set_matrix(cr, &aMatrix);
- const bool bNoJoin((basegfx::B2DLineJoin::NONE == eLineJoin && basegfx::fTools::more(aLineWidths.getX(), 0.0)));
-
// setup line attributes
cairo_line_join_t eCairoLineJoin = CAIRO_LINE_JOIN_MITER;
switch (eLineJoin)
@@ -1279,78 +1293,118 @@ bool SvpSalGraphics::drawPolyLine(
cairo_set_line_join(cr, eCairoLineJoin);
cairo_set_line_cap(cr, eCairoLineCap);
- cairo_set_line_width(cr, aLineWidths.getX());
+ cairo_set_line_width(cr, aLineWidth.getX());
cairo_set_miter_limit(cr, fMiterLimit);
- bool bDone = false;
- bool bIsTrivial = isTrivial(rPolyLine);
+ // try to access buffered data
+ const bool bIsTrivial(isTrivial(rPolyLine));
+ std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
+ bIsTrivial ? nullptr : rPolyLine.getSystemDependentData<SystemDependentData_CairoPath>());
- if (!bIsTrivial)
+ // MM01 need to do line dashing as fallback stuff here now
+ const double fDotDashLength(nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
+ const bool bStrokeUsed(0.0 != fDotDashLength);
+
+ if(pSystemDependentData_CairoPath)
{
- // try to access buffered data
- std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
- rPolyLine.getSystemDependentData<SystemDependentData_CairoPath>());
+ // MM01 - check on stroke change. Used against not used, or if both used,
+ // equal or different?
+ const bool bStrokeWasUsed(!pSystemDependentData_CairoPath->getStroke().empty());
- if(pSystemDependentData_CairoPath)
+ if(bStrokeWasUsed != bStrokeUsed
+ || (bStrokeUsed && *pStroke != pSystemDependentData_CairoPath->getStroke()))
{
- // check data validity
- if(nullptr == pSystemDependentData_CairoPath->getCairoPath()
- || pSystemDependentData_CairoPath->getNoJoin() != bNoJoin
- || pSystemDependentData_CairoPath->getAntiAliasB2DDraw() != bAntiAliasB2DDraw
- || bPixelSnapHairline /*tdf#124700*/ )
- {
- // data invalid, forget
- pSystemDependentData_CairoPath.reset();
- }
+ // data invalid, forget
+ pSystemDependentData_CairoPath.reset();
}
+ }
- if(pSystemDependentData_CairoPath)
+ // check for basegfx::B2DLineJoin::NONE to react accordingly
+ const bool bNoJoin((basegfx::B2DLineJoin::NONE == eLineJoin
+ && basegfx::fTools::more(aLineWidth.getX(), 0.0)));
+
+ if(pSystemDependentData_CairoPath)
+ {
+ // check data validity
+ if(nullptr == pSystemDependentData_CairoPath->getCairoPath()
+ || pSystemDependentData_CairoPath->getNoJoin() != bNoJoin
+ || pSystemDependentData_CairoPath->getAntiAliasB2DDraw() != bAntiAliasB2DDraw
+ || bPixelSnapHairline /*tdf#124700*/ )
{
- // re-use data
- cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
- bDone = true;
+ // data invalid, forget
+ pSystemDependentData_CairoPath.reset();
}
}
- if (!bDone)
+ if(pSystemDependentData_CairoPath)
+ {
+ // re-use data
+ cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
+ }
+ else
{
// create data
- if (!bNoJoin)
+ // MM01 need to do line dashing as fallback stuff here now
+ basegfx::B2DPolyPolygon aPolyPolygonLine;
+
+ if(bStrokeUsed)
{
- // PixelOffset now reflected in linear transformation used
- AddPolygonToPath(
- cr,
- rPolyLine,
- rObjectToDevice, // ObjectToDevice *without* LineDraw-Offset
- !bAntiAliasB2DDraw,
- bPixelSnapHairline);
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(
+ rPolyLine, // source
+ *pStroke, // pattern
+ &aPolyPolygonLine, // traget for lines
+ nullptr, // target for gaps
+ fDotDashLength); // full length if available
}
else
{
- const sal_uInt32 nPointCount(rPolyLine.count());
- const sal_uInt32 nEdgeCount(rPolyLine.isClosed() ? nPointCount : nPointCount - 1);
- basegfx::B2DPolygon aEdge;
+ // no line dashing, just copy
+ aPolyPolygonLine.append(rPolyLine);
+ }
- aEdge.append(rPolyLine.getB2DPoint(0));
- aEdge.append(basegfx::B2DPoint(0.0, 0.0));
+ // MM01 checked/verified for Cairo
+ for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
+ {
+ const basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a));
- for (sal_uInt32 i(0); i < nEdgeCount; i++)
+ if (!bNoJoin)
{
- const sal_uInt32 nNextIndex((i + 1) % nPointCount);
- aEdge.setB2DPoint(1, rPolyLine.getB2DPoint(nNextIndex));
- aEdge.setNextControlPoint(0, rPolyLine.getNextControlPoint(i));
- aEdge.setPrevControlPoint(1, rPolyLine.getPrevControlPoint(nNextIndex));
-
// PixelOffset now reflected in linear transformation used
AddPolygonToPath(
cr,
- aEdge,
+ aPolyLine,
rObjectToDevice, // ObjectToDevice *without* LineDraw-Offset
!bAntiAliasB2DDraw,
bPixelSnapHairline);
+ }
+ else
+ {
+ const sal_uInt32 nPointCount(aPolyLine.count());
+ const sal_uInt32 nEdgeCount(aPolyLine.isClosed() ? nPointCount : nPointCount - 1);
+ basegfx::B2DPolygon aEdge;
+
+ aEdge.append(aPolyLine.getB2DPoint(0));
+ aEdge.append(basegfx::B2DPoint(0.0, 0.0));
- // prepare next step
- aEdge.setB2DPoint(0, aEdge.getB2DPoint(1));
+ for (sal_uInt32 i(0); i < nEdgeCount; i++)
+ {
+ const sal_uInt32 nNextIndex((i + 1) % nPointCount);
+ aEdge.setB2DPoint(1, aPolyLine.getB2DPoint(nNextIndex));
+ aEdge.setNextControlPoint(0, aPolyLine.getNextControlPoint(i));
+ aEdge.setPrevControlPoint(1, aPolyLine.getPrevControlPoint(nNextIndex));
+
+ // PixelOffset now reflected in linear transformation used
+ AddPolygonToPath(
+ cr,
+ aEdge,
+ rObjectToDevice, // ObjectToDevice *without* LineDraw-Offset
+ !bAntiAliasB2DDraw,
+ bPixelSnapHairline);
+
+ // prepare next step
+ aEdge.setB2DPoint(0, aEdge.getB2DPoint(1));
+ }
}
}
@@ -1361,7 +1415,8 @@ bool SvpSalGraphics::drawPolyLine(
ImplGetSystemDependentDataManager(),
cairo_copy_path(cr),
bNoJoin,
- bAntiAliasB2DDraw);
+ bAntiAliasB2DDraw,
+ pStroke);
}
}
@@ -1472,7 +1527,8 @@ bool SvpSalGraphics::drawPolyPolygon(
ImplGetSystemDependentDataManager(),
cairo_copy_path(cr),
false,
- false);
+ false,
+ nullptr);
}
}
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 9ee269aa18a5..ea7be8c0733c 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -117,6 +117,7 @@ public:
const basegfx::B2DPolygon& rPolyLine,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -214,6 +215,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 132a64327e42..8d3f8c95ce7b 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -260,6 +260,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/qt5/Qt5Graphics.hxx b/vcl/inc/qt5/Qt5Graphics.hxx
index 9430be94a112..5b50f9975d70 100644..100755
--- a/vcl/inc/qt5/Qt5Graphics.hxx
+++ b/vcl/inc/qt5/Qt5Graphics.hxx
@@ -119,9 +119,10 @@ public:
const PolyFlags* const* pFlgAry) override;
virtual bool drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon&, double fTransparency,
- const basegfx::B2DVector& rLineWidths, basegfx::B2DLineJoin,
- css::drawing::LineCap eLineCap, double fMiterMinimumAngle,
- bool bPixelSnapHairline) override;
+ const basegfx::B2DVector& rLineWidths,
+ const std::vector<double>* pStroke, // MM01
+ basegfx::B2DLineJoin, css::drawing::LineCap eLineCap,
+ double fMiterMinimumAngle, bool bPixelSnapHairline) override;
virtual bool drawGradient(const tools::PolyPolygon&, const Gradient&) override;
virtual void copyArea(long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth,
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 70b4ddad47f1..e9e9f4905e5e 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -238,6 +238,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index 1106a1eed981..7ce17fa38385 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -248,6 +248,7 @@ public:
const basegfx::B2DPolygon& i_rPolygon,
double i_fTransparency,
const basegfx::B2DVector& i_rLineWidth,
+ const std::vector< double >* i_pStroke, // MM01
basegfx::B2DLineJoin i_eLineJoin,
css::drawing::LineCap i_eLineCap,
double i_fMiterMinimumAngle,
@@ -476,6 +477,7 @@ protected:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx
index a6dc4a808ee9..887d1b49bbaf 100644
--- a/vcl/inc/salgdiimpl.hxx
+++ b/vcl/inc/salgdiimpl.hxx
@@ -111,6 +111,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/unx/genpspgraphics.h b/vcl/inc/unx/genpspgraphics.h
index efe1bc7bfa3f..c5eaf1975626 100644
--- a/vcl/inc/unx/genpspgraphics.h
+++ b/vcl/inc/unx/genpspgraphics.h
@@ -135,6 +135,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 97be62230a68..f979a3841b49 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -168,6 +168,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index cc59322b3098..08061db3c3ea 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -230,6 +230,7 @@ protected:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index dfd916f9e4c7..4e58196e4b01 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -26,6 +26,7 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/b2dlinegeometry.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontriangulator.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
#include <basegfx/polygon/b2dtrapezoid.hxx>
@@ -42,6 +43,7 @@
#include <cmath>
#include <vector>
+#include <numeric>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/norm.hpp>
@@ -1553,6 +1555,7 @@ void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pP
aPoly,
0.0,
basegfx::B2DVector(1.0, 1.0),
+ nullptr, // MM01
basegfx::B2DLineJoin::Miter,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0) /*default*/,
@@ -1630,6 +1633,7 @@ bool OpenGLSalGraphicsImpl::drawPolyLine(
const basegfx::B2DPolygon& rPolygon,
double fTransparency,
const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -1637,28 +1641,60 @@ bool OpenGLSalGraphicsImpl::drawPolyLine(
{
VCL_GL_INFO("::drawPolyLine " << rPolygon.getB2DRange());
+ // MM01 check done for simple reasons
+ if(!rPolygon.count() || fTransparency < 0.0 || fTransparency > 1.0)
+ {
+ return true;
+ }
+
+ // MM01 need to do line dashing as fallback stuff here now
+ const double fDotDashLength(nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
+ const bool bStrokeUsed(0.0 != fDotDashLength);
+ basegfx::B2DPolyPolygon aPolyPolygonLine;
+
+ if(bStrokeUsed)
+ {
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(
+ rPolygon, // source
+ *pStroke, // pattern
+ &aPolyPolygonLine, // traget for lines
+ nullptr, // target for gaps
+ fDotDashLength); // full length if available
+ }
+ else
+ {
+ // no line dashing, just copy
+ aPolyPolygonLine.append(rPolygon);
+ }
+
// Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
- basegfx::B2DPolygon aPolyLine(rPolygon);
- aPolyLine.transform(rObjectToDevice);
- if(bPixelSnapHairline) { aPolyLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyLine); }
+ aPolyPolygonLine.transform(rObjectToDevice);
+ if(bPixelSnapHairline) { aPolyPolygonLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine); }
const basegfx::B2DVector aLineWidth(rObjectToDevice * rLineWidth);
- // addDrawPolyLine() assumes that there are no duplicate points in the
- // polygon.
- // basegfx::B2DPolygon aPolygon(rPolygon);
- aPolyLine.removeDoublePoints();
+ for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
+ {
+ // addDrawPolyLine() assumes that there are no duplicate points in the polygon
+ basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a));
+ basegfx::utils::simplifyCurveSegments(aPolyLine);
+ aPolyLine.removeDoublePoints();
- mpRenderList->addDrawPolyLine(
- aPolyLine,
- fTransparency,
- aLineWidth,
- eLineJoin,
- eLineCap,
- fMiterMinimumAngle,
- mnLineColor,
- mrParent.getAntiAliasB2DDraw());
+ mpRenderList->addDrawPolyLine(
+ aPolyLine,
+ fTransparency,
+ aLineWidth,
+ eLineJoin,
+ eLineCap,
+ fMiterMinimumAngle,
+ mnLineColor,
+ mrParent.getAntiAliasB2DDraw());
+
+ // MM01: not sure - maybe this can be moved out of this loop, but to
+ // keep on the safe side for now, do not relly change something for now
+ PostBatchDraw();
+ }
- PostBatchDraw();
return true;
}
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 851d222f0ab7..afca58868076 100644..100755
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -29,7 +29,9 @@
#include <QtGui/QWindow>
#include <QtWidgets/QWidget>
+#include <numeric>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
static const basegfx::B2DPoint aHalfPointOfs(0.5, 0.5);
@@ -323,37 +325,67 @@ bool Qt5Graphics::drawPolyPolygonBezier(sal_uInt32 /*nPoly*/, const sal_uInt32*
bool Qt5Graphics::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon& rPolyLine, double fTransparency,
- const basegfx::B2DVector& rLineWidths,
+ const basegfx::B2DVector& rLineWidth,
+ const std::vector<double>* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin, css::drawing::LineCap eLineCap,
double fMiterMinimumAngle, bool bPixelSnapHairline)
{
if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor)
+ {
return true;
+ }
- // short circuit if there is nothing to do
- if (0 == rPolyLine.count())
+ // MM01 check done for simple reasons
+ if (!rPolyLine.count() || fTransparency < 0.0 || fTransparency > 1.0)
{
return true;
}
+ // MM01 need to do line dashing as fallback stuff here now
+ const double fDotDashLength(
+ nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
+ const bool bStrokeUsed(0.0 != fDotDashLength);
+ basegfx::B2DPolyPolygon aPolyPolygonLine;
+
+ if (bStrokeUsed)
+ {
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(rPolyLine, // source
+ *pStroke, // pattern
+ &aPolyPolygonLine, // traget for lines
+ nullptr, // target for gaps
+ fDotDashLength); // full length if available
+ }
+ else
+ {
+ // no line dashing, just copy
+ aPolyPolygonLine.append(rPolyLine);
+ }
+
// Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
- basegfx::B2DPolygon aPolyLine(rPolyLine);
- aPolyLine.transform(rObjectToDevice);
+ aPolyPolygonLine.transform(rObjectToDevice);
if (bPixelSnapHairline)
{
- aPolyLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyLine);
+ aPolyPolygonLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine);
}
- const basegfx::B2DVector aLineWidths(rObjectToDevice * rLineWidths);
+ const basegfx::B2DVector aLineWidth(rObjectToDevice * rLineWidth);
// setup poly-polygon path
QPainterPath aPath;
- AddPolygonToPath(aPath, aPolyLine, aPolyLine.isClosed(), !getAntiAliasB2DDraw(), true);
+
+ // MM01 todo - I assume that this is OKAY to be done in one run for Qt5,
+ // but this NEEDS to be checked/verified
+ for (sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
+ {
+ const basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a));
+ AddPolygonToPath(aPath, aPolyLine, aPolyLine.isClosed(), !getAntiAliasB2DDraw(), true);
+ }
Qt5Painter aPainter(*this, false, 255 * (1.0 - fTransparency));
// setup line attributes
QPen aPen = aPainter.pen();
- aPen.setWidth(aLineWidths.getX());
+ aPen.setWidth(aLineWidth.getX());
switch (eLineJoin)
{
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index e43e75caad2e..684cff1e9bd4 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -22,9 +22,11 @@
#include <cassert>
#include <cstring>
+#include <numeric>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <osl/endian.h>
#include <osl/file.hxx>
#include <sal/types.h>
@@ -851,15 +853,18 @@ bool AquaSalGraphics::drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon& rPolyLine,
double fTransparency,
- const basegfx::B2DVector& rLineWidths,
+ const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
bool bPixelSnapHairline)
{
- // short circuit if there is nothing to do
- if(0 == rPolyLine.count())
+ // MM01 check done for simple reasons
+ if(!rPolyLine.count() || fTransparency < 0.0 || fTransparency > 1.0)
+ {
return true;
+ }
#ifdef IOS
if( !CheckContext() )
@@ -867,20 +872,40 @@ bool AquaSalGraphics::drawPolyLine(
#endif
// need to check/handle LineWidth when ObjectToDevice transformation is used
- const basegfx::B2DVector aDeviceLineWidths(rObjectToDevice * rLineWidths);
- const bool bCorrectLineWidth(aDeviceLineWidths.getX() < 1.0 && rLineWidths.getX() >= 1.0);
- const basegfx::B2DVector aLineWidths(bCorrectLineWidth ? rLineWidths : aDeviceLineWidths);
+ const basegfx::B2DVector aDeviceLineWidth(rObjectToDevice * rLineWidth);
+ const bool bCorrectLineWidth(aDeviceLineWidth.getX() < 1.0 && rLineWidth.getX() >= 1.0);
+ const basegfx::B2DVector aLineWidth(bCorrectLineWidth ? rLineWidth : aDeviceLineWidth);
// #i101491# Aqua does not support B2DLineJoin::NONE; return false to use
// the fallback (own geometry preparation)
// #i104886# linejoin-mode and thus the above only applies to "fat" lines
- if( (basegfx::B2DLineJoin::NONE == eLineJoin) && (aLineWidths.getX() > 1.3) )
+ if( (basegfx::B2DLineJoin::NONE == eLineJoin) && (aLineWidth.getX() > 1.3) )
return false;
+ // MM01 need to do line dashing as fallback stuff here now
+ const double fDotDashLength(nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
+ const bool bStrokeUsed(0.0 != fDotDashLength);
+ basegfx::B2DPolyPolygon aPolyPolygonLine;
+
+ if(bStrokeUsed)
+ {
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(
+ rPolyLine, // source
+ *pStroke, // pattern
+ &aPolyPolygonLine, // traget for lines
+ nullptr, // target for gaps
+ fDotDashLength); // full length if available
+ }
+ else
+ {
+ // no line dashing, just copy
+ aPolyPolygonLine.append(rPolyLine);
+ }
+
// Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
- basegfx::B2DPolygon aPolyLine(rPolyLine);
- aPolyLine.transform(rObjectToDevice);
- if(bPixelSnapHairline) { aPolyLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyLine); }
+ aPolyPolygonLine.transform(rObjectToDevice);
+ if(bPixelSnapHairline) { aPolyPolygonLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine); }
// setup line attributes
CGLineJoin aCGLineJoin = kCGLineJoinMiter;
@@ -918,12 +943,19 @@ bool AquaSalGraphics::drawPolyLine(
// setup poly-polygon path
CGMutablePathRef xPath = CGPathCreateMutable();
SAL_INFO( "vcl.cg", "CGPathCreateMutable() = " << xPath );
- AddPolygonToPath(
- xPath,
- aPolyLine,
- aPolyLine.isClosed(),
- !getAntiAliasB2DDraw(),
- true);
+
+ // MM01 todo - I assume that this is OKAY to be done in one run for quartz
+ // but this NEEDS to be checked/verified
+ for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
+ {
+ const basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a));
+ AddPolygonToPath(
+ xPath,
+ aPolyLine,
+ aPolyLine.isClosed(),
+ !getAntiAliasB2DDraw(),
+ true);
+ }
const CGRect aRefreshRect = CGPathGetBoundingBox( xPath );
SAL_INFO( "vcl.cg", "CGPathGetBoundingBox(" << xPath << ") = " << aRefreshRect );
@@ -943,7 +975,7 @@ bool AquaSalGraphics::drawPolyLine(
CGContextSetAlpha( mrContext, 1.0 - fTransparency );
CGContextSetLineJoin( mrContext, aCGLineJoin );
CGContextSetLineCap( mrContext, aCGLineCap );
- CGContextSetLineWidth( mrContext, aLineWidths.getX() );
+ CGContextSetLineWidth( mrContext, aLineWidth.getX() );
CGContextSetMiterLimit(mrContext, fCGMiterLimit);
SAL_INFO( "vcl.cg", "CGContextDrawPath(" << mrContext << ",kCGPathStroke)" );
CGContextDrawPath( mrContext, kCGPathStroke );
diff --git a/vcl/source/gdi/FileDefinitionWidgetDraw.cxx b/vcl/source/gdi/FileDefinitionWidgetDraw.cxx
index 8256b0529dd7..bd494866a21f 100644..100755
--- a/vcl/source/gdi/FileDefinitionWidgetDraw.cxx
+++ b/vcl/source/gdi/FileDefinitionWidgetDraw.cxx
@@ -300,6 +300,7 @@ void drawFromDrawCommands(gfx::DrawRoot const& rDrawRoot, SalGraphics& rGraphics
rGraphics.DrawPolyLine(
basegfx::B2DHomMatrix(), aB2DPolygon, 1.0 - rRectangle.mnOpacity,
basegfx::B2DVector(rRectangle.mnStrokeWidth, rRectangle.mnStrokeWidth),
+ nullptr, // MM01
basegfx::B2DLineJoin::Round, css::drawing::LineCap_ROUND, 0.0f, false,
nullptr);
}
@@ -347,6 +348,7 @@ void drawFromDrawCommands(gfx::DrawRoot const& rDrawRoot, SalGraphics& rGraphics
rGraphics.DrawPolyLine(
basegfx::B2DHomMatrix(), rPolygon, 1.0 - rPath.mnOpacity,
basegfx::B2DVector(rPath.mnStrokeWidth, rPath.mnStrokeWidth),
+ nullptr, // MM01
basegfx::B2DLineJoin::Round, css::drawing::LineCap_ROUND, 0.0f, false,
nullptr);
}
@@ -389,6 +391,7 @@ void munchDrawCommands(std::vector<std::shared_ptr<WidgetDrawAction>> const& rDr
rGraphics.DrawPolyLine(
basegfx::B2DHomMatrix(), aB2DPolygon, 0.0f,
basegfx::B2DVector(rWidgetDraw.mnStrokeWidth, rWidgetDraw.mnStrokeWidth),
+ nullptr, // MM01
basegfx::B2DLineJoin::Round, css::drawing::LineCap_ROUND, 0.0f, false, nullptr);
}
break;
@@ -412,6 +415,7 @@ void munchDrawCommands(std::vector<std::shared_ptr<WidgetDrawAction>> const& rDr
rGraphics.DrawPolyLine(
basegfx::B2DHomMatrix(), aB2DPolygon, 0.0f,
basegfx::B2DVector(rWidgetDraw.mnStrokeWidth, rWidgetDraw.mnStrokeWidth),
+ nullptr, // MM01
basegfx::B2DLineJoin::Round, css::drawing::LineCap_ROUND, 0.0f, false, nullptr);
}
break;
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index 61c510a363d8..114e4051ec24 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -573,6 +573,7 @@ bool SalGraphics::DrawPolyLine(
const basegfx::B2DPolygon& i_rPolygon,
double i_fTransparency,
const basegfx::B2DVector& i_rLineWidth,
+ const std::vector< double >* i_pStroke, // MM01
basegfx::B2DLineJoin i_eLineJoin,
css::drawing::LineCap i_eLineCap,
double i_fMiterMinimumAngle,
@@ -601,6 +602,7 @@ bool SalGraphics::DrawPolyLine(
i_rPolygon,
i_fTransparency,
i_rLineWidth,
+ i_pStroke, // MM01
i_eLineJoin,
i_eLineCap,
i_fMiterMinimumAngle,
@@ -628,6 +630,7 @@ bool SalGraphics::DrawPolyLine(
i_rPolygon,
i_fTransparency,
i_rLineWidth,
+ i_pStroke, // MM01
i_eLineJoin,
i_eLineCap,
i_fMiterMinimumAngle,
@@ -642,6 +645,7 @@ bool SalGraphics::DrawPolyLine(
i_rPolygon,
i_fTransparency,
i_rLineWidth,
+ i_pStroke, // MM01
i_eLineJoin,
i_eLineCap,
i_fMiterMinimumAngle,
diff --git a/vcl/source/outdev/line.cxx b/vcl/source/outdev/line.cxx
index ef7cb30ef6ba..a6a23026aa94 100644
--- a/vcl/source/outdev/line.cxx
+++ b/vcl/source/outdev/line.cxx
@@ -133,6 +133,7 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
aB2DPolyLine,
0.0,
aB2DLineWidth,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
@@ -244,6 +245,7 @@ void OutputDevice::drawLine( basegfx::B2DPolyPolygon aLinePolyPolygon, const Lin
rB2DPolygon,
0.0,
basegfx::B2DVector(1.0,1.0),
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
diff --git a/vcl/source/outdev/polygon.cxx b/vcl/source/outdev/polygon.cxx
index aacbe00df924..8aeda1d0c1e5 100644
--- a/vcl/source/outdev/polygon.cxx
+++ b/vcl/source/outdev/polygon.cxx
@@ -101,6 +101,7 @@ void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly )
rPolygon,
0.0,
aB2DLineWidth,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
@@ -219,6 +220,7 @@ void OutputDevice::DrawPolygon( const tools::Polygon& rPoly )
aB2DPolygon,
0.0,
aB2DLineWidth,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
@@ -329,6 +331,7 @@ void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyP
rPolygon,
0.0,
aB2DLineWidth,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
diff --git a/vcl/source/outdev/polyline.cxx b/vcl/source/outdev/polyline.cxx
index a1b63fe494dd..997f5383aa12 100644
--- a/vcl/source/outdev/polyline.cxx
+++ b/vcl/source/outdev/polyline.cxx
@@ -76,6 +76,7 @@ void OutputDevice::DrawPolyLine( const tools::Polygon& rPoly )
aB2DPolyLine,
0.0,
aB2DLineWidth,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0) /*default fMiterMinimumAngle, not used*/,
@@ -179,6 +180,7 @@ void OutputDevice::DrawPolyLine( const basegfx::B2DPolygon& rB2DPolygon,
rB2DPolygon,
fLineWidth,
0.0,
+ nullptr, // MM01
eLineJoin,
eLineCap,
fMiterMinimumAngle))
@@ -235,6 +237,7 @@ void OutputDevice::DrawPolyLine( const basegfx::B2DPolygon& rB2DPolygon,
rPolygon,
0.0,
0.0,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0) /*default, not used*/,
@@ -306,6 +309,7 @@ bool OutputDevice::DrawPolyLineDirect(
const basegfx::B2DPolygon& rB2DPolygon,
double fLineWidth,
double fTransparency,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -350,6 +354,7 @@ bool OutputDevice::DrawPolyLineDirect(
rB2DPolygon,
fTransparency,
aB2DLineWidth,
+ pStroke, // MM01
eLineJoin,
eLineCap,
fMiterMinimumAngle,
diff --git a/vcl/source/outdev/transparent.cxx b/vcl/source/outdev/transparent.cxx
index fdb3115b2812..764d13fc80d8 100644
--- a/vcl/source/outdev/transparent.cxx
+++ b/vcl/source/outdev/transparent.cxx
@@ -278,6 +278,7 @@ void OutputDevice::DrawTransparent(
rPolygon,
fTransparency,
aHairlineWidth,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
@@ -400,6 +401,7 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
rPolygon,
fTransparency,
aLineWidths,
+ nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index e0a4879ff6fb..62c29fb593bd 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -18,6 +18,8 @@
*/
#include <memory>
+#include <numeric>
+
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xrender.h>
@@ -1656,6 +1658,7 @@ private:
basegfx::B2DLineJoin meJoin;
css::drawing::LineCap meCap;
double mfMiterMinimumAngle;
+ std::vector< double > maStroke;
public:
SystemDependentData_Triangulation(
@@ -1664,13 +1667,16 @@ public:
const basegfx::B2DVector& rLineWidth,
basegfx::B2DLineJoin eJoin,
css::drawing::LineCap eCap,
- double fMiterMinimumAngle);
+ double fMiterMinimumAngle,
+ const std::vector< double >* pStroke); // MM01
+ // read access
const basegfx::triangulator::B2DTriangleVector& getTriangles() const { return maTriangles; }
const basegfx::B2DVector& getLineWidth() const { return maLineWidth; }
const basegfx::B2DLineJoin& getJoin() const { return meJoin; }
const css::drawing::LineCap& getCap() const { return meCap; }
double getMiterMinimumAngle() const { return mfMiterMinimumAngle; }
+ const std::vector< double >& getStroke() const { return maStroke; }
virtual sal_Int64 estimateUsageInBytes() const override;
};
@@ -1681,14 +1687,20 @@ SystemDependentData_Triangulation::SystemDependentData_Triangulation(
const basegfx::B2DVector& rLineWidth,
basegfx::B2DLineJoin eJoin,
css::drawing::LineCap eCap,
- double fMiterMinimumAngle)
+ double fMiterMinimumAngle,
+ const std::vector< double >* pStroke)
: basegfx::SystemDependentData(rSystemDependentDataManager),
maTriangles(rTriangles),
maLineWidth(rLineWidth),
meJoin(eJoin),
meCap(eCap),
- mfMiterMinimumAngle(fMiterMinimumAngle)
+ mfMiterMinimumAngle(fMiterMinimumAngle),
+ maStroke()
{
+ if(nullptr != pStroke)
+ {
+ maStroke = *pStroke;
+ }
}
sal_Int64 SystemDependentData_Triangulation::estimateUsageInBytes() const
@@ -1708,6 +1720,7 @@ bool X11SalGraphicsImpl::drawPolyLine(
const basegfx::B2DPolygon& rPolygon,
double fTransparency,
const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -1725,7 +1738,6 @@ bool X11SalGraphicsImpl::drawPolyLine(
const basegfx::B2DVector aDeviceLineWidths(bObjectToDeviceIsIdentity ? rLineWidth : rObjectToDevice * rLineWidth);
const bool bCorrectLineWidth(!bObjectToDeviceIsIdentity && aDeviceLineWidths.getX() < 1.0 && aLineWidth.getX() >= 1.0);
basegfx::B2DHomMatrix aObjectToDeviceInv;
- basegfx::B2DPolygon aPolygon(rPolygon);
if(bCorrectLineWidth)
{
@@ -1743,6 +1755,25 @@ bool X11SalGraphicsImpl::drawPolyLine(
std::shared_ptr<SystemDependentData_Triangulation> pSystemDependentData_Triangulation(
rPolygon.getSystemDependentData<SystemDependentData_Triangulation>());
+ // MM01 need to do line dashing as fallback stuff here now
+ const double fDotDashLength(nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
+ const bool bStrokeUsed(0.0 != fDotDashLength);
+
+ if(pSystemDependentData_Triangulation)
+ {
+ // MM01 - check on stroke change. Used against not used, or if oth used,
+ // equal or different? Triangulation geometry creation depends heavily
+ // on stroke, independent of being transformation independent
+ const bool bStrokeWasUsed(!pSystemDependentData_Triangulation->getStroke().empty());
+
+ if(bStrokeWasUsed != bStrokeUsed
+ || (bStrokeUsed && *pStroke != pSystemDependentData_Triangulation->getStroke()))
+ {
+ // data invalid, forget
+ pSystemDependentData_Triangulation.reset();
+ }
+ }
+
if(pSystemDependentData_Triangulation)
{
// check data validity (I)
@@ -1779,15 +1810,36 @@ bool X11SalGraphicsImpl::drawPolyLine(
if(!pSystemDependentData_Triangulation)
{
+ // MM01 need to do line dashing as fallback stuff here now
+ basegfx::B2DPolyPolygon aPolyPolygonLine;
+
+ if(bStrokeUsed)
+ {
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(
+ rPolygon, // source
+ *pStroke, // pattern
+ &aPolyPolygonLine, // traget for lines
+ nullptr, // target for gaps
+ fDotDashLength); // full length if available
+ }
+ else
+ {
+ // no line dashing, just copy
+ aPolyPolygonLine.append(rPolygon);
+ }
+
// try to create data
if(bPixelSnapHairline)
{
+ // Do NOT transform, but keep device-independent. To
+ // do so, transform to device for snap, but back again after
if(!bObjectToDeviceIsIdentity)
{
- aPolygon.transform(rObjectToDevice);
+ aPolyPolygonLine.transform(rObjectToDevice);
}
- aPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolygon);
+ aPolyPolygonLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine);
if(!bObjectToDeviceIsIdentity)
{
@@ -1797,21 +1849,30 @@ bool X11SalGraphicsImpl::drawPolyLine(
aObjectToDeviceInv.invert();
}
- aPolygon.transform(aObjectToDeviceInv);
+ aPolyPolygonLine.transform(aObjectToDeviceInv);
}
}
basegfx::triangulator::B2DTriangleVector aTriangles;
- const basegfx::B2DPolyPolygon aAreaPolyPoly(
+
+ // MM01 checked/verified for X11 (linux)
+ for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
+ {
+ const basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a));
+ // MM01 upps - commit 51b5b93092d6231615de470c62494c24e54828a1 removed
+ // this *central* geometry-creating lines (!) probably due to aAreaPolyPoly
+ // *not* being used - that's true, but the work is inside of filling
+ // aTriangles data (!)
basegfx::utils::createAreaGeometry(
- aPolygon,
+ aPolyLine,
0.5 * aLineWidth.getX(),
eLineJoin,
eLineCap,
basegfx::deg2rad(12.5),
0.4,
fMiterMinimumAngle,
- &aTriangles));
+ &aTriangles); // CAUTION! This is *needed* since it creates the data!
+ }
if(!aTriangles.empty())
{
@@ -1824,7 +1885,8 @@ bool X11SalGraphicsImpl::drawPolyLine(
aLineWidth,
eLineJoin,
eLineCap,
- fMiterMinimumAngle);
+ fMiterMinimumAngle,
+ pStroke);
}
}
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index 282b9a29a8d9..222bc6c7a3c1 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -173,6 +173,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 1af613902663..fd3c926b95a5 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -706,6 +706,7 @@ bool X11SalGraphics::drawPolyLine(
const basegfx::B2DPolygon& rPolygon,
double fTransparency,
const basegfx::B2DVector& rLineWidth,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -742,6 +743,7 @@ bool X11SalGraphics::drawPolyLine(
rPolygon,
fTransparency,
rLineWidth,
+ pStroke, // MM01
eLineJoin,
eLineCap,
fMiterMinimumAngle,
@@ -761,6 +763,7 @@ bool X11SalGraphics::drawPolyLine(
rPolygon,
fTransparency,
rLineWidth,
+ pStroke, // MM01
eLineJoin,
eLineCap,
fMiterMinimumAngle,
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index e40b9fd5cc82..7a5df6b3e262 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -419,6 +419,7 @@ bool GenPspGraphics::drawPolyLine(
const basegfx::B2DPolygon&,
double /*fTransparency*/,
const basegfx::B2DVector& /*rLineWidths*/,
+ const std::vector< double >* /*pStroke*/, // MM01
basegfx::B2DLineJoin /*eJoin*/,
css::drawing::LineCap /*eLineCap*/,
double /*fMiterMinimumAngle*/,
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index 434cdcbac8e4..26f972919ff4 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -17,6 +17,11 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <sal/config.h>
+
+#include <memory>
+#include <numeric>
+
#include <svsys.h>
#include "gdiimpl.hxx"
@@ -1957,18 +1962,19 @@ private:
// all other values the triangulation is based on and
// need to be compared with to check for data validity
bool mbNoLineJoin;
+ std::vector< double > maStroke;
public:
SystemDependentData_GraphicsPath(
basegfx::SystemDependentDataManager& rSystemDependentDataManager,
std::shared_ptr<Gdiplus::GraphicsPath>& rpGraphicsPath,
- bool bNoLineJoin);
+ bool bNoLineJoin,
+ const std::vector< double >* pStroke); // MM01
- // read access to Gdiplus::GraphicsPath
+ // read access
std::shared_ptr<Gdiplus::GraphicsPath>& getGraphicsPath() { return mpGraphicsPath; }
-
- // other data-validity access
bool getNoLineJoin() const { return mbNoLineJoin; }
+ const std::vector< double >& getStroke() const { return maStroke; }
virtual sal_Int64 estimateUsageInBytes() const override;
};
@@ -1976,11 +1982,17 @@ public:
SystemDependentData_GraphicsPath::SystemDependentData_GraphicsPath(
basegfx::SystemDependentDataManager& rSystemDependentDataManager,
std::shared_ptr<Gdiplus::GraphicsPath>& rpGraphicsPath,
- bool bNoLineJoin)
+ bool bNoLineJoin,
+ const std::vector< double >* pStroke)
: basegfx::SystemDependentData(rSystemDependentDataManager),
mpGraphicsPath(rpGraphicsPath),
- mbNoLineJoin(bNoLineJoin)
+ mbNoLineJoin(bNoLineJoin),
+ maStroke()
{
+ if(nullptr != pStroke)
+ {
+ maStroke = *pStroke;
+ }
}
sal_Int64 SystemDependentData_GraphicsPath::estimateUsageInBytes() const
@@ -2104,7 +2116,8 @@ bool WinSalGraphicsImpl::drawPolyPolygon(
rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>(
ImplGetSystemDependentDataManager(),
pGraphicsPath,
- false);
+ false,
+ nullptr);
}
if(mrParent.getAntiAliasB2DDraw())
@@ -2164,12 +2177,14 @@ bool WinSalGraphicsImpl::drawPolyLine(
const basegfx::B2DPolygon& rPolygon,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
bool bPixelSnapHairline)
{
- if(!mbPen || 0 == rPolygon.count())
+ // MM01 check done for simple reasons
+ if(!mbPen || !rPolygon.count() || fTransparency < 0.0 || fTransparency > 1.0)
{
return true;
}
@@ -2261,6 +2276,25 @@ bool WinSalGraphicsImpl::drawPolyLine(
std::shared_ptr<SystemDependentData_GraphicsPath> pSystemDependentData_GraphicsPath(
rPolygon.getSystemDependentData<SystemDependentData_GraphicsPath>());
+ // MM01 need to do line dashing as fallback stuff here now
+ const double fDotDashLength(nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0);
+ const bool bStrokeUsed(0.0 != fDotDashLength);
+
+ if(pSystemDependentData_GraphicsPath)
+ {
+ // MM01 - check on stroke change. Used against not used, or if oth used,
+ // equal or different? Triangulation geometry creation depends heavily
+ // on stroke, independent of being transformation independent
+ const bool bStrokeWasUsed(!pSystemDependentData_GraphicsPath->getStroke().empty());
+
+ if(bStrokeWasUsed != bStrokeUsed
+ || (bStrokeUsed && *pStroke != pSystemDependentData_GraphicsPath->getStroke()))
+ {
+ // data invalid, forget
+ pSystemDependentData_GraphicsPath.reset();
+ }
+ }
+
if(pSystemDependentData_GraphicsPath)
{
// check data validity
@@ -2282,17 +2316,47 @@ bool WinSalGraphicsImpl::drawPolyLine(
// fill data of buffered data
pGraphicsPath.reset(new Gdiplus::GraphicsPath());
- impAddB2DPolygonToGDIPlusGraphicsPathReal(
- *pGraphicsPath,
- rPolygon,
- rObjectToDevice,
- bNoLineJoin,
- bPixelSnapHairline);
-
- if(rPolygon.isClosed() && !bNoLineJoin)
+ if(bStrokeUsed)
{
- // #i101491# needed to create the correct line joins
- pGraphicsPath->CloseFigure();
+ // MM01 need to do line dashing as fallback stuff here now
+ basegfx::B2DPolyPolygon aPolyPolygonLine;
+
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(
+ rPolygon, // source
+ *pStroke, // pattern
+ &aPolyPolygonLine, // traget for lines
+ nullptr, // target for gaps
+ fDotDashLength); // full length if available
+
+ // MM01 checked/verified, ok
+ for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
+ {
+ const basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a));
+ pGraphicsPath->StartFigure();
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(
+ *pGraphicsPath,
+ aPolyLine,
+ rObjectToDevice,
+ bNoLineJoin,
+ bPixelSnapHairline);
+ }
+ }
+ else
+ {
+ // no line dashing, just copy
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(
+ *pGraphicsPath,
+ rPolygon,
+ rObjectToDevice,
+ bNoLineJoin,
+ bPixelSnapHairline);
+
+ if(rPolygon.isClosed() && !bNoLineJoin)
+ {
+ // #i101491# needed to create the correct line joins
+ pGraphicsPath->CloseFigure();
+ }
}
// add to buffering mechanism
@@ -2301,7 +2365,8 @@ bool WinSalGraphicsImpl::drawPolyLine(
rPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>(
ImplGetSystemDependentDataManager(),
pGraphicsPath,
- bNoLineJoin);
+ bNoLineJoin,
+ pStroke);
}
}
diff --git a/vcl/win/gdi/gdiimpl.hxx b/vcl/win/gdi/gdiimpl.hxx
index 54d75bd9291c..086d7312b695 100644
--- a/vcl/win/gdi/gdiimpl.hxx
+++ b/vcl/win/gdi/gdiimpl.hxx
@@ -117,6 +117,7 @@ public:
const basegfx::B2DPolygon&,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin,
css::drawing::LineCap,
double fMiterMinimumAngle,
diff --git a/vcl/win/gdi/salgdi_gdiplus.cxx b/vcl/win/gdi/salgdi_gdiplus.cxx
index 99c7d0e506e9..ce2f2cc69c20 100644
--- a/vcl/win/gdi/salgdi_gdiplus.cxx
+++ b/vcl/win/gdi/salgdi_gdiplus.cxx
@@ -42,6 +42,7 @@ bool WinSalGraphics::drawPolyLine(
const basegfx::B2DPolygon& rPolygon,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
+ const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle,
@@ -52,6 +53,7 @@ bool WinSalGraphics::drawPolyLine(
rPolygon,
fTransparency,
rLineWidths,
+ pStroke, // MM01
eLineJoin,
eLineCap,
fMiterMinimumAngle,