diff options
-rw-r--r-- | basegfx/source/tools/systemdependentdata.cxx | 47 | ||||
-rw-r--r-- | include/basegfx/utils/systemdependentdata.hxx | 12 | ||||
-rw-r--r-- | vcl/headless/svpgdi.cxx | 18 | ||||
-rw-r--r-- | vcl/source/app/svdata.cxx | 4 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/gdiimpl.cxx | 14 | ||||
-rw-r--r-- | vcl/win/gdi/gdiimpl.cxx | 96 | ||||
-rw-r--r-- | vcl/win/gdi/salbmp.cxx | 88 |
7 files changed, 236 insertions, 43 deletions
diff --git a/basegfx/source/tools/systemdependentdata.cxx b/basegfx/source/tools/systemdependentdata.cxx index 4153d35f7d55..c727462c7191 100644 --- a/basegfx/source/tools/systemdependentdata.cxx +++ b/basegfx/source/tools/systemdependentdata.cxx @@ -8,6 +8,7 @@ */ #include <basegfx/utils/systemdependentdata.hxx> +#include <math.h> namespace basegfx { @@ -62,7 +63,8 @@ namespace basegfx { SystemDependentData::SystemDependentData( SystemDependentDataManager& rSystemDependentDataManager) - : mrSystemDependentDataManager(rSystemDependentDataManager) + : mrSystemDependentDataManager(rSystemDependentDataManager), + mnCalculatedCycles(0) { } @@ -70,6 +72,49 @@ namespace basegfx { } + sal_uInt32 SystemDependentData::calculateCombinedHoldCyclesInSeconds() const + { + if(0 == mnCalculatedCycles) + { + const sal_Int64 nBytes(estimateUsageInBytes()); + const sal_uInt32 nSeconds(getHoldCyclesInSeconds()); + + // default is Seconds (minimal is one) + sal_uInt32 nResult(0 == nSeconds ? 1 : nSeconds); + + if(0 != nBytes) + { + // use sqrt to get some curved shape. With a default of 60s we get + // a single second at 3600 byte. To get close to 10mb, multiply by + // a corresponding scaling factor + const double fScaleToMB(3600.0 / (1024.0 * 1024.0 * 10.0)); + + // also use a multiplier to move the start point higer + const double fMultiplierSeconds(10.0); + + // calculate + nResult = static_cast<sal_uInt32>((fMultiplierSeconds * nSeconds) / sqrt(nBytes * fScaleToMB)); + + // minimal value is 1 + if(nResult < 1) + { + nResult = 1; + } + + // maximal value is nSeconds + if(nResult > nSeconds) + { + nResult = nSeconds; + } + } + + // set locally (once, on-demand created, non-zero) + const_cast<SystemDependentData*>(this)->mnCalculatedCycles = nResult < 1 ? 1 : nResult; + } + + return mnCalculatedCycles; + } + sal_uInt32 SystemDependentData::getHoldCyclesInSeconds() const { // default implementation returns 60(s) diff --git a/include/basegfx/utils/systemdependentdata.hxx b/include/basegfx/utils/systemdependentdata.hxx index 920a55043870..d5cc8d645eb6 100644 --- a/include/basegfx/utils/systemdependentdata.hxx +++ b/include/basegfx/utils/systemdependentdata.hxx @@ -89,6 +89,12 @@ namespace basegfx // a single, globally used one, but not necessarily SystemDependentDataManager& mrSystemDependentDataManager; + // Buffered CalculatedCycles, result of estimations using + // getHoldCyclesInSeconds and estimateUsageInBytes, executed + // using getHoldCyclesInSeconds. StartValue is 0 to detect + // not-yet-calculated state + sal_uInt32 mnCalculatedCycles; + public: SystemDependentData( SystemDependentDataManager& rSystemDependentDataManager); @@ -103,6 +109,12 @@ namespace basegfx // using getSystemDependentDataManager() SystemDependentDataManager& getSystemDependentDataManager() { return mrSystemDependentDataManager; } + // Calculate HoldCyclesInSeconds based on using + // getHoldCyclesInSeconds and estimateUsageInBytes, the + // result is crated once on-demand and buffered in + // mnCalculatedCycles + sal_uInt32 calculateCombinedHoldCyclesInSeconds() const; + // Number of cycles a SystemDependentDataManager should/might // hold this instance in seconds - does not have to be used, // but should be. Default implementation returns 60(s). Override to diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index b1f622904b5f..e42eb3ed3eaa 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -1056,6 +1056,8 @@ public: cairo_path_t* getCairoPath() { return mpCairoPath; } bool getNoJoin() const { return mbNoJoin; } bool getAntiAliasB2DDraw() const { return mbAntiAliasB2DDraw; } + + virtual sal_Int64 estimateUsageInBytes() const override; }; SystemDependentData_CairoPath::SystemDependentData_CairoPath( @@ -1079,6 +1081,22 @@ SystemDependentData_CairoPath::~SystemDependentData_CairoPath() } } +sal_Int64 SystemDependentData_CairoPath::estimateUsageInBytes() const +{ + sal_Int64 nRetval(0); + + if(nullptr != mpCairoPath) + { + // per node + // - num_data incarnations of + // - sizeof(cairo_path_data_t) which is a union of defines and point data + // thus may 2 x sizeof(double) + nRetval = mpCairoPath->num_data * sizeof(cairo_path_data_t); + } + + return nRetval; +} + bool SvpSalGraphics::drawPolyLine( const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolygon& rPolyLine, diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index d0a0cee244b0..edbcc3b4e870 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -139,7 +139,7 @@ namespace maTimer->Start(); } - maEntries[rData] = rData->getHoldCyclesInSeconds(); + maEntries[rData] = rData->calculateCombinedHoldCyclesInSeconds(); } } @@ -166,7 +166,7 @@ namespace if(aFound != maEntries.end()) { - aFound->second = rData->getHoldCyclesInSeconds(); + aFound->second = rData->calculateCombinedHoldCyclesInSeconds(); } } diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx index 0bfe098e7ef4..7ed38cc6eab5 100644 --- a/vcl/unx/generic/gdi/gdiimpl.cxx +++ b/vcl/unx/generic/gdi/gdiimpl.cxx @@ -1675,6 +1675,8 @@ public: const basegfx::B2DLineJoin& getJoin() const { return meJoin; } const css::drawing::LineCap& getCap() const { return meCap; } double getMiterMinimumAngle() const { return mfMiterMinimumAngle; } + + virtual sal_Int64 estimateUsageInBytes() const override; }; SystemDependentData_Triangulation::SystemDependentData_Triangulation( @@ -1693,6 +1695,18 @@ SystemDependentData_Triangulation::SystemDependentData_Triangulation( { } +sal_Int64 SystemDependentData_Triangulation::estimateUsageInBytes() const +{ + sal_Int64 nRetval(0); + + if(!maTriangles.empty()) + { + nRetval = maTriangles.size() * sizeof(basegfx::triangulator::B2DTriangle); + } + + return nRetval; +} + bool X11SalGraphicsImpl::drawPolyLine( const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolygon& rPolygon, diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx index d446ec877a98..a77e26f0e180 100644 --- a/vcl/win/gdi/gdiimpl.cxx +++ b/vcl/win/gdi/gdiimpl.cxx @@ -1955,33 +1955,57 @@ class SystemDependentData_GraphicsPath : public basegfx::SystemDependentData { private: // the path data itself - Gdiplus::GraphicsPath maGraphicsPath; + std::shared_ptr<Gdiplus::GraphicsPath> mpGraphicsPath; // all other values the triangulation is based on and // need to be compared with to check for data validity - bool mbNoLineJoin; + bool mbNoLineJoin; public: SystemDependentData_GraphicsPath( basegfx::SystemDependentDataManager& rSystemDependentDataManager, + std::shared_ptr<Gdiplus::GraphicsPath>& rpGraphicsPath, bool bNoLineJoin); - // non-const getter to allow manipulation. That way, we do not need - // to copy it (with unknown costs) - Gdiplus::GraphicsPath& getGraphicsPath() { return maGraphicsPath; } + + // read access to Gdiplus::GraphicsPath + std::shared_ptr<Gdiplus::GraphicsPath>& getGraphicsPath() { return mpGraphicsPath; } // other data-validity access bool getNoLineJoin() const { return mbNoLineJoin; } + + virtual sal_Int64 estimateUsageInBytes() const override; }; SystemDependentData_GraphicsPath::SystemDependentData_GraphicsPath( basegfx::SystemDependentDataManager& rSystemDependentDataManager, + std::shared_ptr<Gdiplus::GraphicsPath>& rpGraphicsPath, bool bNoLineJoin) : basegfx::SystemDependentData(rSystemDependentDataManager), - maGraphicsPath(), + mpGraphicsPath(rpGraphicsPath), mbNoLineJoin(bNoLineJoin) { } +sal_Int64 SystemDependentData_GraphicsPath::estimateUsageInBytes() const +{ + sal_Int64 nRetval(0); + + if(mpGraphicsPath) + { + const INT nPointCount(mpGraphicsPath->GetPointCount()); + + if(0 != nPointCount) + { + // Each point has + // - 2 x sizeof(Gdiplus::REAL) + // - 1 byte (see GetPathTypes in docu) + nRetval = nPointCount * ((2 * sizeof(Gdiplus::REAL)) + 1); + } + } + + return nRetval; +} + bool WinSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolyPolygon& rPolyPolygon, @@ -2018,17 +2042,20 @@ bool WinSalGraphicsImpl::drawPolyPolygon( aGraphics.SetTransform(&aMatrix); } + // prepare local instabce of Gdiplus::GraphicsPath + std::shared_ptr<Gdiplus::GraphicsPath> pGraphicsPath; + // try to access buffered data std::shared_ptr<SystemDependentData_GraphicsPath> pSystemDependentData_GraphicsPath( rPolyPolygon.getSystemDependentData<SystemDependentData_GraphicsPath>()); - if(!pSystemDependentData_GraphicsPath) + if(pSystemDependentData_GraphicsPath) + { + // copy buffered data + pGraphicsPath = pSystemDependentData_GraphicsPath->getGraphicsPath(); + } + else { - // add to buffering mechanism - pSystemDependentData_GraphicsPath = rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>( - ImplGetSystemDependentDataManager(), - false); - // 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 @@ -2056,23 +2083,31 @@ bool WinSalGraphicsImpl::drawPolyPolygon( // (at least for now...) // create data + pGraphicsPath.reset(new Gdiplus::GraphicsPath()); + for(sal_uInt32 a(0); a < nCount; a++) { if(0 != a) { // #i101491# not needed for first run - pSystemDependentData_GraphicsPath->getGraphicsPath().StartFigure(); + pGraphicsPath->StartFigure(); } impAddB2DPolygonToGDIPlusGraphicsPathReal( - pSystemDependentData_GraphicsPath->getGraphicsPath(), + *pGraphicsPath, rPolyPolygon.getB2DPolygon(a), rObjectToDevice, // not used due to the two 'false' values below, but to not forget later false, false); - pSystemDependentData_GraphicsPath->getGraphicsPath().CloseFigure(); + pGraphicsPath->CloseFigure(); } + + // add to buffering mechanism + rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>( + ImplGetSystemDependentDataManager(), + pGraphicsPath, + false); } if(mrParent.getAntiAliasB2DDraw()) @@ -2122,7 +2157,7 @@ bool WinSalGraphicsImpl::drawPolyPolygon( // use created or buffered data aGraphics.FillPath( &aSolidBrush, - &pSystemDependentData_GraphicsPath->getGraphicsPath()); + &(*pGraphicsPath)); return true; } @@ -2222,6 +2257,9 @@ bool WinSalGraphicsImpl::drawPolyLine( } } + // prepare local instabce of Gdiplus::GraphicsPath + std::shared_ptr<Gdiplus::GraphicsPath> pGraphicsPath; + // try to access buffered data std::shared_ptr<SystemDependentData_GraphicsPath> pSystemDependentData_GraphicsPath( rPolygon.getSystemDependentData<SystemDependentData_GraphicsPath>()); @@ -2236,16 +2274,18 @@ bool WinSalGraphicsImpl::drawPolyLine( } } - if(!pSystemDependentData_GraphicsPath) + if(pSystemDependentData_GraphicsPath) + { + // copy buffered data + pGraphicsPath = pSystemDependentData_GraphicsPath->getGraphicsPath(); + } + else { - // add to buffering mechanism - pSystemDependentData_GraphicsPath = rPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>( - ImplGetSystemDependentDataManager(), - bNoLineJoin); - // fill data of buffered data + pGraphicsPath.reset(new Gdiplus::GraphicsPath()); + impAddB2DPolygonToGDIPlusGraphicsPathReal( - pSystemDependentData_GraphicsPath->getGraphicsPath(), + *pGraphicsPath, rPolygon, rObjectToDevice, bNoLineJoin, @@ -2254,8 +2294,14 @@ bool WinSalGraphicsImpl::drawPolyLine( if(rPolygon.isClosed() && !bNoLineJoin) { // #i101491# needed to create the correct line joins - pSystemDependentData_GraphicsPath->getGraphicsPath().CloseFigure(); + pGraphicsPath->CloseFigure(); } + + // add to buffering mechanism + rPolygon.addOrReplaceSystemDependentData<SystemDependentData_GraphicsPath>( + ImplGetSystemDependentDataManager(), + pGraphicsPath, + bNoLineJoin); } if(mrParent.getAntiAliasB2DDraw()) @@ -2269,7 +2315,7 @@ bool WinSalGraphicsImpl::drawPolyLine( aGraphics.DrawPath( &aPen, - &pSystemDependentData_GraphicsPath->getGraphicsPath()); + &(*pGraphicsPath)); return true; } diff --git a/vcl/win/gdi/salbmp.cxx b/vcl/win/gdi/salbmp.cxx index 4d21fde79da9..fcdd4b984e1d 100644 --- a/vcl/win/gdi/salbmp.cxx +++ b/vcl/win/gdi/salbmp.cxx @@ -98,21 +98,77 @@ private: public: SystemDependentData_GdiPlusBitmap( - basegfx::SystemDependentDataManager& rSystemDependentDataManager); + basegfx::SystemDependentDataManager& rSystemDependentDataManager, + const std::shared_ptr<Gdiplus::Bitmap>& rGdiPlusBitmap, + const WinSalBitmap* pAssociatedAlpha); const WinSalBitmap* getAssociatedAlpha() const { return mpAssociatedAlpha; } - void setAssociatedAlpha(const WinSalBitmap* pNew) { mpAssociatedAlpha = pNew; } - const std::shared_ptr<Gdiplus::Bitmap>& getGdiPlusBitmap() const { return mpGdiPlusBitmap; } - void setGdiPlusBitmap(const std::shared_ptr<Gdiplus::Bitmap>& rNew) { mpGdiPlusBitmap = rNew; } + + virtual sal_Int64 estimateUsageInBytes() const override; }; SystemDependentData_GdiPlusBitmap::SystemDependentData_GdiPlusBitmap( - basegfx::SystemDependentDataManager& rSystemDependentDataManager) + basegfx::SystemDependentDataManager& rSystemDependentDataManager, + const std::shared_ptr<Gdiplus::Bitmap>& rGdiPlusBitmap, + const WinSalBitmap* pAssociatedAlpha) : basegfx::SystemDependentData(rSystemDependentDataManager), - mpGdiPlusBitmap(), - mpAssociatedAlpha(nullptr) + mpGdiPlusBitmap(rGdiPlusBitmap), + mpAssociatedAlpha(pAssociatedAlpha) +{ +} + +sal_Int64 SystemDependentData_GdiPlusBitmap::estimateUsageInBytes() const { + sal_Int64 nRetval(0); + + if(mpGdiPlusBitmap) + { + const UINT nWidth(mpGdiPlusBitmap->GetWidth()); + const UINT nHeight(mpGdiPlusBitmap->GetHeight()); + + if(0 != nWidth && 0 != nHeight) + { + nRetval = nWidth * nHeight; + + switch(mpGdiPlusBitmap->GetPixelFormat()) + { + case PixelFormat1bppIndexed: + nRetval /= 8; + break; + case PixelFormat4bppIndexed: + nRetval /= 4; + break; + case PixelFormat16bppGrayScale: + case PixelFormat16bppRGB555: + case PixelFormat16bppRGB565: + case PixelFormat16bppARGB1555: + nRetval *= 2; + break; + case PixelFormat24bppRGB: + nRetval *= 3; + break; + case PixelFormat32bppRGB: + case PixelFormat32bppARGB: + case PixelFormat32bppPARGB: + case PixelFormat32bppCMYK: + nRetval *= 4; + break; + case PixelFormat48bppRGB: + nRetval *= 6; + break; + case PixelFormat64bppARGB: + case PixelFormat64bppPARGB: + nRetval *= 8; + break; + default: + case PixelFormat8bppIndexed: + break; + } + } + } + + return nRetval; } std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource) const @@ -144,23 +200,25 @@ std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap(const WinS } else if(maSize.Width() > 0 && maSize.Height() > 0) { - // add to buffering mechanism - pSystemDependentData_GdiPlusBitmap = addOrReplaceSystemDependentData<SystemDependentData_GdiPlusBitmap>( - ImplGetSystemDependentDataManager()); - // create and set data + const WinSalBitmap* pAssociatedAlpha(nullptr); + if(pAlphaSource) { aRetval.reset(const_cast< WinSalBitmap* >(this)->ImplCreateGdiPlusBitmap(*pAlphaSource)); - pSystemDependentData_GdiPlusBitmap->setGdiPlusBitmap(aRetval); - pSystemDependentData_GdiPlusBitmap->setAssociatedAlpha(pAlphaSource); + pAssociatedAlpha = pAlphaSource; } else { aRetval.reset(const_cast< WinSalBitmap* >(this)->ImplCreateGdiPlusBitmap()); - pSystemDependentData_GdiPlusBitmap->setGdiPlusBitmap(aRetval); - pSystemDependentData_GdiPlusBitmap->setAssociatedAlpha(nullptr); + pAssociatedAlpha = nullptr; } + + // add to buffering mechanism + addOrReplaceSystemDependentData<SystemDependentData_GdiPlusBitmap>( + ImplGetSystemDependentDataManager(), + aRetval, + pAssociatedAlpha); } return aRetval; |