summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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++)
{