summaryrefslogtreecommitdiff
path: root/vcl/win/gdi
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 /vcl/win/gdi
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>
Diffstat (limited to 'vcl/win/gdi')
-rw-r--r--vcl/win/gdi/gdiimpl.cxx72
1 files changed, 30 insertions, 42 deletions
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++)
{