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

tdf#98163 Flush ressources at CustomShapes during import

During ODF import using API for CustomShapes Outliners and
VirtualDevioces get created and not destroyed due to referencing.
This makes the ressources blow up, even under 64bit windows.
Also see tdf#93994 where this was already fixed on page base,
but this is not sufficient for this case.

Change-Id: If9b37d341fcfa4e65485c54054d47964ee2fff5f
Reviewed-on: https://gerrit.libreoffice.org/24305Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarArmin Le Grand <Armin.Le.Grand@cib.de>
üst ed42a984
......@@ -606,40 +606,6 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName
throwIfDisposed();
// tdf#93994 Use a custom slot to have filter code flush the UNO
// API implementations of SdrObjCustomShape. Used e.g. by
// SdXMLDrawPageContext::EndElement(), see there for more
// information
if(SvxFmDrawPage::mpPage)
{
const OUString sFlushCustomShapeUnoApiObjects("FlushCustomShapeUnoApiObjects");
if(sFlushCustomShapeUnoApiObjects == aPropertyName)
{
SdrObjListIter aIter(static_cast< SdPage& >(*SvxFmDrawPage::mpPage), IM_DEEPWITHGROUPS);
while(aIter.IsMore())
{
SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >(aIter.Next());
if(pCustomShape)
{
// tdf#96522 do not reset UNO API implementation since e.g. the
// animation evtl. added to the object uses weak references and
// will be lost when resetting it. In that sense it is *not* a
// on-demand recreatable ressource.
// Luckily, the object causing problems in tdf#93994 is not the
// UNO API object, but the XCustomShapeEngine involved. This
// object is on-demand replacable and can be reset here. This
// will free the involved EditEngine and VirtualDevice.
pCustomShape->mxCustomShapeEngine.set(nullptr);
}
}
return;
}
}
const SfxItemPropertySimpleEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName);
switch( pEntry ? pEntry->nWID : -1 )
......
......@@ -22,6 +22,7 @@
#include <sal/types.h>
#include <vector>
#include <set>
class SdrModel;
class SdrOutliner;
......@@ -30,22 +31,18 @@ class SdrOutliner;
class SdrOutlinerCache
{
private:
SdrModel* mpModel;
SdrModel* mpModel;
std::vector< SdrOutliner* > maModeOutline;
std::vector< SdrOutliner* > maModeText;
std::set< SdrOutliner* > maActiveOutliners;
SdrOutliner* mpModeOutline;
SdrOutliner* mpModeText;
std::vector<SdrOutliner*> maActiveOutliners;
public:
SdrOutlinerCache( SdrModel* pModel );
~SdrOutlinerCache();
SdrOutliner* createOutliner( sal_uInt16 nOutlinerMode );
void disposeOutliner( SdrOutliner* pOutliner );
const std::vector<SdrOutliner*>& GetActiveOutliners() const
{
return maActiveOutliners;
}
std::vector< SdrOutliner* > GetActiveOutliners() const;
};
#endif
......
......@@ -1963,9 +1963,7 @@ SdrOutliner* SdrModel::createOutliner( sal_uInt16 nOutlinerMode )
std::vector<SdrOutliner*> SdrModel::GetActiveOutliners() const
{
std::vector<SdrOutliner*> aRet(mpOutlinerCache ?
mpOutlinerCache->GetActiveOutliners() : std::vector<SdrOutliner*>());
std::vector< SdrOutliner* > aRet(mpOutlinerCache ? mpOutlinerCache->GetActiveOutliners() : std::vector< SdrOutliner* >());
aRet.push_back(pDrawOutliner);
aRet.push_back(pHitTestOutliner);
......
......@@ -24,8 +24,9 @@
SdrOutlinerCache::SdrOutlinerCache( SdrModel* pModel )
: mpModel( pModel ),
mpModeOutline( nullptr ),
mpModeText( nullptr )
maModeOutline(),
maModeText(),
maActiveOutliners()
{
}
......@@ -33,22 +34,22 @@ SdrOutliner* SdrOutlinerCache::createOutliner( sal_uInt16 nOutlinerMode )
{
SdrOutliner* pOutliner = nullptr;
if( (OUTLINERMODE_OUTLINEOBJECT == nOutlinerMode) && mpModeOutline )
if( (OUTLINERMODE_OUTLINEOBJECT == nOutlinerMode) && !maModeOutline.empty() )
{
pOutliner = mpModeOutline;
mpModeOutline = nullptr;
pOutliner = maModeOutline.back();
maModeOutline.pop_back();
}
else if( (OUTLINERMODE_TEXTOBJECT == nOutlinerMode) && mpModeText )
else if( (OUTLINERMODE_TEXTOBJECT == nOutlinerMode) && !maModeText.empty() )
{
pOutliner = mpModeText;
mpModeText = nullptr;
pOutliner = maModeText.back();
maModeText.pop_back();
}
else
{
pOutliner = SdrMakeOutliner(nOutlinerMode, *mpModel);
Outliner& aDrawOutliner = mpModel->GetDrawOutliner();
pOutliner->SetCalcFieldValueHdl( aDrawOutliner.GetCalcFieldValueHdl() );
maActiveOutliners.push_back(pOutliner);
maActiveOutliners.insert(pOutliner);
}
return pOutliner;
......@@ -56,17 +57,19 @@ SdrOutliner* SdrOutlinerCache::createOutliner( sal_uInt16 nOutlinerMode )
SdrOutlinerCache::~SdrOutlinerCache()
{
if( mpModeOutline )
for( auto candA : maModeOutline )
{
delete mpModeOutline;
mpModeOutline = nullptr;
delete candA;
}
if( mpModeText )
maModeOutline.clear();
for( auto candB : maModeText )
{
delete mpModeText;
mpModeText = nullptr;
delete candB;
}
maModeText.clear();
}
void SdrOutlinerCache::disposeOutliner( SdrOutliner* pOutliner )
......@@ -75,18 +78,18 @@ void SdrOutlinerCache::disposeOutliner( SdrOutliner* pOutliner )
{
sal_uInt16 nOutlMode = pOutliner->GetOutlinerMode();
if( (OUTLINERMODE_OUTLINEOBJECT == nOutlMode) && (nullptr == mpModeOutline) )
if( OUTLINERMODE_OUTLINEOBJECT == nOutlMode )
{
mpModeOutline = pOutliner;
maModeOutline.push_back(pOutliner);
pOutliner->Clear();
pOutliner->SetVertical( false );
// Deregister on outliner, might be reused from outliner cache
pOutliner->SetNotifyHdl( Link<EENotify&,void>() );
}
else if( (OUTLINERMODE_TEXTOBJECT == nOutlMode) && (nullptr == mpModeText) )
else if( OUTLINERMODE_TEXTOBJECT == nOutlMode )
{
mpModeText = pOutliner;
maModeText.push_back(pOutliner);
pOutliner->Clear();
pOutliner->SetVertical( false );
......@@ -95,11 +98,15 @@ void SdrOutlinerCache::disposeOutliner( SdrOutliner* pOutliner )
}
else
{
maActiveOutliners.erase(std::remove(maActiveOutliners.begin(), maActiveOutliners.end(), pOutliner), maActiveOutliners.end());
maActiveOutliners.erase(pOutliner);
delete pOutliner;
}
}
}
std::vector< SdrOutliner* > SdrOutlinerCache::GetActiveOutliners() const
{
return std::vector< SdrOutliner* >(maActiveOutliners.begin(), maActiveOutliners.end());
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -1822,8 +1822,26 @@ void SAL_CALL SvxCustomShape::setPropertyValue( const OUString& aPropertyName, c
throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException, css::beans::PropertyVetoException, css::lang::IllegalArgumentException, std::exception)
{
::SolarMutexGuard aGuard;
SdrObject* pObject = mpObj.get();
// tdf#98163 Use a custom slot to have filter code flush the UNO
// API implementations of SdrObjCustomShape. Used e.g. by
// ~SdXMLCustomShapeContext, see there for more information
const OUString sFlushCustomShapeUnoApiObjects("FlushCustomShapeUnoApiObjects");
if(sFlushCustomShapeUnoApiObjects == aPropertyName)
{
SdrObjCustomShape* pTarget = dynamic_cast< SdrObjCustomShape* >(pObject);
if(pTarget)
{
// Luckily, the object causing problems in tdf#93994 is not the
// UNO API object, but the XCustomShapeEngine involved. This
// object is on-demand replacable and can be reset here. This
// will free the involved EditEngine and VirtualDevice.
pTarget->mxCustomShapeEngine.set(nullptr);
}
}
bool bCustomShapeGeometry = pObject && aPropertyName == "CustomShapeGeometry";
bool bMirroredX = false;
......
......@@ -279,29 +279,6 @@ void SdXMLDrawPageContext::EndElement()
if(xNodeSupplier.is())
xmloff::AnimationNodeContext::postProcessRootNode( GetSdImport(), xNodeSupplier->getAnimationNode(), xPageProps );
}
// tdf#93994 call a custom slot to be able to reset the UNO API
// implementations held on the SdrObjects of type
// SdrObjCustomShape - those tend to linger until the entire file
// is loaded. For large files with a lot of these 32bit systems
// may crash due to being out of ressources after ca. 4200
// Outliners and VirtualDevices used there as RefDevice
try
{
uno::Reference< beans::XPropertySet > xPropSet(GetLocalShapesContext(), uno::UNO_QUERY);
if(xPropSet.is())
{
const OUString sFlushCustomShapeUnoApiObjects("FlushCustomShapeUnoApiObjects");
uno::Any aAny;
aAny <<= true;
xPropSet->setPropertyValue(sFlushCustomShapeUnoApiObjects, aAny);
}
}
catch(const uno::Exception&)
{
OSL_FAIL("could not flush after load");
}
}
SdXMLBodyContext::SdXMLBodyContext( SdXMLImport& rImport,
......
......@@ -3891,6 +3891,29 @@ void SdXMLCustomShapeContext::EndElement()
}
SdXMLShapeContext::EndElement();
// tdf#98163 call a custom slot to be able to reset the UNO API
// implementations held on the SdrObjects of type
// SdrObjCustomShape - those tend to linger until the entire file
// is loaded. For large files with a lot of these, 32bit systems
// may crash due to being out of ressources after ca. 4200
// Outliners and VirtualDevices used there as RefDevice
try
{
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
if(xPropSet.is())
{
const OUString sFlushCustomShapeUnoApiObjects("FlushCustomShapeUnoApiObjects");
uno::Any aAny;
aAny <<= sal_True;
xPropSet->setPropertyValue(sFlushCustomShapeUnoApiObjects, aAny);
}
}
catch(const uno::Exception&)
{
OSL_FAIL("could not flush after load");
}
}
SvXMLImportContext* SdXMLCustomShapeContext::CreateChildContext(
......
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