diff options
author | Caolán McNamara <caolan.mcnamara@collabora.com> | 2023-06-05 20:15:16 +0100 |
---|---|---|
committer | Caolán McNamara <caolan.mcnamara@collabora.com> | 2023-06-06 18:01:31 +0200 |
commit | 4df278b4a98637aa5050abfd752eae0a9081b752 (patch) | |
tree | 6e5baa87f2e49daccc7e40403ca9df4733df1267 /svx | |
parent | 9b03f778adfb87a10d781860930ed4d09410af9c (diff) |
perf: cache the generated json for an iconview image
before:
|--13.95%--JSDialogNotifyIdle::Invoke
| |
| |--13.01%--JSDialogNotifyIdle::generateWidgetUpdate
| | |
| | |--11.03%--IconView::DumpAsPropertyTree
| | | lcl_DumpEntryAndSiblings (inlined)
| | | |
| | | |--10.94%--extractPngString (inlined)
after:
|--4.86%--JSDialogNotifyIdle::Invoke
...
| |--2.90%--JSDialogNotifyIdle::generateWidgetUpdate
| | |
| | |--0.76%--IconView::DumpAsPropertyTree
| | | IconView::DumpEntryAndSiblings
| | | Link<std::tuple<tools::JsonWriter&, rtl::OUString const&, std::basic_string_view<char, std::char_traits<char> > > const&, bool>::Call (inlined)
| | | StylesPreviewWindow_Base::DoJsonProperty
| | | |
| | | |--0.55%--StylesPreviewWindow_Base::GetCachedPreviewJson
Change-Id: Id234a84e36710794822945584be3adf028808625
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152630
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Diffstat (limited to 'svx')
-rw-r--r-- | svx/source/inc/StylesPreviewWindow.hxx | 2 | ||||
-rw-r--r-- | svx/source/tbxctrls/StylesPreviewWindow.cxx | 67 |
2 files changed, 68 insertions, 1 deletions
diff --git a/svx/source/inc/StylesPreviewWindow.hxx b/svx/source/inc/StylesPreviewWindow.hxx index de4984e35968..1d59c574bfbe 100644 --- a/svx/source/inc/StylesPreviewWindow.hxx +++ b/svx/source/inc/StylesPreviewWindow.hxx @@ -112,6 +112,7 @@ protected: DECL_LINK(Selected, weld::IconView&, void); DECL_LINK(DoubleClick, weld::IconView&, bool); DECL_LINK(DoCommand, const CommandEvent&, bool); + DECL_STATIC_LINK(StylesPreviewWindow_Base, DoJsonProperty, const tools::json_prop_query&, bool); public: StylesPreviewWindow_Base( @@ -122,6 +123,7 @@ public: void Select(const OUString& rStyleName); void RequestStylesListUpdate(); static VclPtr<VirtualDevice> GetCachedPreview(const std::pair<OUString, OUString>& rStyle); + static OString GetCachedPreviewJson(const OUString& rStyle); private: void UpdateStylesList(); diff --git a/svx/source/tbxctrls/StylesPreviewWindow.cxx b/svx/source/tbxctrls/StylesPreviewWindow.cxx index 3cc669ff98ce..eeca3db49840 100644 --- a/svx/source/tbxctrls/StylesPreviewWindow.cxx +++ b/svx/source/tbxctrls/StylesPreviewWindow.cxx @@ -19,6 +19,7 @@ #include <StylesPreviewWindow.hxx> +#include <comphelper/base64.hxx> #include <comphelper/propertyvalue.hxx> #include <utility> #include <vcl/svapp.hxx> @@ -28,6 +29,7 @@ #include <sfx2/sfxsids.hrc> #include <sfx2/tplpitem.hxx> #include <sfx2/viewsh.hxx> +#include <vcl/filter/PngImageWriter.hxx> #include <vcl/glyphitemcache.hxx> #include <vcl/virdev.hxx> #include <vcl/settings.hxx> @@ -59,16 +61,19 @@ #include <com/sun/star/uno/Sequence.hxx> #include <vcl/commandevent.hxx> +#include <tools/json_writer.hxx> namespace { class StylePreviewCache { static std::map<OUString, VclPtr<VirtualDevice>> gStylePreviewCache; + static std::map<OUString, OString> gJsonStylePreviewCache; static int gStylePreviewCacheClients; public: static std::map<OUString, VclPtr<VirtualDevice>>& Get() { return gStylePreviewCache; } + static std::map<OUString, OString>& GetJson() { return gJsonStylePreviewCache; } static void ClearCache() { @@ -76,6 +81,7 @@ public: aPreview.second.disposeAndClear(); gStylePreviewCache.clear(); + gJsonStylePreviewCache.clear(); } static void RegisterClient() { gStylePreviewCacheClients++; } @@ -88,6 +94,7 @@ public: }; std::map<OUString, VclPtr<VirtualDevice>> StylePreviewCache::gStylePreviewCache; +std::map<OUString, OString> StylePreviewCache::gJsonStylePreviewCache; int StylePreviewCache::gStylePreviewCacheClients; } @@ -414,6 +421,8 @@ StylesPreviewWindow_Base::StylesPreviewWindow_Base( m_xStylesView->connect_selection_changed(LINK(this, StylesPreviewWindow_Base, Selected)); m_xStylesView->connect_item_activated(LINK(this, StylesPreviewWindow_Base, DoubleClick)); m_xStylesView->connect_command(LINK(this, StylesPreviewWindow_Base, DoCommand)); + m_xStylesView->connect_get_property_tree_elem( + LINK(this, StylesPreviewWindow_Base, DoJsonProperty)); m_xStatusListener = new StyleStatusListener(this, xDispatchProvider); @@ -497,6 +506,44 @@ void StylesListUpdateTask::Invoke() m_rStylesList.UpdateSelection(); } +static OString extractPngString(const BitmapEx& rBitmap) +{ + SvMemoryStream aOStm(65535, 65535); + // Use fastest compression "1" + css::uno::Sequence<css::beans::PropertyValue> aFilterData{ + comphelper::makePropertyValue("Compression", sal_Int32(1)), + }; + vcl::PngImageWriter aPNGWriter(aOStm); + aPNGWriter.setParameters(aFilterData); + if (aPNGWriter.write(rBitmap)) + { + css::uno::Sequence<sal_Int8> aSeq(static_cast<sal_Int8 const*>(aOStm.GetData()), + aOStm.Tell()); + OStringBuffer aBuffer("data:image/png;base64,"); + ::comphelper::Base64::encode(aBuffer, aSeq); + return aBuffer.makeStringAndClear(); + } + + return ""; +} + +// 0: json writer, 1: id, 2: property. returns true if supported +IMPL_STATIC_LINK(StylesPreviewWindow_Base, DoJsonProperty, const tools::json_prop_query&, rQuery, + bool) +{ + if (std::get<2>(rQuery) != "image") + return false; + + OString sBase64Png(GetCachedPreviewJson(std::get<1>(rQuery))); + if (sBase64Png.isEmpty()) + return false; + + tools::JsonWriter& rJsonWriter = std::get<0>(rQuery); + rJsonWriter.put("image", sBase64Png); + + return true; +} + VclPtr<VirtualDevice> StylesPreviewWindow_Base::GetCachedPreview(const std::pair<OUString, OUString>& rStyle) { @@ -517,6 +564,23 @@ StylesPreviewWindow_Base::GetCachedPreview(const std::pair<OUString, OUString>& } } +OString StylesPreviewWindow_Base::GetCachedPreviewJson(const OUString& rStyle) +{ + auto aJsonFound = StylePreviewCache::GetJson().find(rStyle); + if (aJsonFound != StylePreviewCache::GetJson().end()) + return StylePreviewCache::GetJson()[rStyle]; + + auto aFound = StylePreviewCache::Get().find(rStyle); + if (aFound == StylePreviewCache::Get().end()) + return ""; + + VclPtr<VirtualDevice> xDev = aFound->second; + BitmapEx aBitmap(xDev->GetBitmapEx(Point(0, 0), xDev->GetOutputSize())); + OString sResult = extractPngString(aBitmap); + StylePreviewCache::GetJson()[rStyle] = sResult; + return sResult; +} + void StylesPreviewWindow_Base::UpdateStylesList() { m_aAllStyles = m_aDefaultStyles; @@ -536,7 +600,8 @@ void StylesPreviewWindow_Base::UpdateStylesList() while (pStyle) { - m_aAllStyles.push_back(std::pair<OUString, OUString>("", pStyle->GetName())); + OUString sName(pStyle->GetName()); + m_aAllStyles.push_back(std::pair<OUString, OUString>(sName, sName)); pStyle = xIter->Next(); } } |