summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@me.com>2020-03-05 19:24:30 +0100
committerArmin Le Grand <Armin.Le.Grand@me.com>2020-03-06 10:10:55 +0100
commitdd117712bd5692f7bf3870ba91572a0bab54ab86 (patch)
treebde473f22e43cc320e3960c331de7051d01ad77e
parenta3c8951da607d63ac7ffc76a062bb76208ca5ff3 (diff)
tdf#124848 partial refactor hairline logic
With the handover of transformations to line draw calls it is no longer feasible to detect and prepare LineWidth stuff when the old office definition for hairlnes is used, a line width of zero. It was managed in the system-independent part, but now may have to be prepared in logic and not discrete (pixel) coordinates. To do so, find and cleanup all places where 1/1.0 was used as hairline line width. Adapt all seven graphic subsystems to handle the line width == 0/0.0 cases accordingly. Test as good as possible. Change-Id: I2badc045474dcd51612e50597b8406a55d9dc863 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90057 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx23
-rw-r--r--vcl/headless/svpgdi.cxx20
-rw-r--r--vcl/opengl/gdiimpl.cxx7
-rw-r--r--vcl/qt5/Qt5Graphics_GDI.cxx6
-rw-r--r--vcl/quartz/salgdicommon.cxx9
-rw-r--r--vcl/skia/gdiimpl.cxx8
-rw-r--r--vcl/source/outdev/line.cxx7
-rw-r--r--vcl/source/outdev/polygon.cxx12
-rw-r--r--vcl/source/outdev/polyline.cxx9
-rw-r--r--vcl/source/outdev/textline.cxx3
-rw-r--r--vcl/source/outdev/transparent.cxx8
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.cxx25
-rw-r--r--vcl/win/gdi/gdiimpl.cxx72
13 files changed, 97 insertions, 112 deletions
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 4bd490dcfe78..8cff84f3d3bf 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -166,26 +166,6 @@ namespace drawinglayer::processor2d
const bool bStrokeAttributeNotUsed(rSource.getStrokeAttribute().isDefault()
|| 0.0 == rSource.getStrokeAttribute().getFullDotDashLen());
- // check if LineWidth can be simplified in world coordinates
- double fLineWidth(rSource.getLineAttribute().getWidth());
-
- if(basegfx::fTools::more(fLineWidth, 0.0))
- {
- basegfx::B2DVector aLineWidth(fLineWidth, 0.0);
- aLineWidth = maCurrentTransformation * aLineWidth;
- const double fWorldLineWidth(aLineWidth.getLength());
-
- // draw simple hairline for small line widths
- // see also RenderPolygonStrokePrimitive2D which is used if this try fails
- bool bIsAntiAliasing = getOptionsDrawinglayer().IsAntiAliasing();
- if ( (basegfx::fTools::lessOrEqual(fWorldLineWidth, 1.0) && bIsAntiAliasing)
- || (basegfx::fTools::lessOrEqual(fWorldLineWidth, 1.5) && !bIsAntiAliasing))
- {
- // draw simple hairline
- fLineWidth = 0.0;
- }
- }
-
const basegfx::BColor aLineColor(
maBColorModifierStack.getModifiedColor(
rSource.getLineAttribute().getColor()));
@@ -197,7 +177,8 @@ namespace drawinglayer::processor2d
return mpOutputDevice->DrawPolyLineDirect(
maCurrentTransformation,
rLocalPolygon,
- fLineWidth,
+ // tdf#124848 use LineWidth direct, do not try to solve for zero-case (aka hairline)
+ rSource.getLineAttribute().getWidth(),
fTransparency,
bStrokeAttributeNotUsed ? nullptr : &rSource.getStrokeAttribute().getDotDashArray(),
rSource.getLineAttribute().getLineJoin(),
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index de105c5062f9..fb4514eba37d 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -1525,22 +1525,20 @@ bool SvpSalGraphics::drawPolyLine(
// need to check/handle LineWidth when ObjectToDevice transformation is used
basegfx::B2DVector aLineWidth(rLineWidth);
const bool bObjectToDeviceIsIdentity(rObjectToDevice.isIdentity());
- 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;
-
- if(bCorrectLineWidth)
+ // tdf#124848 calculate-back logical LineWidth for a hairline
+ // since this implementation hands over the transformation to
+ // the graphic sub-system
+ if(aLineWidth.equalZero())
{
- if(aObjectToDeviceInv.isIdentity())
+ aLineWidth = basegfx::B2DVector(1.0, 1.0);
+
+ if(!bObjectToDeviceIsIdentity)
{
- aObjectToDeviceInv = rObjectToDevice;
+ basegfx::B2DHomMatrix aObjectToDeviceInv(rObjectToDevice);
aObjectToDeviceInv.invert();
+ aLineWidth = aObjectToDeviceInv * aLineWidth;
}
-
- // calculate-back logical LineWidth for a hairline
- aLineWidth = aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0);
}
// PixelOffset used: Need to reflect in linear transformation
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 4a4a19c89600..25cac157a56b 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -1678,7 +1678,12 @@ bool OpenGLSalGraphicsImpl::drawPolyLine(
// Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
aPolyPolygonLine.transform(rObjectToDevice);
if(bPixelSnapHairline) { aPolyPolygonLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine); }
- const basegfx::B2DVector aLineWidth(rObjectToDevice * rLineWidth);
+
+ // tdf#124848 get correct LineWidth in discrete coordinates,
+ // take hairline case into account
+ const basegfx::B2DVector aLineWidth(rLineWidth.equalZero()
+ ? basegfx::B2DVector(1.0, 1.0)
+ : rObjectToDevice * rLineWidth);
for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++)
{
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 38866ae96320..eb43811466d4 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -369,7 +369,11 @@ bool Qt5Graphics::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
{
aPolyPolygonLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine);
}
- const basegfx::B2DVector aLineWidth(rObjectToDevice * rLineWidth);
+
+ // tdf#124848 get correct LineWidth in discrete coordinates,
+ // take hairline case into account
+ const basegfx::B2DVector aLineWidth(rLineWidth.equalZero() ? basegfx::B2DVector(1.0, 1.0)
+ : rObjectToDevice * rLineWidth);
// setup poly-polygon path
QPainterPath aPath;
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index a526790bb907..4ca5eede4578 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -835,10 +835,11 @@ bool AquaSalGraphics::drawPolyLine(
return false;
#endif
- // need to check/handle LineWidth when ObjectToDevice transformation is used
- const basegfx::B2DVector aDeviceLineWidth(rObjectToDevice * rLineWidth);
- const bool bCorrectLineWidth(aDeviceLineWidth.getX() < 1.0 && rLineWidth.getX() >= 1.0);
- const basegfx::B2DVector aLineWidth(bCorrectLineWidth ? rLineWidth : aDeviceLineWidth);
+ // tdf#124848 get correct LineWidth in discrete coordinates,
+ // take hairline case into account
+ const basegfx::B2DVector aLineWidth(rLineWidth.equalZero()
+ ? basegfx::B2DVector(1.0, 1.0)
+ : rObjectToDevice * rLineWidth);
// #i101491# Aqua does not support B2DLineJoin::NONE; return false to use
// the fallback (own geometry preparation)
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index a704ef9c5312..7dfd667e8a63 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -718,10 +718,10 @@ bool SkiaSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDev
preDraw();
SAL_INFO("vcl.skia", "drawpolyline(" << this << "): " << rPolyLine << ":" << mLineColor);
- // need to check/handle LineWidth when ObjectToDevice transformation is used
- const basegfx::B2DVector aDeviceLineWidth(rObjectToDevice * rLineWidth);
- const bool bCorrectLineWidth(aDeviceLineWidth.getX() < 1.0 && rLineWidth.getX() >= 1.0);
- const basegfx::B2DVector aLineWidth(bCorrectLineWidth ? rLineWidth : aDeviceLineWidth);
+ // tdf#124848 get correct LineWidth in discrete coordinates,
+ // take hairline case into account
+ const basegfx::B2DVector aLineWidth(rLineWidth.equalZero() ? basegfx::B2DVector(1.0, 1.0)
+ : rObjectToDevice * rLineWidth);
// Skia does not support B2DLineJoin::NONE; return false to use
// the fallback (own geometry preparation),
diff --git a/vcl/source/outdev/line.cxx b/vcl/source/outdev/line.cxx
index 3332ab711a24..e88dd383e7f3 100644
--- a/vcl/source/outdev/line.cxx
+++ b/vcl/source/outdev/line.cxx
@@ -116,7 +116,6 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
// at least transform with double precision to device coordinates; this will
// avoid pixel snap of single, appended lines
const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
- const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
basegfx::B2DPolygon aB2DPolyLine;
aB2DPolyLine.append(basegfx::B2DPoint(rStartPt.X(), rStartPt.Y()));
@@ -129,7 +128,8 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
basegfx::B2DHomMatrix(),
aB2DPolyLine,
0.0,
- aB2DLineWidth,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
@@ -241,7 +241,8 @@ void OutputDevice::drawLine( basegfx::B2DPolyPolygon aLinePolyPolygon, const Lin
basegfx::B2DHomMatrix(),
rB2DPolygon,
0.0,
- basegfx::B2DVector(1.0,1.0),
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
diff --git a/vcl/source/outdev/polygon.cxx b/vcl/source/outdev/polygon.cxx
index c33374f3a408..c742379d39de 100644
--- a/vcl/source/outdev/polygon.cxx
+++ b/vcl/source/outdev/polygon.cxx
@@ -88,7 +88,6 @@ void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly )
if(bSuccess && IsLineColor())
{
- const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
for(auto const& rPolygon : aB2DPolyPolygon)
@@ -97,7 +96,8 @@ void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly )
aTransform,
rPolygon,
0.0,
- aB2DLineWidth,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
@@ -209,14 +209,14 @@ void OutputDevice::DrawPolygon( const tools::Polygon& rPoly )
if(bSuccess && IsLineColor())
{
- const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
bSuccess = mpGraphics->DrawPolyLine(
aTransform,
aB2DPolygon,
0.0,
- aB2DLineWidth,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
@@ -318,7 +318,6 @@ void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyP
if(bSuccess && IsLineColor())
{
- const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
for(auto const& rPolygon : aB2DPolyPolygon)
@@ -327,7 +326,8 @@ void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyP
aTransform,
rPolygon,
0.0,
- aB2DLineWidth,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
diff --git a/vcl/source/outdev/polyline.cxx b/vcl/source/outdev/polyline.cxx
index 161bf5fb4e52..3e2ed372e01b 100644
--- a/vcl/source/outdev/polyline.cxx
+++ b/vcl/source/outdev/polyline.cxx
@@ -65,14 +65,14 @@ void OutputDevice::DrawPolyLine( const tools::Polygon& rPoly )
const basegfx::B2DPolygon aB2DPolyLine(rPoly.getB2DPolygon());
const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
- const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
if(mpGraphics->DrawPolyLine(
aTransform,
aB2DPolyLine,
0.0,
- aB2DLineWidth,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
@@ -341,8 +341,6 @@ bool OutputDevice::DrawPolyLineDirect(
{
// combine rObjectTransform with WorldToDevice
const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation() * rObjectTransform);
- const bool bLineWidthZero(basegfx::fTools::equalZero(fLineWidth));
- const basegfx::B2DVector aB2DLineWidth(bLineWidthZero ? 1.0 : fLineWidth, bLineWidthZero ? 1.0 : fLineWidth);
const bool bPixelSnapHairline((mnAntialiasing & AntialiasingFlags::PixelSnapHairline) && rB2DPolygon.count() < 1000);
// draw the polyline
@@ -350,7 +348,8 @@ bool OutputDevice::DrawPolyLineDirect(
aTransform,
rB2DPolygon,
fTransparency,
- aB2DLineWidth,
+ // tdf#124848 use LineWidth direct, do not try to solve for zero-case (aka hairline)
+ basegfx::B2DVector(fLineWidth, fLineWidth),
pStroke, // MM01
eLineJoin,
eLineCap,
diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
index e52b02410ebd..a6eaa6b1c3a7 100644
--- a/vcl/source/outdev/textline.cxx
+++ b/vcl/source/outdev/textline.cxx
@@ -997,7 +997,8 @@ void OutputDevice::DrawWaveLine(const Point& rStartPos, const Point& rEndPos, lo
if (nWaveHeight > pFontInstance->mxFontMetric->GetWavelineUnderlineSize())
{
nWaveHeight = pFontInstance->mxFontMetric->GetWavelineUnderlineSize();
- nLineWidth = 1;
+ // tdf#124848 hairline
+ nLineWidth = 0;
}
const basegfx::B2DRectangle aWaveLineRectangle(nStartX, nStartY, nEndX, nEndY + nWaveHeight);
diff --git a/vcl/source/outdev/transparent.cxx b/vcl/source/outdev/transparent.cxx
index 3c4a6fb2a1c0..c6baa93ed7c3 100644
--- a/vcl/source/outdev/transparent.cxx
+++ b/vcl/source/outdev/transparent.cxx
@@ -260,7 +260,6 @@ void OutputDevice::DrawTransparent(
if( bDrawnOk && IsLineColor() )
{
- const basegfx::B2DVector aHairlineWidth(1,1);
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
for(auto const& rPolygon : aB2DPolyPolygon)
@@ -269,7 +268,8 @@ void OutputDevice::DrawTransparent(
aFullTransform,
rPolygon,
fTransparency,
- aHairlineWidth,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
@@ -383,7 +383,6 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
mpGraphics->SetFillColor();
// draw the border line
- const basegfx::B2DVector aLineWidths( 1, 1 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
for(auto const& rPolygon : aB2DPolyPolygon)
@@ -392,7 +391,8 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
aTransform,
rPolygon,
fTransparency,
- aLineWidths,
+ // tdf#124848 hairline
+ basegfx::B2DVector::getEmptyVector(),
nullptr, // MM01
basegfx::B2DLineJoin::NONE,
css::drawing::LineCap_BUTT,
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index ddbf68cda3d1..99884a4c0941 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -1665,20 +1665,27 @@ bool X11SalGraphicsImpl::drawPolyLine(
// need to check/handle LineWidth when ObjectToDevice transformation is used
basegfx::B2DVector aLineWidth(rLineWidth);
const bool bObjectToDeviceIsIdentity(rObjectToDevice.isIdentity());
- const basegfx::B2DVector aDeviceLineWidths(bObjectToDeviceIsIdentity ? rLineWidth : rObjectToDevice * rLineWidth);
- const bool bCorrectLineWidth(!bObjectToDeviceIsIdentity && aDeviceLineWidths.getX() < 1.0 && aLineWidth.getX() >= 1.0);
basegfx::B2DHomMatrix aObjectToDeviceInv;
- if(bCorrectLineWidth)
+ // tdf#124848 calculate-back logical LineWidth for a hairline.
+ // This implementation does not hand over the transformation to
+ // the graphic sub-system, but the triangulation data is prepared
+ // view-independent based on the logic LineWidth, so we need to
+ // know it
+ if(aLineWidth.equalZero())
{
- if(aObjectToDeviceInv.isIdentity())
+ aLineWidth = basegfx::B2DVector(1.0, 1.0);
+
+ if(!bObjectToDeviceIsIdentity)
{
- aObjectToDeviceInv = rObjectToDevice;
- aObjectToDeviceInv.invert();
- }
+ if(aObjectToDeviceInv.isIdentity())
+ {
+ aObjectToDeviceInv = rObjectToDevice;
+ aObjectToDeviceInv.invert();
+ }
- // calculate-back logical LineWidth for a hairline
- aLineWidth = aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0);
+ aLineWidth = aObjectToDeviceInv * aLineWidth;
+ }
}
// try to access buffered data
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index a26d85d1e378..08c5f7861e8e 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -2111,7 +2111,7 @@ bool WinSalGraphicsImpl::drawPolyPolygon(
// and embed into a TransformPrimitive2D containing the transformation.
//
// A 2nd problem is that the NoLineJoin mode (basegfx::B2DLineJoin::NONE
- // && rLineWidths > 0.0) creates polygon fill infos that are not reusable
+ // && !bIsHairline) creates polygon fill infos that are not reusable
// for the fill case (see ::drawPolyLine below) - thus we would need a
// bool and/or two system-dependent paths buffered - doable, but complicated.
//
@@ -2204,7 +2204,7 @@ bool WinSalGraphicsImpl::drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon& rPolygon,
double fTransparency,
- const basegfx::B2DVector& rLineWidths,
+ const basegfx::B2DVector& rLineWidth,
const std::vector< double >* pStroke, // MM01
basegfx::B2DLineJoin eLineJoin,
css::drawing::LineCap eLineCap,
@@ -2217,14 +2217,34 @@ bool WinSalGraphicsImpl::drawPolyLine(
return true;
}
+ // need to check/handle LineWidth when ObjectToDevice transformation is used
+ basegfx::B2DVector aLineWidth(rLineWidth);
+ const bool bObjectToDeviceIsIdentity(rObjectToDevice.isIdentity());
+ const bool bIsHairline(aLineWidth.equalZero());
+
+ // tdf#124848 calculate-back logical LineWidth for a hairline
+ // since this implementation hands over the transformation to
+ // the graphic sub-system
+ if(bIsHairline)
+ {
+ aLineWidth = basegfx::B2DVector(1.0, 1.0);
+
+ if(!bObjectToDeviceIsIdentity)
+ {
+ basegfx::B2DHomMatrix aObjectToDeviceInv(rObjectToDevice);
+ aObjectToDeviceInv.invert();
+ aLineWidth = aObjectToDeviceInv * aLineWidth;
+ }
+ }
+
Gdiplus::Graphics aGraphics(mrParent.getHDC());
const sal_uInt8 aTrans = static_cast<sal_uInt8>(basegfx::fround( 255 * (1.0 - fTransparency) ));
const Gdiplus::Color aTestColor(aTrans, maLineColor.GetRed(), maLineColor.GetGreen(), maLineColor.GetBlue());
- Gdiplus::Pen aPen(aTestColor.GetValue(), Gdiplus::REAL(rLineWidths.getX()));
+ Gdiplus::Pen aPen(aTestColor.GetValue(), Gdiplus::REAL(aLineWidth.getX()));
bool bNoLineJoin(false);
// Set full (Object-to-Device) transformation - if used
- if(rObjectToDevice.isIdentity())
+ if(bObjectToDeviceIsIdentity)
{
aGraphics.ResetTransform();
}
@@ -2246,7 +2266,7 @@ bool WinSalGraphicsImpl::drawPolyLine(
{
case basegfx::B2DLineJoin::NONE :
{
- if(basegfx::fTools::more(rLineWidths.getX(), 0.0))
+ if(!bIsHairline)
{
bNoLineJoin = true;
}
@@ -2315,44 +2335,12 @@ bool WinSalGraphicsImpl::drawPolyLine(
// activate to stroke directly
if(bDoDirectGDIPlusStroke && bStrokeUsed)
{
- // tdf#130478
- // Unfortunately GDIPlus wants to have the dash pattern relative to line width
- // which gets problematic due to the good old office's hairline definition. This
- // means that we do not *have* the real line width here, but 0.0 - or in the case
- // of GDIPlus (here) 1.0.
- // This is 'corrected' in several locations, e.g. OutputDevice::DrawPolyLineDirect
- // to 1.0 and VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect to 0.0.
- // This would need some cleanup what will be highly problematic due to the usage
- // of hairlines with line width of 0.0 being a pixel always and leading to different
- // visualizations. More bad - the potential of having pretty 'invisible' lines
- // in unexpected places when zooming far out. Another problematic aspect of that hairline
- // definition is that this makes hairlines per definition view-transformation dependent
- // regarding their 'core' line width and the area they cover - handled in Primitives,
- // but not easy to do.
- // The way out here is to calculate back a single pixel from device to logic
- // (Object coordinates) to have the 'logic', view-dependent line width and use it.
- // That works for the cost of a matrix inversion - sigh.
+ // tdf#124848 the fix of tdf#130478 that was needed here before
+ // gets much easier when already handling the hairline case above,
+ // the back-calculated logical linewidth is already here, just use it.
+ // Still be careful - a zero LineWidth *should* not happen, but...
std::vector<Gdiplus::REAL> aDashArray(pStroke->size());
- double fFactor(1.0);
-
- if(rLineWidths.getX() <= 1.0)
- {
- // no 'real' line width, need to calculate back the logic line width
- // for a one pixel hairline
- basegfx::B2DHomMatrix aObjectToDeviceInv(rObjectToDevice);
- aObjectToDeviceInv.invert();
- const basegfx::B2DVector aOnePixel(aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0));
-
- if(aOnePixel.getX() > 0.0)
- {
- fFactor = 1.0 / aOnePixel.getX();
- }
- }
- else
- {
- // use logic line width
- fFactor = 1.0 / rLineWidths.getX();
- }
+ const double fFactor(aLineWidth.equalZero() ? 1.0 : 1.0 / aLineWidth.getX());
for(size_t a(0); a < pStroke->size(); a++)
{