office-gobmx/basegfx/source/tools/systemdependentdata.cxx

191 lines
5.4 KiB
C++
Raw Normal View History

Support buffering SystemDependent GraphicData This is a first step to allow buffering of system dependent data, especially (but not only) for the system-dependent implementations of graphic output. For example, for B2DPolygon and Win output, it allows buffering the Gdiplus::GraphicsPath instead of re- creating it all the time. To support that, the change includes forwarding the current transformation to the renderers in SalGraphics. The current state in VCL is to transform all and everything to device coordinates at every single paint. I have currently started to do this for ::drawPolyLine implementations. The fallbacks for all systems will at the start of that method just transform the data to device coordinates, so all works as before. This may also be done for FilledPolygon paint in a later step, but most urgent is FatLine painting. An arrangement of shared_ptr/weak_ptr is used so that either the instance buffering (in the example B2DPolygon) or the instance managing it can delete it. The instance managing it currently uses a 1s Timer and a cycle-lifetime management, but that can be extended in the future to e.g. include size hints, too. The mechanism it designed to support multiple Data per buffering element, e.g. for B2DPolygon at the same time system-dependent instances of Gdiplus and Cairo can be buffered, but also PDF-data. This is achieved semi-automatic by using typeid(class).hash_code() as key for organization. The mechanism will be used for now at B2DPolygon, but is not limited to. There is already a similar but less general buffer (see GdiPlusBuffer) that can and will be converted to use this new mechanism. Added vcl/headless Cairo renderer to support given ObjectToDevice transformation (not to transform given B2DPolygon) Added support for CairoPath buffered at B2DPolygon, seems to work well. Need to do more tests Moved usage to templates suggested by Noel Grandin (Noel Grandin <noelgrandin@gmail.com>), thanks for these suggestions. Adapted Win usage to that, too. Converted Win-specific GdiPlus BitmapBuffer to new mechanism, works well. Checked, the manager holds now a mix of bitmap and path data under Win Added a cleanup mechanism to flush all buffered data at DeInitVCL() using flushAll() at SystemDependentDataBuffer Adapted Linux-versions of ::drawPolyLine to support PixelSnapHairline, for now in a simplified version that still allows buffering. This will also be used (and use buffering) for the Cairo-fallback in X11SalGraphics Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7 Reviewed-on: https://gerrit.libreoffice.org/59555 Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 06:01:08 -05:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <basegfx/utils/systemdependentdata.hxx>
#include <math.h>
Support buffering SystemDependent GraphicData This is a first step to allow buffering of system dependent data, especially (but not only) for the system-dependent implementations of graphic output. For example, for B2DPolygon and Win output, it allows buffering the Gdiplus::GraphicsPath instead of re- creating it all the time. To support that, the change includes forwarding the current transformation to the renderers in SalGraphics. The current state in VCL is to transform all and everything to device coordinates at every single paint. I have currently started to do this for ::drawPolyLine implementations. The fallbacks for all systems will at the start of that method just transform the data to device coordinates, so all works as before. This may also be done for FilledPolygon paint in a later step, but most urgent is FatLine painting. An arrangement of shared_ptr/weak_ptr is used so that either the instance buffering (in the example B2DPolygon) or the instance managing it can delete it. The instance managing it currently uses a 1s Timer and a cycle-lifetime management, but that can be extended in the future to e.g. include size hints, too. The mechanism it designed to support multiple Data per buffering element, e.g. for B2DPolygon at the same time system-dependent instances of Gdiplus and Cairo can be buffered, but also PDF-data. This is achieved semi-automatic by using typeid(class).hash_code() as key for organization. The mechanism will be used for now at B2DPolygon, but is not limited to. There is already a similar but less general buffer (see GdiPlusBuffer) that can and will be converted to use this new mechanism. Added vcl/headless Cairo renderer to support given ObjectToDevice transformation (not to transform given B2DPolygon) Added support for CairoPath buffered at B2DPolygon, seems to work well. Need to do more tests Moved usage to templates suggested by Noel Grandin (Noel Grandin <noelgrandin@gmail.com>), thanks for these suggestions. Adapted Win usage to that, too. Converted Win-specific GdiPlus BitmapBuffer to new mechanism, works well. Checked, the manager holds now a mix of bitmap and path data under Win Added a cleanup mechanism to flush all buffered data at DeInitVCL() using flushAll() at SystemDependentDataBuffer Adapted Linux-versions of ::drawPolyLine to support PixelSnapHairline, for now in a simplified version that still allows buffering. This will also be used (and use buffering) for the Cairo-fallback in X11SalGraphics Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7 Reviewed-on: https://gerrit.libreoffice.org/59555 Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 06:01:08 -05:00
namespace basegfx
{
SystemDependentDataManager::SystemDependentDataManager()
{
}
SystemDependentDataManager::~SystemDependentDataManager()
{
}
} // namespace basegfx
namespace basegfx
{
MinimalSystemDependentDataManager::MinimalSystemDependentDataManager()
: SystemDependentDataManager(),
maSystemDependentDataReferences()
{
}
MinimalSystemDependentDataManager::~MinimalSystemDependentDataManager()
{
}
void MinimalSystemDependentDataManager::startUsage(basegfx::SystemDependentData_SharedPtr& rData)
{
if(rData)
{
maSystemDependentDataReferences.insert(rData);
}
}
void MinimalSystemDependentDataManager::endUsage(basegfx::SystemDependentData_SharedPtr& rData)
{
if(rData)
{
maSystemDependentDataReferences.erase(rData);
}
}
void MinimalSystemDependentDataManager::touchUsage(basegfx::SystemDependentData_SharedPtr& /* rData */)
{
}
void MinimalSystemDependentDataManager::flushAll()
{
maSystemDependentDataReferences.clear();
}
} // namespace basegfx
namespace basegfx
{
SystemDependentData::SystemDependentData(
SystemDependentDataManager& rSystemDependentDataManager)
: mrSystemDependentDataManager(rSystemDependentDataManager),
mnCalculatedCycles(0)
Support buffering SystemDependent GraphicData This is a first step to allow buffering of system dependent data, especially (but not only) for the system-dependent implementations of graphic output. For example, for B2DPolygon and Win output, it allows buffering the Gdiplus::GraphicsPath instead of re- creating it all the time. To support that, the change includes forwarding the current transformation to the renderers in SalGraphics. The current state in VCL is to transform all and everything to device coordinates at every single paint. I have currently started to do this for ::drawPolyLine implementations. The fallbacks for all systems will at the start of that method just transform the data to device coordinates, so all works as before. This may also be done for FilledPolygon paint in a later step, but most urgent is FatLine painting. An arrangement of shared_ptr/weak_ptr is used so that either the instance buffering (in the example B2DPolygon) or the instance managing it can delete it. The instance managing it currently uses a 1s Timer and a cycle-lifetime management, but that can be extended in the future to e.g. include size hints, too. The mechanism it designed to support multiple Data per buffering element, e.g. for B2DPolygon at the same time system-dependent instances of Gdiplus and Cairo can be buffered, but also PDF-data. This is achieved semi-automatic by using typeid(class).hash_code() as key for organization. The mechanism will be used for now at B2DPolygon, but is not limited to. There is already a similar but less general buffer (see GdiPlusBuffer) that can and will be converted to use this new mechanism. Added vcl/headless Cairo renderer to support given ObjectToDevice transformation (not to transform given B2DPolygon) Added support for CairoPath buffered at B2DPolygon, seems to work well. Need to do more tests Moved usage to templates suggested by Noel Grandin (Noel Grandin <noelgrandin@gmail.com>), thanks for these suggestions. Adapted Win usage to that, too. Converted Win-specific GdiPlus BitmapBuffer to new mechanism, works well. Checked, the manager holds now a mix of bitmap and path data under Win Added a cleanup mechanism to flush all buffered data at DeInitVCL() using flushAll() at SystemDependentDataBuffer Adapted Linux-versions of ::drawPolyLine to support PixelSnapHairline, for now in a simplified version that still allows buffering. This will also be used (and use buffering) for the Cairo-fallback in X11SalGraphics Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7 Reviewed-on: https://gerrit.libreoffice.org/59555 Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 06:01:08 -05:00
{
}
SystemDependentData::~SystemDependentData()
{
}
sal_uInt32 SystemDependentData::calculateCombinedHoldCyclesInSeconds() const
{
if(0 == mnCalculatedCycles)
{
const sal_Int64 nBytes(estimateUsageInBytes());
const sal_uInt32 nSeconds = 60; // HoldCyclesInSeconds
// 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 higher
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_Int64 SystemDependentData::estimateUsageInBytes() const
{
// default implementation has no idea
return 0;
}
Support buffering SystemDependent GraphicData This is a first step to allow buffering of system dependent data, especially (but not only) for the system-dependent implementations of graphic output. For example, for B2DPolygon and Win output, it allows buffering the Gdiplus::GraphicsPath instead of re- creating it all the time. To support that, the change includes forwarding the current transformation to the renderers in SalGraphics. The current state in VCL is to transform all and everything to device coordinates at every single paint. I have currently started to do this for ::drawPolyLine implementations. The fallbacks for all systems will at the start of that method just transform the data to device coordinates, so all works as before. This may also be done for FilledPolygon paint in a later step, but most urgent is FatLine painting. An arrangement of shared_ptr/weak_ptr is used so that either the instance buffering (in the example B2DPolygon) or the instance managing it can delete it. The instance managing it currently uses a 1s Timer and a cycle-lifetime management, but that can be extended in the future to e.g. include size hints, too. The mechanism it designed to support multiple Data per buffering element, e.g. for B2DPolygon at the same time system-dependent instances of Gdiplus and Cairo can be buffered, but also PDF-data. This is achieved semi-automatic by using typeid(class).hash_code() as key for organization. The mechanism will be used for now at B2DPolygon, but is not limited to. There is already a similar but less general buffer (see GdiPlusBuffer) that can and will be converted to use this new mechanism. Added vcl/headless Cairo renderer to support given ObjectToDevice transformation (not to transform given B2DPolygon) Added support for CairoPath buffered at B2DPolygon, seems to work well. Need to do more tests Moved usage to templates suggested by Noel Grandin (Noel Grandin <noelgrandin@gmail.com>), thanks for these suggestions. Adapted Win usage to that, too. Converted Win-specific GdiPlus BitmapBuffer to new mechanism, works well. Checked, the manager holds now a mix of bitmap and path data under Win Added a cleanup mechanism to flush all buffered data at DeInitVCL() using flushAll() at SystemDependentDataBuffer Adapted Linux-versions of ::drawPolyLine to support PixelSnapHairline, for now in a simplified version that still allows buffering. This will also be used (and use buffering) for the Cairo-fallback in X11SalGraphics Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7 Reviewed-on: https://gerrit.libreoffice.org/59555 Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 06:01:08 -05:00
} // namespace basegfx
namespace basegfx
{
SystemDependentDataHolder::SystemDependentDataHolder()
: maSystemDependentReferences()
{
}
SystemDependentDataHolder::~SystemDependentDataHolder()
{
for(const auto& candidate : maSystemDependentReferences)
Support buffering SystemDependent GraphicData This is a first step to allow buffering of system dependent data, especially (but not only) for the system-dependent implementations of graphic output. For example, for B2DPolygon and Win output, it allows buffering the Gdiplus::GraphicsPath instead of re- creating it all the time. To support that, the change includes forwarding the current transformation to the renderers in SalGraphics. The current state in VCL is to transform all and everything to device coordinates at every single paint. I have currently started to do this for ::drawPolyLine implementations. The fallbacks for all systems will at the start of that method just transform the data to device coordinates, so all works as before. This may also be done for FilledPolygon paint in a later step, but most urgent is FatLine painting. An arrangement of shared_ptr/weak_ptr is used so that either the instance buffering (in the example B2DPolygon) or the instance managing it can delete it. The instance managing it currently uses a 1s Timer and a cycle-lifetime management, but that can be extended in the future to e.g. include size hints, too. The mechanism it designed to support multiple Data per buffering element, e.g. for B2DPolygon at the same time system-dependent instances of Gdiplus and Cairo can be buffered, but also PDF-data. This is achieved semi-automatic by using typeid(class).hash_code() as key for organization. The mechanism will be used for now at B2DPolygon, but is not limited to. There is already a similar but less general buffer (see GdiPlusBuffer) that can and will be converted to use this new mechanism. Added vcl/headless Cairo renderer to support given ObjectToDevice transformation (not to transform given B2DPolygon) Added support for CairoPath buffered at B2DPolygon, seems to work well. Need to do more tests Moved usage to templates suggested by Noel Grandin (Noel Grandin <noelgrandin@gmail.com>), thanks for these suggestions. Adapted Win usage to that, too. Converted Win-specific GdiPlus BitmapBuffer to new mechanism, works well. Checked, the manager holds now a mix of bitmap and path data under Win Added a cleanup mechanism to flush all buffered data at DeInitVCL() using flushAll() at SystemDependentDataBuffer Adapted Linux-versions of ::drawPolyLine to support PixelSnapHairline, for now in a simplified version that still allows buffering. This will also be used (and use buffering) for the Cairo-fallback in X11SalGraphics Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7 Reviewed-on: https://gerrit.libreoffice.org/59555 Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 06:01:08 -05:00
{
basegfx::SystemDependentData_SharedPtr aData(candidate.second.lock());
if(aData)
{
aData->getSystemDependentDataManager().endUsage(aData);
}
}
}
void SystemDependentDataHolder::addOrReplaceSystemDependentData(basegfx::SystemDependentData_SharedPtr& rData)
{
const size_t hash_code(typeid(*rData).hash_code());
Support buffering SystemDependent GraphicData This is a first step to allow buffering of system dependent data, especially (but not only) for the system-dependent implementations of graphic output. For example, for B2DPolygon and Win output, it allows buffering the Gdiplus::GraphicsPath instead of re- creating it all the time. To support that, the change includes forwarding the current transformation to the renderers in SalGraphics. The current state in VCL is to transform all and everything to device coordinates at every single paint. I have currently started to do this for ::drawPolyLine implementations. The fallbacks for all systems will at the start of that method just transform the data to device coordinates, so all works as before. This may also be done for FilledPolygon paint in a later step, but most urgent is FatLine painting. An arrangement of shared_ptr/weak_ptr is used so that either the instance buffering (in the example B2DPolygon) or the instance managing it can delete it. The instance managing it currently uses a 1s Timer and a cycle-lifetime management, but that can be extended in the future to e.g. include size hints, too. The mechanism it designed to support multiple Data per buffering element, e.g. for B2DPolygon at the same time system-dependent instances of Gdiplus and Cairo can be buffered, but also PDF-data. This is achieved semi-automatic by using typeid(class).hash_code() as key for organization. The mechanism will be used for now at B2DPolygon, but is not limited to. There is already a similar but less general buffer (see GdiPlusBuffer) that can and will be converted to use this new mechanism. Added vcl/headless Cairo renderer to support given ObjectToDevice transformation (not to transform given B2DPolygon) Added support for CairoPath buffered at B2DPolygon, seems to work well. Need to do more tests Moved usage to templates suggested by Noel Grandin (Noel Grandin <noelgrandin@gmail.com>), thanks for these suggestions. Adapted Win usage to that, too. Converted Win-specific GdiPlus BitmapBuffer to new mechanism, works well. Checked, the manager holds now a mix of bitmap and path data under Win Added a cleanup mechanism to flush all buffered data at DeInitVCL() using flushAll() at SystemDependentDataBuffer Adapted Linux-versions of ::drawPolyLine to support PixelSnapHairline, for now in a simplified version that still allows buffering. This will also be used (and use buffering) for the Cairo-fallback in X11SalGraphics Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7 Reviewed-on: https://gerrit.libreoffice.org/59555 Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 06:01:08 -05:00
auto result(maSystemDependentReferences.find(hash_code));
if(result != maSystemDependentReferences.end())
{
basegfx::SystemDependentData_SharedPtr aData(result->second.lock());
if(aData)
{
aData->getSystemDependentDataManager().endUsage(aData);
}
maSystemDependentReferences.erase(result);
result = maSystemDependentReferences.end();
}
maSystemDependentReferences[hash_code] = rData;
rData->getSystemDependentDataManager().startUsage(rData);
}
SystemDependentData_SharedPtr SystemDependentDataHolder::getSystemDependentData(size_t hash_code) const
{
basegfx::SystemDependentData_SharedPtr aRetval;
auto result(maSystemDependentReferences.find(hash_code));
if(result != maSystemDependentReferences.end())
{
aRetval = result->second.lock();
if(aRetval)
{
aRetval->getSystemDependentDataManager().touchUsage(aRetval);
}
else
{
const_cast< SystemDependentDataHolder* >(this)->maSystemDependentReferences.erase(result);
}
}
return aRetval;
}
} // namespace basegfx
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */