diff options
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 23 | ||||
-rw-r--r-- | vcl/headless/svpgdi.cxx | 20 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 7 | ||||
-rw-r--r-- | vcl/qt5/Qt5Graphics_GDI.cxx | 6 | ||||
-rw-r--r-- | vcl/quartz/salgdicommon.cxx | 9 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 8 | ||||
-rw-r--r-- | vcl/source/outdev/line.cxx | 7 | ||||
-rw-r--r-- | vcl/source/outdev/polygon.cxx | 12 | ||||
-rw-r--r-- | vcl/source/outdev/polyline.cxx | 9 | ||||
-rw-r--r-- | vcl/source/outdev/textline.cxx | 3 | ||||
-rw-r--r-- | vcl/source/outdev/transparent.cxx | 8 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/gdiimpl.cxx | 25 | ||||
-rw-r--r-- | vcl/win/gdi/gdiimpl.cxx | 72 |
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++) { |