Kaydet (Commit) e650279d authored tarafından Armin Le Grand's avatar Armin Le Grand

Support estimateUsageInBytes for SystemDependentData

Change-Id: I6074035ed8f90e452915e9ecffdbe9363375e126
Reviewed-on: https://gerrit.libreoffice.org/61306
Tested-by: Jenkins
Reviewed-by: 's avatarArmin Le Grand <Armin.Le.Grand@cib.de>
üst dd36db16
......@@ -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)
......
......@@ -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
......
......@@ -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,
......
......@@ -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();
}
}
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment