summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2016-07-01 15:50:00 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2016-07-07 15:09:09 +0200
commitede382b3928afae9e59e8da0f475a4e59decf30e (patch)
treea03d780d3dbf7e7a574bfd96d4fd4a1936cd2733
parent3665e5b65d74d4ae22b637502efdac65d4b6c96c (diff)
tdf#82214 optimize PatternFillPrimitive and SVG
Use buffering in the drawinglayer, and don't do slow stuff in the windows gdi renderer. Conflicts: svgio/source/svgreader/svgstyleattributes.cxx Change-Id: Id955ee6a3b03e568c2678f02d77af35d2e5ba1d4
-rw-r--r--drawinglayer/source/primitive2d/patternfillprimitive2d.cxx73
-rw-r--r--svgio/source/svgreader/svgstyleattributes.cxx99
-rw-r--r--vcl/win/gdi/gdiimpl.cxx56
3 files changed, 112 insertions, 116 deletions
diff --git a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
index 39b695c4be7a..5d1eec1ca93b 100644
--- a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
@@ -31,8 +31,8 @@
using namespace com::sun::star;
-#define MAXIMUM_SQUARE_LENGTH (164.0)
-#define MINIMUM_SQUARE_LENGTH (32.0)
+#define MAXIMUM_SQUARE_LENGTH (186.0)
+#define MINIMUM_SQUARE_LENGTH (16.0)
#define MINIMUM_TILES_LENGTH (3)
namespace drawinglayer
@@ -257,57 +257,58 @@ namespace drawinglayer
Primitive2DContainer PatternFillPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
- if(0 == mnDiscreteWidth || 0 == mnDiscreteHeight)
+ // The existing bufferd decomposition uses a buffer in the remembered
+ // size or none if sizes are zero. Get new needed sizes which depend on
+ // the given ViewInformation
+ bool bResetBuffering = false;
+ sal_uInt32 nW(0);
+ sal_uInt32 nH(0);
+ calculateNeededDiscreteBufferSize(nW, nH, rViewInformation);
+ const bool bBufferingCurrentlyUsed(0 != mnDiscreteWidth && 0 != mnDiscreteHeight);
+ const bool bBufferingNextUsed(0 != nW && 0 != nH);
+
+ if(bBufferingNextUsed)
{
- // Currently no buffering is used. Check if the resulting discrete sizes
- // in the current situation would be good for buffering from now on
- PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
-
- calculateNeededDiscreteBufferSize(pThat->mnDiscreteWidth, pThat->mnDiscreteHeight, rViewInformation);
- }
- else
- {
- // The existing bufferd decomposition uses a buffer in the remembered
- // size. Get new needed sizes which depend on the given ViewInformation
- sal_uInt32 nW(0);
- sal_uInt32 nH(0);
- calculateNeededDiscreteBufferSize(nW, nH, rViewInformation);
-
- if(0 != nW && 0 != nH)
+ // buffering is now possible
+ if(bBufferingCurrentlyUsed)
{
- // buffering is possible - check if reset is needed
- bool bResetBuffering = false;
-
if(nW > mnDiscreteWidth || nH > mnDiscreteHeight)
{
// Higher resolution is needed than used in the existing buffered
- // decomposition
+ // decomposition - create new one
bResetBuffering = true;
}
else if(double(nW * nH) / double(mnDiscreteWidth * mnDiscreteHeight) <= 0.5)
{
// Size has shrunk for 50% or more - it's worth to refresh the buffering
+ // to spare some ressources
bResetBuffering = true;
}
-
- if(bResetBuffering)
- {
- PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
- pThat->mnDiscreteWidth = nW;
- pThat->mnDiscreteHeight = nH;
- pThat->setBuffered2DDecomposition(Primitive2DContainer());
- }
}
else
{
- // no buffering wanted or possible - clear decomposition to create a
- // new, unbuffered one
- PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
- pThat->mnDiscreteWidth = 0;
- pThat->mnDiscreteHeight = 0;
- pThat->setBuffered2DDecomposition(Primitive2DContainer());
+ // currently no buffering used - reset evtl. unbuffered
+ // decomposition to start buffering
+ bResetBuffering = true;
}
}
+ else
+ {
+ // buffering is no longer possible
+ if(bBufferingCurrentlyUsed)
+ {
+ // reset decomposition to allow creation of unbuffered one
+ bResetBuffering = true;
+ }
+ }
+
+ if(bResetBuffering)
+ {
+ PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
+ pThat->mnDiscreteWidth = nW;
+ pThat->mnDiscreteHeight = nH;
+ pThat->setBuffered2DDecomposition(Primitive2DContainer());
+ }
// call parent
return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx
index dcde298b72be..993521c39922 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -664,54 +664,75 @@ namespace svgio
if(basegfx::fTools::more(fStrokeWidth, 0.0))
{
- // get LineJoin, LineCap and stroke array
- const basegfx::B2DLineJoin aB2DLineJoin(StrokeLinejoinToB2DLineJoin(getStrokeLinejoin()));
- const css::drawing::LineCap aLineCap(StrokeLinecapToDrawingLineCap(getStrokeLinecap()));
- ::std::vector< double > aDashArray;
+ drawinglayer::primitive2d::Primitive2DReference aNewLinePrimitive;
- if(!getStrokeDasharray().empty())
+ // if we have a line with two identical points it is not really a line,
+ // but used by SVG sometimes to paint a single dot.In that case, create
+ // the geometry for a single dot
+ if(1 == rPath.count())
{
- aDashArray = solveSvgNumberVector(getStrokeDasharray(), mrOwner);
- }
+ const basegfx::B2DPolygon aSingle(rPath.getB2DPolygon(0));
- // todo: Handle getStrokeDashOffset()
-
- // convert svg:stroke-miterlimit to LineAttrute:mfMiterMinimumAngle
- // The default needs to be set explicitly, because svg default <> Draw default
- double fMiterMinimumAngle;
- if (getStrokeMiterLimit().isSet())
- {
- fMiterMinimumAngle = 2.0 * asin(1.0/getStrokeMiterLimit().getNumber());
+ if(2 == aSingle.count() && aSingle.getB2DPoint(0).equal(aSingle.getB2DPoint(1)))
+ {
+ aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(
+ basegfx::tools::createPolygonFromCircle(
+ aSingle.getB2DPoint(0),
+ fStrokeWidth * (1.44 * 0.5))),
+ pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0));
+ }
}
- else
+
+ if(!aNewLinePrimitive.is())
{
- fMiterMinimumAngle = 2.0 * asin(0.25); // 1.0/default 4.0
- }
+ // get LineJoin, LineCap and stroke array
+ const basegfx::B2DLineJoin aB2DLineJoin(StrokeLinejoinToB2DLineJoin(getStrokeLinejoin()));
+ const css::drawing::LineCap aLineCap(StrokeLinecapToDrawingLineCap(getStrokeLinecap()));
+ ::std::vector< double > aDashArray;
- // prepare line attribute
- drawinglayer::primitive2d::Primitive2DReference aNewLinePrimitive;
+ if(!getStrokeDasharray().empty())
+ {
+ aDashArray = solveSvgNumberVector(getStrokeDasharray(), mrOwner);
+ }
+
+ // convert svg:stroke-miterlimit to LineAttrute:mfMiterMinimumAngle
+ // The default needs to be set explicitely, because svg default <> Draw default
+ double fMiterMinimumAngle;
+ if (getStrokeMiterLimit().isSet())
+ {
+ fMiterMinimumAngle = 2.0 * asin(1.0/getStrokeMiterLimit().getNumber());
+ }
+ else
+ {
+ fMiterMinimumAngle = 2.0 * asin(0.25); // 1.0/default 4.0
+ }
- const drawinglayer::attribute::LineAttribute aLineAttribute(
- pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0),
- fStrokeWidth,
- aB2DLineJoin,
- aLineCap,
- fMiterMinimumAngle);
+ // todo: Handle getStrokeDashOffset()
- if(aDashArray.empty())
- {
- aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
- rPath,
- aLineAttribute);
- }
- else
- {
- const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashArray);
+ // prepare line attribute
+ const drawinglayer::attribute::LineAttribute aLineAttribute(
+ pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0),
+ fStrokeWidth,
+ aB2DLineJoin,
+ aLineCap,
+ fMiterMinimumAngle);
- aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
- rPath,
- aLineAttribute,
- aStrokeAttribute);
+ if(aDashArray.empty())
+ {
+ aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+ rPath,
+ aLineAttribute);
+ }
+ else
+ {
+ const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashArray);
+
+ aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+ rPath,
+ aLineAttribute,
+ aStrokeAttribute);
+ }
}
if(pStrokeGradient || pStrokePattern)
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index 3728755cb756..09c63f554799 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -1896,10 +1896,9 @@ bool WinSalGraphicsImpl::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt
}
void impAddB2DPolygonToGDIPlusGraphicsPathReal(
- Gdiplus::GpPath *pPath,
+ Gdiplus::GraphicsPath& rGraphicsPath,
const basegfx::B2DPolygon& rPolygon,
- bool bNoLineJoin,
- const basegfx::B2DVector* pLineWidths)
+ bool bNoLineJoin)
{
sal_uInt32 nCount(rPolygon.count());
@@ -1941,43 +1940,17 @@ void impAddB2DPolygonToGDIPlusGraphicsPathReal(
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());
+ 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
{
- 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.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)
@@ -1986,7 +1959,7 @@ void impAddB2DPolygonToGDIPlusGraphicsPathReal(
if(bNoLineJoin)
{
- Gdiplus::DllExports::GdipStartPathFigure(pPath);
+ rGraphicsPath.StartFigure();
}
}
}
@@ -2014,8 +1987,9 @@ bool WinSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPo
aGraphicsPath.StartFigure();
}
- impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath, rPolyPolygon.getB2DPolygon(a), false, 0);
- Gdiplus::DllExports::GdipClosePathFigure(pPath);
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(aGraphicsPath, rPolyPolygon.getB2DPolygon(a), false);
+
+ aGraphicsPath.CloseFigure();
}
if(mrParent.getAntiAliasB2DDraw())
@@ -2127,7 +2101,7 @@ bool WinSalGraphicsImpl::drawPolyLine(
}
}
- impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath, rPolygon, bNoLineJoin, &rLineWidths);
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(aGraphicsPath, rPolygon, bNoLineJoin);
if(rPolygon.isClosed() && !bNoLineJoin)
{