summaryrefslogtreecommitdiff
path: root/vcl/win
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2016-07-01 15:40:00 +0200
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2016-07-07 22:32:39 +0200
commit4609380bb0bde0d4437b72b752c1c24ee2950361 (patch)
treed5083eb62aa8f5717997274cecf4011e8f5b8126 /vcl/win
parentc1f476d91805e6a9573bba3ea8f5f980e0ea7b54 (diff)
tdf#82214 optimize performance for primitives
See svg bug doc, which is processed quite slowly. Beyond needing faster renderers, there is also demand to improve the handling of primitives created by SVG import. Conflicts: drawinglayer/source/primitive2d/patternfillprimitive2d.cxx vcl/win/gdi/gdiimpl.cxx Change-Id: I10992a5746b8b2d6b50e3ee3fe415a035685c9ba
Diffstat (limited to 'vcl/win')
-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)
{