track impress style-sheet fill bitmaps per SfxStyleSheet, drop the pool bodge
Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com> Change-Id: Iafd45f05c32f4d2096be20b354bd6e93b6a9ef89 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/3550 Tested-by: Jenkins CPCI <releng@collaboraoffice.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com> (cherry picked from commit 6b4932267e3b0a5aec3fc1611d931eaa99eaf05a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208580 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
09ff91d4fc
commit
8be0c744f5
@@ -15,7 +15,6 @@
|
||||
#include <com/sun/star/uno/Reference.hxx>
|
||||
#include <cppuhelper/weakref.hxx>
|
||||
#include <tools/ref.hxx>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@@ -24,6 +23,7 @@ class SdrModel;
|
||||
class SdrObject;
|
||||
class SdrPage;
|
||||
class SfxItemPool;
|
||||
class SfxStyleSheet;
|
||||
class XFillBitmapItem;
|
||||
|
||||
namespace com::sun::star::beans
|
||||
@@ -45,17 +45,6 @@ SVXCORE_DLLPUBLIC OUString getDeferredOriginURL(const XFillBitmapItem& rItem);
|
||||
// unresolved remote URLs (GraphicType::Default with non-empty originURL).
|
||||
SVXCORE_DLLPUBLIC bool hasDeferredFillBitmapLinks(const SfxItemPool& rPool);
|
||||
|
||||
// Scan pool surrogates for XATTR_FILLBITMAP items with unresolved remote
|
||||
// URLs (GraphicType::Default with non-empty originURL) and register an
|
||||
// sfx2::SvBaseLink for each. When the link is updated, the fetched graphic
|
||||
// replaces the pool item and fnInvalidate is called to trigger a repaint.
|
||||
SVXCORE_DLLPUBLIC void registerFillBitmapLinks(SfxItemPool& rPool, sfx2::LinkManager& rLinkMgr,
|
||||
std::function<void()> fnInvalidate);
|
||||
|
||||
// Convenience overload for the drawing layer: registers fill bitmap links
|
||||
// and flushes all ViewObjectContacts on all pages when the graphic arrives.
|
||||
SVXCORE_DLLPUBLIC void registerFillBitmapLinks(SdrModel& rModel, sfx2::LinkManager& rLinkMgr);
|
||||
|
||||
namespace sdr
|
||||
{
|
||||
// Owns one sfx2::SvBaseLink per host (SdrObject or SdrPage background) that
|
||||
@@ -74,9 +63,13 @@ public:
|
||||
~FillBitmapLinkTracker();
|
||||
|
||||
// rNewURL is the deferred origin URL of the new item, or empty when the
|
||||
// item is absent, already resolved, or the host is going away.
|
||||
// item is absent, already resolved, or the host is going away. The
|
||||
// SfxStyleSheet host covers a fill shared by every object or page using
|
||||
// that style (e.g. an Impress slide background on the Background style),
|
||||
// the drawing-layer counterpart of a fill on a Writer paragraph style.
|
||||
void onFillBitmapURLChanged(SdrObject& rObj, std::u16string_view rNewURL);
|
||||
void onFillBitmapURLChanged(SdrPage& rPage, std::u16string_view rNewURL);
|
||||
void onFillBitmapURLChanged(SfxStyleSheet& rStyle, std::u16string_view rNewURL);
|
||||
|
||||
// Suppress the onFillBitmapURLChanged that a link's own write-back of the
|
||||
// resolved graphic would otherwise raise for its host.
|
||||
@@ -91,6 +84,7 @@ private:
|
||||
const void* m_pUpdatingHost = nullptr;
|
||||
std::map<SdrObject*, tools::SvRef<sfx2::SvBaseLink>> m_aObjLinks;
|
||||
std::map<SdrPage*, tools::SvRef<sfx2::SvBaseLink>> m_aPageLinks;
|
||||
std::map<SfxStyleSheet*, tools::SvRef<sfx2::SvBaseLink>> m_aStyleLinks;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <svl/intitem.hxx>
|
||||
#include <svl/itemset.hxx>
|
||||
|
||||
#include <svx/fillbitmaplink.hxx>
|
||||
#include <svx/xbtmpit.hxx>
|
||||
#include <svx/xdef.hxx>
|
||||
#include <svx/xflbmtit.hxx>
|
||||
#include <svx/xflbstit.hxx>
|
||||
#include <svx/xlnclit.hxx>
|
||||
@@ -1074,6 +1077,25 @@ void SdStyleSheet::setPropertyValue_Impl(const OUString& aPropertyName, const cs
|
||||
}
|
||||
|
||||
rStyleSet.Put( aSet );
|
||||
|
||||
// Track a deferred remote fill bitmap landing on this style sheet, so a
|
||||
// shared background (e.g. an Impress slide Background style) is registered
|
||||
// per style as the item is set, the drawing-layer counterpart of the
|
||||
// SwFormat::SetFormatAttr hook for Writer paragraph styles.
|
||||
if (auto* pPool = dynamic_cast<SdStyleSheetPool*>(GetPool()))
|
||||
{
|
||||
if (SdDrawDocument* pDoc = pPool->GetDoc())
|
||||
{
|
||||
if (sdr::FillBitmapLinkTracker* pTracker = pDoc->GetFillBitmapLinkTracker())
|
||||
{
|
||||
OUString aURL;
|
||||
if (const XFillBitmapItem* pItem
|
||||
= rStyleSet.GetItemIfSet(XATTR_FILLBITMAP, false))
|
||||
aURL = getDeferredOriginURL(*pItem);
|
||||
pTracker->onFillBitmapURLChanged(*this, aURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Must be guarded by solar mutex; must not be disposed
|
||||
|
||||
+3
-3
@@ -19,7 +19,6 @@
|
||||
#include <rtl/ustring.hxx>
|
||||
#include <sfx2/linkmgr.hxx>
|
||||
#include <sfx2/objsh.hxx>
|
||||
#include <svx/fillbitmaplink.hxx>
|
||||
#include <svx/sdr/contact/displayinfo.hxx>
|
||||
#include <svx/sdr/contact/viewcontact.hxx>
|
||||
#include <svx/sdr/contact/viewobjectcontact.hxx>
|
||||
@@ -187,7 +186,9 @@ CPPUNIT_TEST_FIXTURE(SdrTest, testSlideBackground)
|
||||
|
||||
// Allow link updates and resolve the linked background image via the
|
||||
// LinkManager before rendering, so createNewSdrFillGraphicAttribute
|
||||
// sees a Bitmap and not a deferred GraphicType::Default item.
|
||||
// sees a Bitmap and not a deferred GraphicType::Default item. The link
|
||||
// was registered per style sheet by the model's FillBitmapLinkTracker as
|
||||
// the background was set on the Background style during load.
|
||||
SfxObjectShell* pShell = SfxObjectShell::GetShellFromComponent(mxComponent);
|
||||
CPPUNIT_ASSERT(pShell);
|
||||
pShell->getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true);
|
||||
@@ -196,7 +197,6 @@ CPPUNIT_TEST_FIXTURE(SdrTest, testSlideBackground)
|
||||
SdrModel& rModel = pSvxDrawPage->GetSdrPage()->getSdrModelFromSdrPage();
|
||||
sfx2::LinkManager* pLinkMgr = rModel.GetLinkManager();
|
||||
CPPUNIT_ASSERT(pLinkMgr);
|
||||
registerFillBitmapLinks(rModel.GetItemPool(), *pLinkMgr, []() {});
|
||||
pLinkMgr->UpdateAllLinks(false, nullptr, u""_ustr);
|
||||
|
||||
// When rendering that document:
|
||||
|
||||
@@ -17,70 +17,17 @@
|
||||
#include <svx/svdpage.hxx>
|
||||
#include <svx/sdrobjectuser.hxx>
|
||||
#include <svx/sdrpageuser.hxx>
|
||||
#include <svx/sdr/contact/viewcontact.hxx>
|
||||
#include <svl/hint.hxx>
|
||||
#include <svl/itempool.hxx>
|
||||
#include <svl/itemset.hxx>
|
||||
#include <svl/lstner.hxx>
|
||||
#include <svl/style.hxx>
|
||||
#include <svx/xbtmpit.hxx>
|
||||
#include <svx/xdef.hxx>
|
||||
#include <vcl/GraphicObject.hxx>
|
||||
#include <vcl/graph.hxx>
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Link class for fill bitmap items with remote URLs.
|
||||
// DataChanged receives the fetched graphic and updates the actual
|
||||
// XFillBitmapItem in the attribute pool so the drawing layer picks up
|
||||
// the resolved image on the next repaint.
|
||||
class FillBitmapLink final : public sfx2::SvBaseLink
|
||||
{
|
||||
SfxItemPool& m_rPool;
|
||||
sfx2::LinkManager& m_rLinkMgr;
|
||||
std::function<void()> m_fnInvalidate;
|
||||
|
||||
public:
|
||||
FillBitmapLink(SfxItemPool& rPool, sfx2::LinkManager& rLinkMgr,
|
||||
std::function<void()> fnInvalidate)
|
||||
: SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB)
|
||||
, m_rPool(rPool)
|
||||
, m_rLinkMgr(rLinkMgr)
|
||||
, m_fnInvalidate(std::move(fnInvalidate))
|
||||
{
|
||||
}
|
||||
|
||||
virtual UpdateResult DataChanged(const OUString& rMimeType,
|
||||
const css::uno::Any& rValue) override
|
||||
{
|
||||
Graphic aGrf;
|
||||
if (!m_rLinkMgr.GetGraphicFromAny(rMimeType, rValue, aGrf, nullptr))
|
||||
return ERROR_GENERAL;
|
||||
if (aGrf.GetType() == GraphicType::Default)
|
||||
return ERROR_GENERAL;
|
||||
|
||||
OUString aURL;
|
||||
sfx2::LinkManager::GetDisplayNames(this, nullptr, &aURL);
|
||||
GraphicObject aGrfObj(std::move(aGrf));
|
||||
|
||||
// Replace the item in all attribute sets via pool surrogates
|
||||
m_rPool.iterateItemSurrogates(
|
||||
XATTR_FILLBITMAP, [&aURL, &aGrfObj](SfxItemPool::SurrogateData& rData) -> bool {
|
||||
auto& rItem = static_cast<const XFillBitmapItem&>(rData.getItem());
|
||||
const Graphic& rGrf = rItem.GetGraphicObject().GetGraphic();
|
||||
if (rGrf.GetType() == GraphicType::Default && rGrf.getOriginURL() == aURL)
|
||||
{
|
||||
rData.setItem(std::make_unique<XFillBitmapItem>(aGrfObj));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (m_fnInvalidate)
|
||||
m_fnInvalidate();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
OUString getDeferredOriginURL(const XFillBitmapItem& rItem)
|
||||
{
|
||||
const Graphic& rGrf = rItem.GetGraphicObject().GetGraphic();
|
||||
@@ -99,29 +46,6 @@ bool hasDeferredFillBitmapLinks(const SfxItemPool& rPool)
|
||||
return false;
|
||||
}
|
||||
|
||||
void registerFillBitmapLinks(SfxItemPool& rPool, sfx2::LinkManager& rLinkMgr,
|
||||
std::function<void()> fnInvalidate)
|
||||
{
|
||||
for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(XATTR_FILLBITMAP))
|
||||
{
|
||||
OUString aURL = getDeferredOriginURL(static_cast<const XFillBitmapItem&>(*pItem));
|
||||
if (aURL.isEmpty())
|
||||
continue;
|
||||
tools::SvRef<sfx2::SvBaseLink> xLink(new FillBitmapLink(rPool, rLinkMgr, fnInvalidate));
|
||||
rLinkMgr.InsertFileLink(*xLink, sfx2::SvBaseLinkObjectType::ClientGraphic, aURL);
|
||||
}
|
||||
}
|
||||
|
||||
void registerFillBitmapLinks(SdrModel& rModel, sfx2::LinkManager& rLinkMgr)
|
||||
{
|
||||
registerFillBitmapLinks(rModel.GetItemPool(), rLinkMgr, [&rModel]() {
|
||||
for (sal_uInt16 nPage = 0; nPage < rModel.GetPageCount(); ++nPage)
|
||||
rModel.GetPage(nPage)->GetViewContact().flushViewObjectContacts();
|
||||
for (sal_uInt16 nPage = 0; nPage < rModel.GetMasterPageCount(); ++nPage)
|
||||
rModel.GetMasterPage(nPage)->GetViewContact().flushViewObjectContacts();
|
||||
});
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Per-host fill bitmap link. Unlike FillBitmapLink, which patches every pool
|
||||
@@ -247,6 +171,62 @@ public:
|
||||
m_rTracker.onFillBitmapURLChanged(const_cast<SdrPage&>(rPage), u"");
|
||||
}
|
||||
};
|
||||
|
||||
// Style-sheet counterpart, for a fill shared by every host using the style
|
||||
// (e.g. an Impress slide background on the Background pseudo-style). Listens to
|
||||
// the style sheet's broadcaster for SfxHintId::Dying and writes the resolved
|
||||
// graphic back into the style sheet's item set so all users repaint.
|
||||
class SdrStyleSheetFillBitmapLink final : public sfx2::SvBaseLink, public SfxListener
|
||||
{
|
||||
sdr::FillBitmapLinkTracker& m_rTracker;
|
||||
SfxStyleSheet* m_pStyle;
|
||||
sfx2::LinkManager& m_rLinkMgr;
|
||||
|
||||
public:
|
||||
SdrStyleSheetFillBitmapLink(sdr::FillBitmapLinkTracker& rTracker, SfxStyleSheet& rStyle,
|
||||
sfx2::LinkManager& rLinkMgr)
|
||||
: SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB)
|
||||
, m_rTracker(rTracker)
|
||||
, m_pStyle(&rStyle)
|
||||
, m_rLinkMgr(rLinkMgr)
|
||||
{
|
||||
StartListening(rStyle);
|
||||
}
|
||||
|
||||
virtual UpdateResult DataChanged(const OUString& rMimeType,
|
||||
const css::uno::Any& rValue) override
|
||||
{
|
||||
tools::SvRef<SvBaseLink> xSelf(this);
|
||||
|
||||
if (!m_pStyle)
|
||||
return ERROR_GENERAL;
|
||||
|
||||
Graphic aGrf;
|
||||
if (!m_rLinkMgr.GetGraphicFromAny(rMimeType, rValue, aGrf, nullptr))
|
||||
return ERROR_GENERAL;
|
||||
if (aGrf.GetType() == GraphicType::Default)
|
||||
return ERROR_GENERAL;
|
||||
|
||||
SfxItemSet& rSet = m_pStyle->GetItemSet();
|
||||
OUString aName;
|
||||
if (const XFillBitmapItem* pItem = rSet.GetItemIfSet(XATTR_FILLBITMAP, false))
|
||||
aName = pItem->GetName();
|
||||
rSet.Put(XFillBitmapItem(aName, aGrf));
|
||||
m_pStyle->Broadcast(SfxHint(SfxHintId::DataChanged));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
virtual void Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) override
|
||||
{
|
||||
if (rHint.GetId() != SfxHintId::Dying)
|
||||
return;
|
||||
SfxStyleSheet* pStyle = m_pStyle;
|
||||
m_pStyle = nullptr;
|
||||
tools::SvRef<SvBaseLink> xSelf(this);
|
||||
if (pStyle)
|
||||
m_rTracker.onFillBitmapURLChanged(*pStyle, u"");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sdr
|
||||
@@ -264,9 +244,12 @@ FillBitmapLinkTracker::~FillBitmapLinkTracker()
|
||||
pLinkMgr->Remove(rEntry.second.get());
|
||||
for (const auto& rEntry : m_aPageLinks)
|
||||
pLinkMgr->Remove(rEntry.second.get());
|
||||
for (const auto& rEntry : m_aStyleLinks)
|
||||
pLinkMgr->Remove(rEntry.second.get());
|
||||
}
|
||||
m_aObjLinks.clear();
|
||||
m_aPageLinks.clear();
|
||||
m_aStyleLinks.clear();
|
||||
}
|
||||
|
||||
template <typename Host, typename Link>
|
||||
@@ -303,6 +286,12 @@ void FillBitmapLinkTracker::onFillBitmapURLChanged(SdrPage& rPage, std::u16strin
|
||||
{
|
||||
onURLChangedImpl<SdrPage, SdrPageFillBitmapLink>(m_aPageLinks, rPage, rNewURL);
|
||||
}
|
||||
|
||||
void FillBitmapLinkTracker::onFillBitmapURLChanged(SfxStyleSheet& rStyle,
|
||||
std::u16string_view rNewURL)
|
||||
{
|
||||
onURLChangedImpl<SfxStyleSheet, SdrStyleSheetFillBitmapLink>(m_aStyleLinks, rStyle, rNewURL);
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
|
||||
Reference in New Issue
Block a user