summaryrefslogtreecommitdiff
path: root/vcl/win/gdi/gdiimpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/win/gdi/gdiimpl.cxx')
-rw-r--r--vcl/win/gdi/gdiimpl.cxx125
1 files changed, 77 insertions, 48 deletions
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index c5e591a2eaf7..3728755cb756 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -1896,9 +1896,10 @@ bool WinSalGraphicsImpl::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt
}
void impAddB2DPolygonToGDIPlusGraphicsPathReal(
- Gdiplus::GraphicsPath& rGraphicsPath,
+ Gdiplus::GpPath *pPath,
const basegfx::B2DPolygon& rPolygon,
- bool bNoLineJoin)
+ bool bNoLineJoin,
+ const basegfx::B2DVector* pLineWidths)
{
sal_uInt32 nCount(rPolygon.count());
@@ -1908,56 +1909,85 @@ void impAddB2DPolygonToGDIPlusGraphicsPathReal(
const bool bControls(rPolygon.areControlPointsUsed());
basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
- for(sal_uInt32 a(0); a < nEdgeCount; a++)
+ if(nEdgeCount)
{
- const sal_uInt32 nNextIndex((a + 1) % nCount);
- const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
- const bool b1stControlPointUsed(bControls && rPolygon.isNextControlPointUsed(a));
- const bool b2ndControlPointUsed(bControls && rPolygon.isPrevControlPointUsed(nNextIndex));
-
- if(b1stControlPointUsed || b2ndControlPointUsed)
+ for(sal_uInt32 a(0); a < nEdgeCount; a++)
{
- basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
- basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
-
- // tdf#99165 MS Gdiplus cannot handle creating correct extra geometry for fat lines
- // with LineCap or LineJoin when a bezier segment starts or ends trivial, e.g. has
- // no 1st or 2nd control point, despite that these are mathematicaly correct definitions
- // (basegfx can handle that). To solve, create replacement vectors to thre resp. next
- // control point with 1/3rd of length (the default control vector for these cases).
- // Only one of this can happen here, else the is(Next|Prev)ControlPointUsed wopuld have
- // both been false.
- // Caution: This error (and it's correction) might be necessary for other graphical
- // sub-systems in a similar way
- if(!b1stControlPointUsed)
+ const sal_uInt32 nNextIndex((a + 1) % nCount);
+ const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
+ const bool b1stControlPointUsed(bControls && rPolygon.isNextControlPointUsed(a));
+ const bool b2ndControlPointUsed(bControls && rPolygon.isPrevControlPointUsed(nNextIndex));
+
+ if(b1stControlPointUsed || b2ndControlPointUsed)
{
- aCa = aCurr + ((aCb - aCurr) * 0.3);
+ basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
+ basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
+
+ // tdf#99165 MS Gdiplus cannot handle creating correct extra geometry for fat lines
+ // with LineCap or LineJoin when a bezier segment starts or ends trivial, e.g. has
+ // no 1st or 2nd control point, despite that these are mathematicaly correct definitions
+ // (basegfx can handle that). To solve, create replacement vectors to thre resp. next
+ // control point with 1/3rd of length (the default control vector for these cases).
+ // Only one of this can happen here, else the is(Next|Prev)ControlPointUsed wopuld have
+ // both been false.
+ // Caution: This error (and it's correction) might be necessary for other graphical
+ // sub-systems in a similar way
+ if(!b1stControlPointUsed)
+ {
+ aCa = aCurr + ((aCb - aCurr) * 0.3);
+ }
+ else if(!b2ndControlPointUsed)
+ {
+ aCb = aNext + ((aCa - aNext) * 0.3);
+ }
+
+ Gdiplus::DllExports::GdipAddPathBezier(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aCa.getX(), aCa.getY(),
+ aCb.getX(), aCb.getY(),
+ aNext.getX(), aNext.getY());
}
- else if(!b2ndControlPointUsed)
+ else
{
- aCb = aNext + ((aCa - aNext) * 0.3);
+ if(pLineWidths && aCurr.equal(aNext))
+ {
+ // For lines with no length Gdiplus unfortunately paints nothing,
+ // independent of LineCaps being set. This differs from e.g. SVG
+ // and other systems. To get geometry created, add some offset,
+ // based on line width to have something relative to current metrics
+ if(!basegfx::fTools::equalZero(pLineWidths->getX()))
+ {
+ Gdiplus::DllExports::GdipAddPathLine(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aNext.getX() + (pLineWidths->getX() * 0.1), aNext.getY());
+ }
+ else
+ {
+ Gdiplus::DllExports::GdipAddPathLine(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aNext.getX(), aNext.getY() + (pLineWidths->getY() * 0.1));
+ }
+ }
+ else
+ {
+ Gdiplus::DllExports::GdipAddPathLine(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aNext.getX(), aNext.getY());
+ }
}
- rGraphicsPath.AddBezier(
- static_cast< Gdiplus::REAL >(aCurr.getX()), static_cast< Gdiplus::REAL >(aCurr.getY()),
- static_cast< Gdiplus::REAL >(aCa.getX()), static_cast< Gdiplus::REAL >(aCa.getY()),
- static_cast< Gdiplus::REAL >(aCb.getX()), static_cast< Gdiplus::REAL >(aCb.getY()),
- static_cast< Gdiplus::REAL >(aNext.getX()), static_cast< Gdiplus::REAL >(aNext.getY()));
- }
- else
- {
- rGraphicsPath.AddLine(
- static_cast< Gdiplus::REAL >(aCurr.getX()), static_cast< Gdiplus::REAL >(aCurr.getY()),
- static_cast< Gdiplus::REAL >(aNext.getX()), static_cast< Gdiplus::REAL >(aNext.getY()));
- }
-
- if(a + 1 < nEdgeCount)
- {
- aCurr = aNext;
-
- if(bNoLineJoin)
+ if(a + 1 < nEdgeCount)
{
- rGraphicsPath.StartFigure();
+ aCurr = aNext;
+
+ if(bNoLineJoin)
+ {
+ Gdiplus::DllExports::GdipStartPathFigure(pPath);
+ }
}
}
}
@@ -1984,9 +2014,8 @@ bool WinSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPo
aGraphicsPath.StartFigure();
}
- impAddB2DPolygonToGDIPlusGraphicsPathReal(aGraphicsPath, rPolyPolygon.getB2DPolygon(a), false);
-
- aGraphicsPath.CloseFigure();
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath, rPolyPolygon.getB2DPolygon(a), false, 0);
+ Gdiplus::DllExports::GdipClosePathFigure(pPath);
}
if(mrParent.getAntiAliasB2DDraw())
@@ -2098,7 +2127,7 @@ bool WinSalGraphicsImpl::drawPolyLine(
}
}
- impAddB2DPolygonToGDIPlusGraphicsPathReal(aGraphicsPath, rPolygon, bNoLineJoin);
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath, rPolygon, bNoLineJoin, &rLineWidths);
if(rPolygon.isClosed() && !bNoLineJoin)
{