summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2018-09-06 18:15:02 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2018-09-13 08:49:35 +0200
commit7034311dce663c895577267110baadbec312d491 (patch)
tree8c1d712cbfb1b15dc492e6e724b6b22892914249 /vcl
parentd92b0efe58b77247e1e5292c1a989baa934df797 (diff)
Support buffering SystemDependent GraphicData (II)
In this step I have changed all calls that use a B2DPolyPolygon and do filled graphics, added support for providing needed transformation which will -if supported- be used. Added buffering of SystemDependentData at B2DPolyPolygon for that purpose, see comments describing the current possibilities in the Gdiplus implementation. Moved lifetime creation/cleanup of SystemDependentDataManager to ImplSVData due to cleanup problems in the clang build Tried to use a std::unique_ptr to hold the instance of a SystemDependentDataBuffer at ImplSVData and cleanup inside DeInitVCL() right before ::ImplDeInitScheduler. This works in principle, but scheduler shutdown triggers ProcessEventsToIdle which leads to repaints and re-creates the buffer. Will now do exactly as was done with GdiPlusBuffer before, a simple local static incarnation and a call to SetStatic() in constructor Splitted SystemDependentDataBuffer and Timer due to different LifeTimes. Timer needs to be destructed earlier than SystemDependentDataBuffer, before Scheduler::ImplDeInitScheduler() is called from DeInitVCL() Change-Id: I2134e4346a183a4cee1be3428c51541cc8867c11 Reviewed-on: https://gerrit.libreoffice.org/60102 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/headless/svpgdi.cxx152
-rw-r--r--vcl/inc/headless/svpgdi.hxx10
-rw-r--r--vcl/inc/openglgdiimpl.hxx6
-rw-r--r--vcl/inc/qt5/Qt5Graphics.hxx3
-rw-r--r--vcl/inc/quartz/salgdi.h5
-rw-r--r--vcl/inc/salgdi.hxx12
-rw-r--r--vcl/inc/salgdiimpl.hxx6
-rw-r--r--vcl/inc/svdata.hxx6
-rw-r--r--vcl/inc/unx/genpspgraphics.h8
-rw-r--r--vcl/inc/unx/salgdi.h5
-rw-r--r--vcl/inc/win/salgdi.h5
-rw-r--r--vcl/opengl/gdiimpl.cxx28
-rw-r--r--vcl/qt5/Qt5Graphics_GDI.cxx9
-rw-r--r--vcl/quartz/salgdicommon.cxx14
-rw-r--r--vcl/source/app/scheduler.cxx2
-rw-r--r--vcl/source/app/svdata.cxx132
-rw-r--r--vcl/source/app/svmain.cxx6
-rw-r--r--vcl/source/gdi/salgdilayout.cxx175
-rw-r--r--vcl/source/outdev/line.cxx10
-rw-r--r--vcl/source/outdev/polygon.cxx67
-rw-r--r--vcl/source/outdev/polyline.cxx28
-rw-r--r--vcl/source/outdev/transparent.cxx45
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.cxx27
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.hxx6
-rw-r--r--vcl/unx/generic/gdi/salgdi.cxx21
-rw-r--r--vcl/unx/generic/print/genpspgraphics.cxx5
-rw-r--r--vcl/win/gdi/gdiimpl.cxx238
-rw-r--r--vcl/win/gdi/gdiimpl.hxx6
-rw-r--r--vcl/win/gdi/salbmp.cxx2
-rw-r--r--vcl/win/gdi/salgdi_gdiplus.cxx10
30 files changed, 637 insertions, 412 deletions
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 5acd288e8787..56bd740dbe40 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -714,7 +714,10 @@ void SvpSalGraphics::drawPixel( long nX, long nY, Color nColor )
m_aLineColor = SALCOLOR_NONE;
m_aFillColor = nColor;
- drawPolyPolygon(basegfx::B2DPolyPolygon(aRect));
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ basegfx::B2DPolyPolygon(aRect),
+ 0.0);
m_aFillColor = aOrigFillColor;
m_aLineColor = aOrigLineColor;
@@ -732,7 +735,12 @@ void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
{
basegfx::B2DPolygon aRect = basegfx::utils::createPolygonFromRect(basegfx::B2DRectangle(nX, nY, nX+nWidth, nY+nHeight));
m_aFillColor = aOrigFillColor;
- drawPolyPolygon(basegfx::B2DPolyPolygon(aRect));
+
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ basegfx::B2DPolyPolygon(aRect),
+ 0.0);
+
m_aFillColor = SALCOLOR_NONE;
}
@@ -741,7 +749,12 @@ void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
// need same -1 hack as X11SalGraphicsImpl::drawRect
basegfx::B2DPolygon aRect = basegfx::utils::createPolygonFromRect(basegfx::B2DRectangle( nX, nY, nX+nWidth-1, nY+nHeight-1));
m_aLineColor = aOrigLineColor;
- drawPolyPolygon(basegfx::B2DPolyPolygon(aRect));
+
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ basegfx::B2DPolyPolygon(aRect),
+ 0.0);
+
m_aLineColor = SALCOLOR_NONE;
}
@@ -775,7 +788,10 @@ void SvpSalGraphics::drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry)
for (sal_uInt32 i = 1; i < nPoints; ++i)
aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY));
- drawPolyPolygon(basegfx::B2DPolyPolygon(aPoly));
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ basegfx::B2DPolyPolygon(aPoly),
+ 0.0);
}
void SvpSalGraphics::drawPolyPolygon(sal_uInt32 nPoly,
@@ -798,7 +814,10 @@ void SvpSalGraphics::drawPolyPolygon(sal_uInt32 nPoly,
}
}
- drawPolyPolygon(aPolyPoly);
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ aPolyPoly,
+ 0.0);
}
basegfx::B2DPoint impPixelSnap(
@@ -1061,7 +1080,7 @@ bool SvpSalGraphics::drawPolyLine(
bool bPixelSnapHairline)
{
// short circuit if there is nothing to do
- if(0 == rPolyLine.count())
+ if(0 == rPolyLine.count() || fTransparency < 0.0 || fTransparency >= 1.0)
{
return true;
}
@@ -1111,7 +1130,7 @@ bool SvpSalGraphics::drawPolyLine(
bool bPixelSnapHairline)
{
// short circuit if there is nothing to do
- if(0 == rPolyLine.count())
+ if(0 == rPolyLine.count() || fTransparency < 0.0 || fTransparency >= 1.0)
{
return true;
}
@@ -1283,7 +1302,7 @@ bool SvpSalGraphics::drawPolyLine(
// copy and add to buffering mechanism
pSystemDependentData_CairoPath = rPolyLine.addOrReplaceSystemDependentData<SystemDependentData_CairoPath>(
- SalGraphics::getSystemDependentDataManager(),
+ ImplGetSystemDependentDataManager(),
cairo_copy_path(cr));
// fill data of buffered data
@@ -1337,36 +1356,68 @@ bool SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32,
return false;
}
-void SvpSalGraphics::setupPolyPolygon(cairo_t* cr, const basegfx::B2DPolyPolygon& rPolyPoly)
-{
- clipRegion(cr);
-
- for (const auto & rPoly : rPolyPoly)
- {
- // PixelOffset used: Was dependent of 'm_aLineColor != SALCOLOR_NONE'
- // Adapt setupPolyPolygon-users to set a linear transformation to achieve PixelOffset
- AddPolygonToPath(
- cr,
- rPoly,
- basegfx::B2DHomMatrix(),
- !getAntiAliasB2DDraw(),
- false);
- }
-}
-
-bool SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency)
+bool SvpSalGraphics::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
{
const bool bHasFill(m_aFillColor != SALCOLOR_NONE);
const bool bHasLine(m_aLineColor != SALCOLOR_NONE);
- if(0 == rPolyPoly.count() || !(bHasFill || bHasLine))
+ if(0 == rPolyPolygon.count() || !(bHasFill || bHasLine) || fTransparency < 0.0 || fTransparency >= 1.0)
{
return true;
}
cairo_t* cr = getCairoContext(true);
+ clipRegion(cr);
+
+ // Set full (Object-to-Device) transformation - if used
+ if(!rObjectToDevice.isIdentity())
+ {
+ cairo_matrix_t aMatrix;
+
+ cairo_matrix_init(
+ &aMatrix,
+ rObjectToDevice.get( 0, 0 ),
+ rObjectToDevice.get( 1, 0 ),
+ rObjectToDevice.get( 0, 1 ),
+ rObjectToDevice.get( 1, 1 ),
+ rObjectToDevice.get( 0, 2 ),
+ rObjectToDevice.get( 1, 2 ));
+ cairo_set_matrix(cr, &aMatrix);
+ }
- setupPolyPolygon(cr, rPolyPoly);
+ // try to access buffered data
+ std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
+ rPolyPolygon.getSystemDependentData<SystemDependentData_CairoPath>());
+
+ if(pSystemDependentData_CairoPath)
+ {
+ // re-use data
+ cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
+ }
+ else
+ {
+ // create data
+ for (const auto & rPoly : rPolyPolygon)
+ {
+ // PixelOffset used: Was dependent of 'm_aLineColor != SALCOLOR_NONE'
+ // Adapt setupPolyPolygon-users to set a linear transformation to achieve PixelOffset
+ AddPolygonToPath(
+ cr,
+ rPoly,
+ rObjectToDevice,
+ !getAntiAliasB2DDraw(),
+ false);
+ }
+
+ // copy and add to buffering mechanism
+ // for decisions how/what to buffer, see Note in WinSalGraphicsImpl::drawPolyPolygon
+ pSystemDependentData_CairoPath = rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_CairoPath>(
+ ImplGetSystemDependentDataManager(),
+ cairo_copy_path(cr));
+ }
// To make releaseCairoContext work, use empty extents
basegfx::B2DRange extents;
@@ -1426,51 +1477,6 @@ void SvpSalGraphics::applyColor(cairo_t *cr, Color aColor)
}
}
-void SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly)
-{
- const bool bHasFill(m_aFillColor != SALCOLOR_NONE);
- const bool bHasLine(m_aLineColor != SALCOLOR_NONE);
-
- if(0 == rPolyPoly.count() || !(bHasFill || bHasLine))
- {
- return;
- }
-
- cairo_t* cr = getCairoContext(true);
-
- setupPolyPolygon(cr, rPolyPoly);
-
- // To make releaseCairoContext work, use empty extents
- basegfx::B2DRange extents;
-
- if (bHasFill)
- {
- applyColor(cr, m_aFillColor);
-
- // Get FillDamage (will be extended for LineDamage below)
- extents = getClippedFillDamage(cr);
-
- cairo_fill_preserve(cr);
- }
-
- if (bHasLine)
- {
- // PixelOffset used: Set PixelOffset as linear transformation
- cairo_matrix_t aMatrix;
- cairo_matrix_init_translate(&aMatrix, 0.5, 0.5);
- cairo_set_matrix(cr, &aMatrix);
-
- applyColor(cr, m_aLineColor);
-
- // expand with possible StrokeDamage
- extents.expand(getClippedStrokeDamage(cr));
-
- cairo_stroke_preserve(cr);
- }
-
- releaseCairoContext(cr, true, extents);
-}
-
void SvpSalGraphics::copyArea( long nDestX,
long nDestY,
long nSrcX,
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 158c331eded6..9c7ee0391f47 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -122,9 +122,8 @@ private:
void copySource(const SalTwoRect& rTR, cairo_surface_t* source);
void copyWithOperator(const SalTwoRect& rTR, cairo_surface_t* source,
cairo_operator_t eOp = CAIRO_OPERATOR_SOURCE);
- void setupPolyPolygon(cairo_t* cr, const basegfx::B2DPolyPolygon& rPolyPoly);
void applyColor(cairo_t *cr, Color rColor);
- void drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly);
+
protected:
vcl::Region m_aClipRegion;
SvpCairoTextRender m_aTextRenderImpl;
@@ -200,7 +199,12 @@ public:
virtual void drawPixel( long nX, long nY, Color nColor ) override;
virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ) override;
virtual void drawRect( long nX, long nY, long nWidth, long nHeight ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency ) override;
+
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon&,
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index f2fd9b7819dd..bc19dcd338fb 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -249,7 +249,11 @@ public:
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
diff --git a/vcl/inc/qt5/Qt5Graphics.hxx b/vcl/inc/qt5/Qt5Graphics.hxx
index 6bde41ffa27f..76c39146728c 100644
--- a/vcl/inc/qt5/Qt5Graphics.hxx
+++ b/vcl/inc/qt5/Qt5Graphics.hxx
@@ -108,7 +108,8 @@ public:
virtual void drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry) override;
virtual void drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints,
PCONSTSALPOINT* pPtAry) override;
- virtual bool drawPolyPolygon(const basegfx::B2DPolyPolygon&, double fTransparency) override;
+ virtual bool drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&, double fTransparency) override;
virtual bool drawPolyLineBezier(sal_uInt32 nPoints, const SalPoint* pPtAry,
const PolyFlags* pFlgAry) override;
virtual bool drawPolygonBezier(sal_uInt32 nPoints, const SalPoint* pPtAry,
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index b03fa5b6b3b2..24b5268493de 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -224,7 +224,10 @@ public:
virtual void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
virtual bool drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry ) override;
virtual bool drawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry ) override;
virtual bool drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, const SalPoint* const* pPtAry, const PolyFlags* const* pFlgAry ) override;
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index 31c484885a2b..19fac921d2fb 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -55,7 +55,6 @@ namespace basegfx {
class B2DVector;
class B2DPolygon;
class B2DPolyPolygon;
- class SystemDependentDataManager;
}
typedef sal_Unicode sal_Ucs; // TODO: use sal_UCS4 instead of sal_Unicode
@@ -78,10 +77,6 @@ public:
virtual SalGraphicsImpl* GetImpl() const = 0;
- // access to single global managing instance of a basegfx::SystemDependentDataManager,
- // used to handle graphic data in system-dependent form
- static basegfx::SystemDependentDataManager& getSystemDependentDataManager();
-
/// Check that our mpImpl is OpenGL and return the context, otherwise NULL.
rtl::Reference<OpenGLContext> GetOpenGLContext() const;
@@ -244,6 +239,7 @@ public:
const OutputDevice *pOutDev );
bool DrawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolyPolygon &i_rPolyPolygon,
double i_fTransparency,
const OutputDevice *i_pOutDev);
@@ -464,7 +460,11 @@ protected:
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) = 0;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) = 0;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) = 0;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) = 0;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx
index 8e545d093d20..d4023bd52947 100644
--- a/vcl/inc/salgdiimpl.hxx
+++ b/vcl/inc/salgdiimpl.hxx
@@ -100,7 +100,11 @@ public:
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) = 0;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) = 0;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) = 0;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) = 0;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 679debce188e..6ef279586ea1 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -106,6 +106,11 @@ namespace vcl
class Window;
}
+namespace basegfx
+{
+ class SystemDependentDataManager;
+}
+
class LocaleConfigurationListener : public utl::ConfigurationListener
{
public:
@@ -372,6 +377,7 @@ struct ImplSVData
css::uno::Reference<css::i18n::XCharacterClassification> const& ImplGetCharClass();
void ImplDeInitSVData();
+VCL_PLUGIN_PUBLIC basegfx::SystemDependentDataManager& ImplGetSystemDependentDataManager();
VCL_PLUGIN_PUBLIC vcl::Window* ImplGetDefaultWindow();
VCL_PLUGIN_PUBLIC vcl::Window* ImplGetDefaultContextWindow();
VCL_PLUGIN_PUBLIC const std::locale& ImplGetResLocale();
diff --git a/vcl/inc/unx/genpspgraphics.h b/vcl/inc/unx/genpspgraphics.h
index 3f6bae6c0744..bddcb888ebc6 100644
--- a/vcl/inc/unx/genpspgraphics.h
+++ b/vcl/inc/unx/genpspgraphics.h
@@ -126,8 +126,12 @@ public:
virtual void drawPolyPolygon( sal_uInt32 nPoly,
const sal_uInt32* pPoints,
PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&,
- double fTransparency ) override;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
+
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon&,
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 8b73c4583243..d6054eae4b4c 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -160,7 +160,10 @@ public:
const sal_uInt32* pPoints,
PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 9f30f57ecac8..e8fe72cc4ca7 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -221,7 +221,10 @@ protected:
virtual void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon&,
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 4c966bd408ef..082c8d66b7b0 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -1567,7 +1567,10 @@ void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPt
for (sal_uInt32 i = 1; i < nPoints; ++i)
aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY));
- drawPolyPolygon(basegfx::B2DPolyPolygon(aPoly), 0.0);
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ basegfx::B2DPolyPolygon(aPoly),
+ 0.0);
}
void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPointCounts, PCONSTSALPOINT* pPtAry )
@@ -1589,13 +1592,30 @@ void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32*
}
}
- drawPolyPolygon(aPolyPoly, 0.0);
+ drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ aPolyPoly,
+ 0.0);
}
-bool OpenGLSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
+bool OpenGLSalGraphicsImpl::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
{
VCL_GL_INFO("::drawPolyPolygon " << rPolyPolygon.getB2DRange());
- mpRenderList->addDrawPolyPolygon(rPolyPolygon, fTransparency, mnLineColor, mnFillColor, mrParent.getAntiAliasB2DDraw());
+
+ // Fallback: Transform to DeviceCoordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+ aPolyPolygon.transform(rObjectToDevice);
+
+ mpRenderList->addDrawPolyPolygon(
+ aPolyPolygon,
+ fTransparency,
+ mnLineColor,
+ mnFillColor,
+ mrParent.getAntiAliasB2DDraw());
+
PostBatchDraw();
return true;
}
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 3b8d2ee80d3c..f8ab00ea1494 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -279,7 +279,8 @@ void Qt5Graphics::drawPolyPolygon(sal_uInt32 nPolyCount, const sal_uInt32* pPoin
aPainter.update(aPath.boundingRect());
}
-bool Qt5Graphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency)
+bool Qt5Graphics::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
{
// ignore invisible polygons
if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor)
@@ -287,9 +288,13 @@ bool Qt5Graphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, doub
if ((fTransparency >= 1.0) || (fTransparency < 0))
return true;
+ // Fallback: Transform to DeviceCoordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+ aPolyPolygon.transform(rObjectToDevice);
+
QPainterPath aPath;
// ignore empty polygons
- if (!AddPolyPolygonToPath(aPath, rPolyPoly, !getAntiAliasB2DDraw(),
+ if (!AddPolyPolygonToPath(aPath, aPolyPolygon, !getAntiAliasB2DDraw(),
m_aLineColor != SALCOLOR_NONE))
return true;
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index 09adf784d2ad..59d836506b52 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -1072,13 +1072,15 @@ bool AquaSalGraphics::drawPolyLineBezier( sal_uInt32, const SalPoint*, const Pol
return false;
}
-bool AquaSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly,
- double fTransparency )
+bool AquaSalGraphics::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
{
DBG_DRAW_OPERATION("drawPolyPolygon", true);
// short circuit if there is nothing to do
- const int nPolyCount = rPolyPoly.count();
+ const int nPolyCount = rPolyPolygon.count();
if( nPolyCount <= 0 )
{
DBG_DRAW_OPERATION_EXIT_EARLY("drawPolyPolygon");
@@ -1092,12 +1094,16 @@ bool AquaSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly,
return true;
}
+ // Fallback: Transform to DeviceCoordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+ aPolyPolygon.transform(rObjectToDevice);
+
// setup poly-polygon path
CGMutablePathRef xPath = CGPathCreateMutable();
SAL_INFO( "vcl.cg", "CGPathCreateMutable() = " << xPath );
for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
{
- const basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx );
+ const basegfx::B2DPolygon rPolygon = rPolyPolygon.getB2DPolygon( nPolyIdx );
AddPolygonToPath( xPath, rPolygon, true, !getAntiAliasB2DDraw(), IsPenVisible() );
}
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 93fcfeca7df9..9e5c3bc8db72 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -155,7 +155,7 @@ void Scheduler::ImplDeInitScheduler()
|| !strcmp( pTask->GetDebugName(), "svtools::GraphicCache maReleaseTimer" )
|| !strcmp( pTask->GetDebugName(), "svtools::GraphicObject mpSwapOutTimer" )
|| !strcmp( pTask->GetDebugName(), "svx OLEObjCache pTimer UnloadCheck" )
- || !strcmp( pTask->GetDebugName(), "vcl::win GdiPlusBuffer aGdiPlusBuffer" )
+ || !strcmp( pTask->GetDebugName(), "vcl SystemDependentDataBuffer aSystemDependentDataBuffer" )
))
{
sIgnored = " (ignored)";
diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx
index ce3ed1393729..251da9e6b1a5 100644
--- a/vcl/source/app/svdata.cxx
+++ b/vcl/source/app/svdata.cxx
@@ -60,6 +60,9 @@
#if HAVE_FEATURE_OPENGL
#include <vcl/opengl/OpenGLContext.hxx>
#endif
+#include <basegfx/utils/systemdependentdata.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <o3tl/make_unique.hxx>
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
@@ -97,6 +100,135 @@ void ImplDeInitSVData()
pSVData->maPaperNames.clear();
}
+namespace
+{
+ typedef ::std::map< basegfx::SystemDependentData_SharedPtr, sal_uInt32 > EntryMap;
+
+ class SystemDependentDataBuffer : public basegfx::SystemDependentDataManager, protected cppu::BaseMutex
+ {
+ private:
+ std::unique_ptr<Timer> maTimer;
+ EntryMap maEntries;
+
+ DECL_LINK(implTimeoutHdl, Timer *, void);
+
+ public:
+ SystemDependentDataBuffer(const sal_Char* pDebugName)
+ : basegfx::SystemDependentDataManager(),
+ maTimer(o3tl::make_unique<Timer>(pDebugName)),
+ maEntries()
+ {
+ maTimer->SetTimeout(1000);
+ maTimer->SetInvokeHandler(LINK(this, SystemDependentDataBuffer, implTimeoutHdl));
+ }
+
+ virtual ~SystemDependentDataBuffer() override
+ {
+ flushAll();
+ }
+
+ void startUsage(basegfx::SystemDependentData_SharedPtr& rData) override
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ EntryMap::iterator aFound(maEntries.find(rData));
+
+ if(aFound == maEntries.end())
+ {
+ if(maEntries.empty() && maTimer)
+ {
+ maTimer->Start();
+ }
+
+ maEntries[rData] = rData->getHoldCycles();
+ }
+ }
+
+ void endUsage(basegfx::SystemDependentData_SharedPtr& rData) override
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ EntryMap::iterator aFound(maEntries.find(rData));
+
+ if(aFound != maEntries.end())
+ {
+ maEntries.erase(aFound);
+
+ if(maEntries.empty() && maTimer)
+ {
+ maTimer->Stop();
+ }
+ }
+ }
+
+ void touchUsage(basegfx::SystemDependentData_SharedPtr& rData) override
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ EntryMap::iterator aFound(maEntries.find(rData));
+
+ if(aFound != maEntries.end())
+ {
+ aFound->second = rData->getHoldCycles();
+ }
+ }
+
+ void flushAll() override
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ EntryMap::iterator aIter(maEntries.begin());
+
+ if(maTimer)
+ {
+ maTimer->Stop();
+ maTimer.reset();
+ }
+
+ while(aIter != maEntries.end())
+ {
+ EntryMap::iterator aDelete(aIter);
+ ++aIter;
+ maEntries.erase(aDelete);
+ }
+ }
+ };
+
+ IMPL_LINK_NOARG(SystemDependentDataBuffer, implTimeoutHdl, Timer *, void)
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ EntryMap::iterator aIter(maEntries.begin());
+
+ while(aIter != maEntries.end())
+ {
+ if(aIter->second)
+ {
+ aIter->second--;
+ ++aIter;
+ }
+ else
+ {
+ EntryMap::iterator aDelete(aIter);
+ ++aIter;
+ maEntries.erase(aDelete);
+
+ if(maEntries.empty() && maTimer)
+ {
+ maTimer->Stop();
+ }
+ }
+ }
+
+ if(!maEntries.empty() && maTimer)
+ {
+ maTimer->Start();
+ }
+ }
+}
+
+basegfx::SystemDependentDataManager& ImplGetSystemDependentDataManager()
+{
+ static SystemDependentDataBuffer aSystemDependentDataBuffer("vcl SystemDependentDataBuffer aSystemDependentDataBuffer");
+
+ return aSystemDependentDataBuffer;
+}
+
/// Returns either the application window, or the default GL context window
vcl::Window* ImplGetDefaultWindow()
{
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index beed24273e0d..b4cfa736792c 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -428,9 +428,6 @@ void DeInitVCL()
}
ImplSVData* pSVData = ImplGetSVData();
- // cleanup SystemDependentData
- SalGraphics::getSystemDependentDataManager().flushAll();
-
// lp#1560328: clear cache before disposing rest of VCL
if(pSVData->mpBlendFrameCache)
pSVData->mpBlendFrameCache->m_aLastResult.Clear();
@@ -481,6 +478,9 @@ void DeInitVCL()
pSVData->mpSettingsConfigItem.reset();
+ // empty and deactivate the SystemDependentDataManager
+ ImplGetSystemDependentDataManager().flushAll();
+
Scheduler::ImplDeInitScheduler();
pSVData->maWinData.maMsgBoxImgList.clear();
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index d39bd333a9cf..d28c751f42a9 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -31,11 +31,8 @@
#include <salgdi.hxx>
#include <salframe.hxx>
#include <basegfx/numeric/ftools.hxx> //for F_PI180
-#include <basegfx/utils/systemdependentdata.hxx>
-#include <cppuhelper/basemutex.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
-#include <o3tl/make_unique.hxx>
// The only common SalFrame method
@@ -69,131 +66,6 @@ SalGraphics::~SalGraphics()
{
}
-basegfx::SystemDependentDataManager& SalGraphics::getSystemDependentDataManager()
-{
- typedef ::std::map< basegfx::SystemDependentData_SharedPtr, sal_uInt32 > EntryMap;
-
- class SystemDependentDataBuffer : public basegfx::SystemDependentDataManager, protected cppu::BaseMutex, public Timer
- {
- private:
- EntryMap maEntries;
-
- public:
- SystemDependentDataBuffer( const sal_Char *pDebugName )
- : basegfx::SystemDependentDataManager(),
- Timer( pDebugName ),
- maEntries()
- {
- SetTimeout(1000);
- SetStatic();
- }
-
- virtual ~SystemDependentDataBuffer() override
- {
- Stop();
- }
-
- void startUsage(basegfx::SystemDependentData_SharedPtr& rData) override
- {
- ::osl::MutexGuard aGuard(m_aMutex);
- EntryMap::iterator aFound(maEntries.find(rData));
-
- if(aFound == maEntries.end())
- {
- if(maEntries.empty())
- {
- Start();
- }
-
- maEntries[rData] = rData->getHoldCycles();
- }
- }
-
- void endUsage(basegfx::SystemDependentData_SharedPtr& rData) override
- {
- ::osl::MutexGuard aGuard(m_aMutex);
- EntryMap::iterator aFound(maEntries.find(rData));
-
- if(aFound != maEntries.end())
- {
- maEntries.erase(aFound);
-
- if(maEntries.empty())
- {
- Stop();
- }
- }
- }
-
- void touchUsage(basegfx::SystemDependentData_SharedPtr& rData) override
- {
- ::osl::MutexGuard aGuard(m_aMutex);
- EntryMap::iterator aFound(maEntries.find(rData));
-
- if(aFound != maEntries.end())
- {
- aFound->second = rData->getHoldCycles();
- }
- }
-
- void flushAll() override
- {
- ::osl::MutexGuard aGuard(m_aMutex);
- EntryMap::iterator aIter(maEntries.begin());
-
- Stop();
-
- while(aIter != maEntries.end())
- {
- EntryMap::iterator aDelete(aIter);
- ++aIter;
- maEntries.erase(aDelete);
- }
- }
-
- // from parent Timer
- virtual void Invoke() override
- {
- ::osl::MutexGuard aGuard(m_aMutex);
- EntryMap::iterator aIter(maEntries.begin());
-
- while(aIter != maEntries.end())
- {
- if(aIter->second)
- {
- aIter->second--;
- ++aIter;
- }
- else
- {
- EntryMap::iterator aDelete(aIter);
- ++aIter;
- maEntries.erase(aDelete);
-
- if(maEntries.empty())
- {
- Stop();
- }
- }
- }
-
- if(!maEntries.empty())
- {
- Start();
- }
- }
- };
-
- static std::unique_ptr<SystemDependentDataBuffer> aSystemDependentDataBuffer;
-
- if(!aSystemDependentDataBuffer)
- {
- aSystemDependentDataBuffer = o3tl::make_unique<SystemDependentDataBuffer>(nullptr);
- }
-
- return *aSystemDependentDataBuffer.get();
-}
-
#if HAVE_FEATURE_OPENGL
namespace
@@ -589,17 +461,50 @@ void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
drawPolyPolygon( nPoly, pPoints, pPtAry );
}
-bool SalGraphics::DrawPolyPolygon( const basegfx::B2DPolyPolygon& i_rPolyPolygon, double i_fTransparency, const OutputDevice* i_pOutDev )
+bool SalGraphics::DrawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& i_rPolyPolygon,
+ double i_fTransparency,
+ const OutputDevice* i_pOutDev)
{
- bool bRet = false;
if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
{
- basegfx::B2DPolyPolygon aMirror( mirror( i_rPolyPolygon, i_pOutDev ) );
- bRet = drawPolyPolygon( aMirror, i_fTransparency );
+ // mirroring set
+ const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
+
+ if(!rMirror.isIdentity())
+ {
+ if(rObjectToDevice.isIdentity())
+ {
+ // There is no ObjectToDevice transformation set. We can just
+ // use rMirror, that would be the result of the linear combination
+ return drawPolyPolygon(
+ rMirror,
+ i_rPolyPolygon,
+ i_fTransparency);
+ }
+ else
+ {
+ // Create the linear combination
+ basegfx::B2DHomMatrix aLinearCombination(rObjectToDevice);
+ basegfx::B2DHomMatrix aObjectToDeviceInv(rObjectToDevice);
+
+ aLinearCombination = rMirror * aLinearCombination;
+ aObjectToDeviceInv.invert();
+ aLinearCombination = aObjectToDeviceInv * aLinearCombination;
+
+ return drawPolyPolygon(
+ aLinearCombination,
+ i_rPolyPolygon,
+ i_fTransparency);
+ }
+ }
}
- else
- bRet = drawPolyPolygon( i_rPolyPolygon, i_fTransparency );
- return bRet;
+
+ return drawPolyPolygon(
+ rObjectToDevice,
+ i_rPolyPolygon,
+ i_fTransparency);
}
bool SalGraphics::DrawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev )
diff --git a/vcl/source/outdev/line.cxx b/vcl/source/outdev/line.cxx
index fe16d676c29f..fecacba8f641 100644
--- a/vcl/source/outdev/line.cxx
+++ b/vcl/source/outdev/line.cxx
@@ -133,10 +133,6 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
aB2DPolyLine.transform( aTransform );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
- // if(mnAntialiasing & AntialiasingFlags::PixelSnapHairline)
- // {
- // aB2DPolyLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
- // }
if( mpGraphics->DrawPolyLine(
basegfx::B2DHomMatrix(),
@@ -287,7 +283,11 @@ void OutputDevice::drawLine( basegfx::B2DPolyPolygon aLinePolyPolygon, const Lin
if(bTryAA)
{
- bDone = mpGraphics->DrawPolyPolygon(aFillPolyPolygon, 0.0, this);
+ bDone = mpGraphics->DrawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ aFillPolyPolygon,
+ 0.0,
+ this);
}
if(!bDone)
diff --git a/vcl/source/outdev/polygon.cxx b/vcl/source/outdev/polygon.cxx
index 94ad52a79dbd..1496b1a1daf8 100644
--- a/vcl/source/outdev/polygon.cxx
+++ b/vcl/source/outdev/polygon.cxx
@@ -70,17 +70,23 @@ void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly )
RasterOp::OverPaint == GetRasterOp() &&
(IsLineColor() || IsFillColor()))
{
- const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
+ const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
bool bSuccess(true);
- // transform the polygon and ensure closed
- aB2DPolyPolygon.transform(aTransform);
- aB2DPolyPolygon.setClosed(true);
+ // ensure closed - may be asserted, will prevent buffering
+ if(!aB2DPolyPolygon.isClosed())
+ {
+ aB2DPolyPolygon.setClosed(true);
+ }
if(IsFillColor())
{
- bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
+ bSuccess = mpGraphics->DrawPolyPolygon(
+ aTransform,
+ aB2DPolyPolygon,
+ 0.0,
+ this);
}
if(bSuccess && IsLineColor())
@@ -88,15 +94,10 @@ void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly )
const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
- // if(mnAntialiasing & AntialiasingFlags::PixelSnapHairline)
- // {
- // aB2DPolyPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
- // }
-
for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++)
{
bSuccess = mpGraphics->DrawPolyLine(
- basegfx::B2DHomMatrix(),
+ aTransform,
aB2DPolyPolygon.getB2DPolygon(a),
0.0,
aB2DLineWidth,
@@ -187,17 +188,23 @@ void OutputDevice::DrawPolygon( const tools::Polygon& rPoly )
RasterOp::OverPaint == GetRasterOp() &&
(IsLineColor() || IsFillColor()))
{
- const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
+ const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon());
bool bSuccess(true);
- // transform the polygon and ensure closed
- aB2DPolygon.transform(aTransform);
- aB2DPolygon.setClosed(true);
+ // ensure closed - maybe assert, hinders bufering
+ if(!aB2DPolygon.isClosed())
+ {
+ aB2DPolygon.setClosed(true);
+ }
if(IsFillColor())
{
- bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(aB2DPolygon), 0.0, this);
+ bSuccess = mpGraphics->DrawPolyPolygon(
+ aTransform,
+ basegfx::B2DPolyPolygon(aB2DPolygon),
+ 0.0,
+ this);
}
if(bSuccess && IsLineColor())
@@ -205,13 +212,8 @@ void OutputDevice::DrawPolygon( const tools::Polygon& rPoly )
const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
- // if(mnAntialiasing & AntialiasingFlags::PixelSnapHairline)
- // {
- // aB2DPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
- // }
-
bSuccess = mpGraphics->DrawPolyLine(
- basegfx::B2DHomMatrix(),
+ aTransform,
aB2DPolygon,
0.0,
aB2DLineWidth,
@@ -298,13 +300,19 @@ void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyP
basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
bool bSuccess(true);
- // transform the polygon and ensure closed
- aB2DPolyPolygon.transform(aTransform);
- aB2DPolyPolygon.setClosed(true);
+ // ensure closed - maybe assert, hinders buffering
+ if(!aB2DPolyPolygon.isClosed())
+ {
+ aB2DPolyPolygon.setClosed(true);
+ }
if(IsFillColor())
{
- bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
+ bSuccess = mpGraphics->DrawPolyPolygon(
+ aTransform,
+ aB2DPolyPolygon,
+ 0.0,
+ this);
}
if(bSuccess && IsLineColor())
@@ -312,15 +320,10 @@ void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyP
const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
- // if(mnAntialiasing & AntialiasingFlags::PixelSnapHairline)
- // {
- // aB2DPolyPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
- // }
-
for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++)
{
bSuccess = mpGraphics->DrawPolyLine(
- basegfx::B2DHomMatrix(),
+ aTransform,
aB2DPolyPolygon.getB2DPolygon(a),
0.0,
aB2DLineWidth,
diff --git a/vcl/source/outdev/polyline.cxx b/vcl/source/outdev/polyline.cxx
index b5c06b9aa411..da8be42cd304 100644
--- a/vcl/source/outdev/polyline.cxx
+++ b/vcl/source/outdev/polyline.cxx
@@ -71,14 +71,6 @@ void OutputDevice::DrawPolyLine( const tools::Polygon& rPoly )
const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
- // transform the polygon - do not (!)
- // aB2DPolyLine.transform( aTransform );
-
- // if(mnAntialiasing & AntialiasingFlags::PixelSnapHairline)
- // {
- // aB2DPolyLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
- // }
-
if(mpGraphics->DrawPolyLine(
aTransform,
aB2DPolyLine,
@@ -350,27 +342,7 @@ bool OutputDevice::DrawPolyLineDirect(
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);
-
- // transform the line width if used
- // if( fLineWidth != 0.0 )
- // {
- // aB2DLineWidth = aTransform * basegfx::B2DVector( fLineWidth, fLineWidth );
- // }
-
- // transform the polygon - no!
- // basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
- // aB2DPolygon.transform(aTransform);
-
const bool bPixelSnapHairline((mnAntialiasing & AntialiasingFlags::PixelSnapHairline) && rB2DPolygon.count() < 1000);
- // if((mnAntialiasing & AntialiasingFlags::PixelSnapHairline) &&
- // aB2DPolygon.count() < 1000)
- // {
- // // #i98289#, #i101491#
- // // better to remove doubles on device coordinates. Also assume from a given amount
- // // of points that the single edges are not long enough to smooth
- // aB2DPolygon.removeDoublePoints();
- // aB2DPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
- // }
// draw the polyline
bool bDrawSuccess = mpGraphics->DrawPolyLine(
diff --git a/vcl/source/outdev/transparent.cxx b/vcl/source/outdev/transparent.cxx
index ecd63b642b47..5a9bd599a6ff 100644
--- a/vcl/source/outdev/transparent.cxx
+++ b/vcl/source/outdev/transparent.cxx
@@ -212,7 +212,10 @@ void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask
// void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
// so when changes are made here do not forget to make changes there, too
-void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
+void OutputDevice::DrawTransparent(
+ const basegfx::B2DHomMatrix& rObjectTransform,
+ const basegfx::B2DPolyPolygon& rB2DPolyPoly,
+ double fTransparency)
{
assert(!is_double_buffered_window());
@@ -241,16 +244,27 @@ void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly,
(RasterOp::OverPaint == GetRasterOp()) )
{
// b2dpolygon support not implemented yet on non-UNX platforms
- const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
- // transform the polygon into device space and ensure it is closed
- aB2DPolyPolygon.transform( aTransform );
- aB2DPolyPolygon.setClosed( true );
+ // ensure it is closed
+ if(!aB2DPolyPolygon.isClosed())
+ {
+ // maybe assert, prevents buffering due to making a copy
+ aB2DPolyPolygon.setClosed( true );
+ }
+
+ // create ObjectToDevice transformation
+ const basegfx::B2DHomMatrix aFullTransform(ImplGetDeviceTransformation() * rObjectTransform);
+ bool bDrawnOk(true);
- bool bDrawnOk = true;
if( IsFillColor() )
- bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
+ {
+ bDrawnOk = mpGraphics->DrawPolyPolygon(
+ aFullTransform,
+ aB2DPolyPolygon,
+ fTransparency,
+ this);
+ }
if( bDrawnOk && IsLineColor() )
{
@@ -263,7 +277,7 @@ void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly,
const basegfx::B2DPolygon aOnePoly(aB2DPolyPolygon.getB2DPolygon(nPolyIdx));
mpGraphics->DrawPolyLine(
- basegfx::B2DHomMatrix(),
+ aFullTransform,
aOnePoly,
fTransparency,
aHairlineWidth,
@@ -338,9 +352,8 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
InitFillColor();
// get the polygon in device coordinates
- basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
- const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- aB2DPolyPolygon.transform( aTransform );
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
+ const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
const double fTransparency = 0.01 * nTransparencePercent;
if( mbFillColor )
@@ -354,13 +367,18 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
// functionality and we use the fallback some lines below (which is not very good,
// though. For now, WinSalGraphics::drawPolyPolygon will detect printer usage and
// correct the wrong mapping (see there for details)
- bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
+ bDrawn = mpGraphics->DrawPolyPolygon(
+ aTransform,
+ aB2DPolyPolygon,
+ fTransparency,
+ this);
}
if( mbLineColor )
{
// disable the fill color for now
mpGraphics->SetFillColor();
+
// draw the border line
const basegfx::B2DVector aLineWidths( 1, 1 );
const sal_uInt32 nPolyCount(aB2DPolyPolygon.count());
@@ -371,7 +389,7 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
const basegfx::B2DPolygon aPolygon(aB2DPolyPolygon.getB2DPolygon(nPolyIdx));
bDrawn = mpGraphics->DrawPolyLine(
- basegfx::B2DHomMatrix(),
+ aTransform,
aPolygon,
fTransparency,
aLineWidths,
@@ -381,6 +399,7 @@ bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly
bPixelSnapHairline,
this );
}
+
// prepare to restore the fill color
mbInitFillColor = mbFillColor;
}
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index c650f9dd4dad..a5fcf86cd3a7 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -1442,10 +1442,13 @@ bool X11SalGraphicsImpl::drawEPS( long,long,long,long,void*,sal_uLong )
}
// draw a poly-polygon
-bool X11SalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency )
+bool X11SalGraphicsImpl::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
{
// nothing to do for empty polypolygons
- const int nOrigPolyCount = rOrigPolyPoly.count();
+ const int nOrigPolyCount = rPolyPolygon.count();
if( nOrigPolyCount <= 0 )
return true;
@@ -1464,21 +1467,24 @@ bool X11SalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPo
if( pRenderEnv )
return false;
+ // Fallback: Transform to DeviceCoordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+ aPolyPolygon.transform(rObjectToDevice);
+
// snap to raster if requested
- basegfx::B2DPolyPolygon aPolyPoly = rOrigPolyPoly;
const bool bSnapToRaster = !mrParent.getAntiAliasB2DDraw();
if( bSnapToRaster )
- aPolyPoly = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges( aPolyPoly );
+ aPolyPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges( aPolyPolygon );
// don't bother with polygons outside of visible area
const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() );
- aPolyPoly = basegfx::utils::clipPolyPolygonOnRange( aPolyPoly, aViewRange, true, false );
- if( !aPolyPoly.count() )
+ aPolyPolygon = basegfx::utils::clipPolyPolygonOnRange( aPolyPolygon, aViewRange, true, false );
+ if( !aPolyPolygon.count() )
return true;
// tessellate the polypolygon into trapezoids
basegfx::B2DTrapezoidVector aB2DTrapVector;
- basegfx::utils::trapezoidSubdivide( aB2DTrapVector, aPolyPoly );
+ basegfx::utils::trapezoidSubdivide( aB2DTrapVector, aPolyPolygon );
const int nTrapCount = aB2DTrapVector.size();
if( !nTrapCount )
return true;
@@ -1654,7 +1660,12 @@ bool X11SalGraphicsImpl::drawPolyLine(
for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
{
const basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( nPolyIdx ) );
- bDrawnOk = drawPolyPolygon( aOnePoly, fTransparency );
+
+ bDrawnOk = drawPolyPolygon(
+ basegfx::B2DHomMatrix(),
+ aOnePoly,
+ fTransparency);
+
if( !bDrawnOk )
break;
}
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index f738e1e996ea..ac80ec6f0c40 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -157,7 +157,11 @@ public:
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index c6eff6d45304..632d08d1a35b 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -577,14 +577,17 @@ css::uno::Any X11SalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rS
#endif // ENABLE_CAIRO_CANVAS
// draw a poly-polygon
-bool X11SalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency )
+bool X11SalGraphics::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
{
if(fTransparency >= 1.0)
{
return true;
}
- const sal_uInt32 nPolyCount(rOrigPolyPoly.count());
+ const sal_uInt32 nPolyCount(rPolyPolygon.count());
if(nPolyCount <= 0)
{
@@ -592,6 +595,10 @@ bool X11SalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPolyPo
}
#if ENABLE_CAIRO_CANVAS
+ // Fallback: Transform to DeviceCoordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+ aPolyPolygon.transform(rObjectToDevice);
+
if(SALCOLOR_NONE == mnFillColor && SALCOLOR_NONE == mnPenColor)
{
return true;
@@ -602,12 +609,11 @@ bool X11SalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPolyPo
if (!m_bOpenGL && bUseCairoForPolygons && SupportsCairo())
{
// snap to raster if requested
- basegfx::B2DPolyPolygon aPolyPoly(rOrigPolyPoly);
const bool bSnapPoints(!getAntiAliasB2DDraw());
if(bSnapPoints)
{
- aPolyPoly = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPoly);
+ aPolyPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygon);
}
cairo_t* cr = getCairoContext();
@@ -615,7 +621,7 @@ bool X11SalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPolyPo
for(sal_uInt32 a(0); a < nPolyCount; ++a)
{
- const basegfx::B2DPolygon aPolygon(aPolyPoly.getB2DPolygon(a));
+ const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a));
const sal_uInt32 nPointCount(aPolygon.count());
if(nPointCount)
@@ -684,7 +690,10 @@ bool X11SalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rOrigPolyPo
}
#endif // ENABLE_CAIRO_CANVAS
- return mxImpl->drawPolyPolygon( rOrigPolyPoly, fTransparency );
+ return mxImpl->drawPolyPolygon(
+ rObjectToDevice,
+ rPolyPolygon,
+ fTransparency);
}
#if ENABLE_CAIRO_CANVAS
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index 4ee35c8b72eb..3a8f951ea03a 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -404,7 +404,10 @@ void GenPspGraphics::drawPolyPolygon( sal_uInt32 nPoly,
m_pPrinterGfx->DrawPolyPolygon (nPoly, pPoints, reinterpret_cast<const Point**>(pPtAry));
}
-bool GenPspGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
+bool GenPspGraphics::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& /*rObjectToDevice*/,
+ const basegfx::B2DPolyPolygon&,
+ double /*fTransparency*/)
{
// TODO: implement and advertise OutDevSupportType::B2DDraw support
return false;
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index 33d89b6c94e1..4dcd86a4f405 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -1951,71 +1951,6 @@ void impAddB2DPolygonToGDIPlusGraphicsPathReal(
}
}
-bool WinSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
-{
- const sal_uInt32 nCount(rPolyPolygon.count());
-
- if(mbBrush && nCount && (fTransparency >= 0.0 && fTransparency < 1.0))
- {
- Gdiplus::Graphics aGraphics(mrParent.getHDC());
- const sal_uInt8 aTrans(sal_uInt8(255) - static_cast<sal_uInt8>(basegfx::fround(fTransparency * 255.0)));
- const Gdiplus::Color aTestColor(aTrans, maFillColor.GetRed(), maFillColor.GetGreen(), maFillColor.GetBlue());
- const Gdiplus::SolidBrush aSolidBrush(aTestColor.GetValue());
- Gdiplus::GraphicsPath aGraphicsPath(Gdiplus::FillModeAlternate);
-
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- if(0 != a)
- {
- // #i101491# not needed for first run
- aGraphicsPath.StartFigure();
- }
-
- impAddB2DPolygonToGDIPlusGraphicsPathReal(
- aGraphicsPath,
- rPolyPolygon.getB2DPolygon(a),
- basegfx::B2DHomMatrix(),
- false,
- false);
-
- aGraphicsPath.CloseFigure();
- }
-
- if(mrParent.getAntiAliasB2DDraw())
- {
- aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- }
- else
- {
- aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone);
- }
-
- if(mrParent.isPrinter())
- {
- // #i121591#
- // Normally GdiPlus should not be used for printing at all since printers cannot
- // print transparent filled polygon geometry and normally this does not happen
- // since OutputDevice::RemoveTransparenciesFromMetaFile is used as preparation
- // and no transparent parts should remain for printing. But this can be overridden
- // by the user and thus happens. This call can only come (currently) from
- // OutputDevice::DrawTransparent, see comments there with the same TaskID.
- // If it is used, the mapping for the printer is wrong and needs to be corrected. I
- // checked that there is *no* transformation set and estimated that a stable factor
- // dependent of the printer's DPI is used. Create and set a transformation here to
- // correct this.
- const Gdiplus::REAL aDpiX(aGraphics.GetDpiX());
- const Gdiplus::REAL aDpiY(aGraphics.GetDpiY());
-
- aGraphics.ResetTransform();
- aGraphics.ScaleTransform(Gdiplus::REAL(100.0) / aDpiX, Gdiplus::REAL(100.0) / aDpiY, Gdiplus::MatrixOrderAppend);
- }
-
- aGraphics.FillPath(&aSolidBrush, &aGraphicsPath);
- }
-
- return true;
-}
-
class SystemDependentData_GraphicsPath : public basegfx::SystemDependentData
{
private:
@@ -2040,6 +1975,150 @@ SystemDependentData_GraphicsPath::SystemDependentData_GraphicsPath(
{
}
+bool WinSalGraphicsImpl::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
+{
+ const sal_uInt32 nCount(rPolyPolygon.count());
+
+ if(!mbBrush || 0 == nCount || fTransparency < 0.0 || fTransparency > 1.0)
+ {
+ return true;
+ }
+
+ Gdiplus::Graphics aGraphics(mrParent.getHDC());
+ const sal_uInt8 aTrans(sal_uInt8(255) - static_cast<sal_uInt8>(basegfx::fround(fTransparency * 255.0)));
+ const Gdiplus::Color aTestColor(aTrans, maFillColor.GetRed(), maFillColor.GetGreen(), maFillColor.GetBlue());
+ const Gdiplus::SolidBrush aSolidBrush(aTestColor.GetValue());
+
+ // Set full (Object-to-Device) transformation - if used
+ if(rObjectToDevice.isIdentity())
+ {
+ aGraphics.ResetTransform();
+ }
+ else
+ {
+ Gdiplus::Matrix aMatrix;
+
+ aMatrix.SetElements(
+ rObjectToDevice.get(0, 0),
+ rObjectToDevice.get(1, 0),
+ rObjectToDevice.get(0, 1),
+ rObjectToDevice.get(1, 1),
+ rObjectToDevice.get(0, 2),
+ rObjectToDevice.get(1, 2));
+ aGraphics.SetTransform(&aMatrix);
+ }
+
+ // try to access buffered data
+ std::shared_ptr<SystemDependentData_GraphicsPath> pSystemDependentData_GraphicsPath(
+ rPolyPolygon.getSystemDependentData<SystemDependentData_GraphicsPath>());
+
+ if(!pSystemDependentData_GraphicsPath)
+ {
+ // add to buffering mechanism
+ pSystemDependentData_GraphicsPath = rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>(
+ ImplGetSystemDependentDataManager());
+
+ // Note: In principle we could use the same buffered geometry at line
+ // and fill polygons. Checked that in a first try, used
+ // GraphicsPath::AddPath from Gdiplus combined with below used
+ // StartFigure/CloseFigure, worked well (thus the line-draw version
+ // may create non-cloded partial Polygon data).
+ //
+ // But in current reality it gets not used due to e.g.
+ // SdrPathPrimitive2D::create2DDecomposition creating transformed
+ // line and fill polygon-primitives (what could be changed).
+ //
+ // There will probably be more hindrances here in other rendering paths
+ // which could all be found - intention to do this would be: Use more
+ // transformations, less modifications of B2DPolygons/B2DPolyPolygons.
+ //
+ // A fix for SdrPathPrimitive2D would be to create the sub-geometry
+ // 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
+ // for the fill case (see ::drawPolyLine bnelow) - thus we would need a
+ // bool and/or two system-dependent paths buffered - doable, but complicated.
+ //
+ // All in all: Make B2DPolyPolygon a SystemDependentDataProvider and buffer
+ // the whole to-be-filled PolyPolygon independent from evtl. line-polygon
+ // (at least for now...)
+
+ // create data
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ if(0 != a)
+ {
+ // #i101491# not needed for first run
+ pSystemDependentData_GraphicsPath->getGraphicsPath().StartFigure();
+ }
+
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(
+ pSystemDependentData_GraphicsPath->getGraphicsPath(),
+ rPolyPolygon.getB2DPolygon(a),
+ rObjectToDevice, // not used due to the two 'false' values below, but to not forget later
+ false,
+ false);
+
+ pSystemDependentData_GraphicsPath->getGraphicsPath().CloseFigure();
+ }
+ }
+
+ if(mrParent.getAntiAliasB2DDraw())
+ {
+ aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
+ }
+ else
+ {
+ aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone);
+ }
+
+ if(mrParent.isPrinter())
+ {
+ // #i121591#
+ // Normally GdiPlus should not be used for printing at all since printers cannot
+ // print transparent filled polygon geometry and normally this does not happen
+ // since OutputDevice::RemoveTransparenciesFromMetaFile is used as preparation
+ // and no transparent parts should remain for printing. But this can be overridden
+ // by the user and thus happens. This call can only come (currently) from
+ // OutputDevice::DrawTransparent, see comments there with the same TaskID.
+ // If it is used, the mapping for the printer is wrong and needs to be corrected. I
+ // checked that there is *no* transformation set and estimated that a stable factor
+ // dependent of the printer's DPI is used. Create and set a transformation here to
+ // correct this.
+ const Gdiplus::REAL aDpiX(aGraphics.GetDpiX());
+ const Gdiplus::REAL aDpiY(aGraphics.GetDpiY());
+
+ // Now the transformation maybe/is already used (see above), so do
+ // modify it without resetting to not destroy it.
+ // I double-checked with MS docu that Gdiplus::MatrixOrderAppend does what
+ // we need - in our notation, would be a multiply from left to execute
+ // current transform first and this scale last.
+ // I tried to trigger this code using Print from the menu and various
+ // targets, but got no hit, thus maybe obsolete anyways. If someone knows
+ // more, feel free to remove it.
+ // One more hint: This *may* also be needed now in ::drawPolyLine below
+ // since it also uses transformations now.
+ //
+ // aGraphics.ResetTransform();
+
+ aGraphics.ScaleTransform(
+ Gdiplus::REAL(100.0) / aDpiX,
+ Gdiplus::REAL(100.0) / aDpiY,
+ Gdiplus::MatrixOrderAppend);
+ }
+
+ // use created or buffered data
+ aGraphics.FillPath(
+ &aSolidBrush,
+ &pSystemDependentData_GraphicsPath->getGraphicsPath());
+
+ return true;
+}
+
bool WinSalGraphicsImpl::drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
const basegfx::B2DPolygon& rPolygon,
@@ -2062,15 +2141,24 @@ bool WinSalGraphicsImpl::drawPolyLine(
bool bNoLineJoin(false);
Gdiplus::Matrix aMatrix;
- // Set full (Object-to-Device) transformation
- aMatrix.SetElements(
- rObjectToDevice.get(0, 0),
- rObjectToDevice.get(1, 0),
- rObjectToDevice.get(0, 1),
- rObjectToDevice.get(1, 1),
- rObjectToDevice.get(0, 2),
- rObjectToDevice.get(1, 2));
- aGraphics.SetTransform(&aMatrix);
+ // Set full (Object-to-Device) transformation - if used
+ if(rObjectToDevice.isIdentity())
+ {
+ aGraphics.ResetTransform();
+ }
+ else
+ {
+ Gdiplus::Matrix aMatrix;
+
+ aMatrix.SetElements(
+ rObjectToDevice.get(0, 0),
+ rObjectToDevice.get(1, 0),
+ rObjectToDevice.get(0, 1),
+ rObjectToDevice.get(1, 1),
+ rObjectToDevice.get(0, 2),
+ rObjectToDevice.get(1, 2));
+ aGraphics.SetTransform(&aMatrix);
+ }
switch(eLineJoin)
{
@@ -2145,7 +2233,7 @@ bool WinSalGraphicsImpl::drawPolyLine(
{
// add to buffering mechanism
pSystemDependentData_GraphicsPath = rPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>(
- SalGraphics::getSystemDependentDataManager());
+ ImplGetSystemDependentDataManager());
// fill data of buffered data
pSystemDependentData_GraphicsPath->setPixelSnapHairline(bPixelSnapHairline);
diff --git a/vcl/win/gdi/gdiimpl.hxx b/vcl/win/gdi/gdiimpl.hxx
index 83d4125207a2..94a6de0e1e44 100644
--- a/vcl/win/gdi/gdiimpl.hxx
+++ b/vcl/win/gdi/gdiimpl.hxx
@@ -106,7 +106,11 @@ public:
virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) override;
virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) override;
- virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override;
+
+ virtual bool drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&,
+ double fTransparency) override;
virtual bool drawPolyLine(
const basegfx::B2DHomMatrix& rObjectToDevice,
diff --git a/vcl/win/gdi/salbmp.cxx b/vcl/win/gdi/salbmp.cxx
index b61103e17067..664eedb6d269 100644
--- a/vcl/win/gdi/salbmp.cxx
+++ b/vcl/win/gdi/salbmp.cxx
@@ -146,7 +146,7 @@ std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap(const WinS
{
// add to buffering mechanism
pSystemDependentData_GdiPlusBitmap = addOrReplaceSystemDependentData<SystemDependentData_GdiPlusBitmap>(
- SalGraphics::getSystemDependentDataManager());
+ ImplGetSystemDependentDataManager());
// create and set data
if(pAlphaSource)
diff --git a/vcl/win/gdi/salgdi_gdiplus.cxx b/vcl/win/gdi/salgdi_gdiplus.cxx
index 1f536e1843e6..99c7d0e506e9 100644
--- a/vcl/win/gdi/salgdi_gdiplus.cxx
+++ b/vcl/win/gdi/salgdi_gdiplus.cxx
@@ -26,9 +26,15 @@
#include "gdiimpl.hxx"
-bool WinSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
+bool WinSalGraphics::drawPolyPolygon(
+ const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
{
- return mpImpl->drawPolyPolygon( rPolyPolygon, fTransparency );
+ return mpImpl->drawPolyPolygon(
+ rObjectToDevice,
+ rPolyPolygon,
+ fTransparency);
}
bool WinSalGraphics::drawPolyLine(