include/tools/helpers.hxx | 16 ++- include/vcl/ITiledRenderable.hxx | 6 + sd/source/ui/inc/unomodel.hxx | 3 sd/source/ui/unoidl/unomodel.cxx | 202 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 225 insertions(+), 2 deletions(-)
New commits: commit 649ecf83b7e2b9891b4545a58e7091db854d7870 Author: Marco Cecchetti <marco.cecche...@collabora.com> AuthorDate: Tue Jun 25 18:59:23 2024 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Tue Jun 25 17:10:44 2024 +0200 sd: function to return a presentation info in a JSON document The presentation info includes properties like document size, if the slide is visible, master slide information and similar. Change-Id: I5b0acff2ee0df351dd1859e02695ca249e17c391 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169481 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/include/tools/helpers.hxx b/include/tools/helpers.hxx index 05ee59960f50..9a2db3388ce5 100644 --- a/include/tools/helpers.hxx +++ b/include/tools/helpers.hxx @@ -7,12 +7,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once - +#include <com/sun/star/uno/Reference.h> #include <sal/config.h> #include <sal/types.h> #include <tools/long.hxx> #include <cassert> #include <limits> +#include <string> #include <type_traits> inline sal_uInt32 AlignedWidth4Bytes(sal_uInt32 nWidthBits) @@ -54,4 +55,17 @@ template <typename T> [[nodiscard]] inline T NormAngle360(T angle) return angle; } +// get hash from interface +// TODO: UNIT TEST +[[nodiscard]] inline +std::string GetInterfaceHash(const ::css::uno::Reference<::css::uno::XInterface>& xIf) +{ + if (xIf.is()) + { + auto ptr = reinterpret_cast<sal_uIntPtr>(xIf.get()); + return std::to_string(ptr); + } + return {}; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx index be6c050ad36d..483176aca3b8 100644 --- a/include/vcl/ITiledRenderable.hxx +++ b/include/vcl/ITiledRenderable.hxx @@ -384,6 +384,12 @@ public: * @param pViewShell the view to get the options from, if nullptr the current view shell is used */ virtual OString getViewRenderState(SfxViewShell* = nullptr) { return rtl::OString(); } + + /** Return JSON structure filled with the information about the presentation (Impress only function) */ + virtual OString getPresentationInfo() const + { + return {}; + } }; } // namespace vcl diff --git a/sd/source/ui/inc/unomodel.hxx b/sd/source/ui/inc/unomodel.hxx index e0fa051d8826..0cf13555ddfa 100644 --- a/sd/source/ui/inc/unomodel.hxx +++ b/sd/source/ui/inc/unomodel.hxx @@ -287,6 +287,9 @@ public: /// @see vcl::ITiledRenderable::getViewRenderState(). OString getViewRenderState(SfxViewShell* pViewShell = nullptr) override; + /// @see vcl::ITiledRenderable::getPresentationInfo(). + OString getPresentationInfo() const override; + // XComponent /** This dispose implementation releases the resources held by the diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index 45291ec0ce64..efda0612a3cc 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -21,6 +21,7 @@ #include <com/sun/star/presentation/XPresentation2.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/lang/DisposedException.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> #include <com/sun/star/lang/ServiceNotRegisteredException.hpp> @@ -79,6 +80,8 @@ #include <editeng/eeitem.hxx> #include <unotools/datetime.hxx> #include <xmloff/autolayout.hxx> +#include <tools/json_writer.hxx> +#include <tools/helpers.hxx> // Support creation of GraphicStorageHandler and EmbeddedObjectResolver #include <svx/xmleohlp.hxx> @@ -190,8 +193,120 @@ private: SdrModel* mpModel; }; +class SlideBackgroundInfo +{ +public: + SlideBackgroundInfo(const uno::Reference<drawing::XDrawPage>& xDrawPage, + const uno::Reference<drawing::XDrawPage>& xMasterPage); + bool slideHasOwnBackground() const { return mbIsCustom; } + bool hasBackground() const { return bHasBackground; } + bool isSolidColor() const { return mbIsSolidColor; } + ::Color getFillColor() const; + sal_Int32 getFillTransparency() const; + OString getFillColorAsRGBA() const; +private: + bool getFillStyleImpl(const uno::Reference<drawing::XDrawPage>& xDrawPage); +private: + uno::Reference<drawing::XDrawPage> mxDrawPage; + uno::Reference<drawing::XDrawPage> mxMasterPage; + uno::Reference<beans::XPropertySet> mxBackground; + bool mbIsCustom; + bool bHasBackground; + bool mbIsSolidColor; + drawing::FillStyle maFillStyle; +}; + +SlideBackgroundInfo::SlideBackgroundInfo( + const uno::Reference<drawing::XDrawPage>& xDrawPage, + const uno::Reference<drawing::XDrawPage>& xMasterPage) + : mxDrawPage(xDrawPage) + , mxMasterPage(xMasterPage) + , mbIsCustom(false) + , bHasBackground(false) + , mbIsSolidColor(false) + , maFillStyle(drawing::FillStyle_NONE) +{ + mbIsCustom = getFillStyleImpl(xDrawPage); + bHasBackground = mbIsCustom; + if (!bHasBackground) + { + bHasBackground = getFillStyleImpl(xMasterPage); + } + if (bHasBackground) + { + if (maFillStyle == drawing::FillStyle_SOLID) + { + OUString sGradientName; + mxBackground->getPropertyValue("FillTransparenceGradientName") >>= sGradientName; + if (sGradientName.isEmpty()) + { + mbIsSolidColor = true; + } + } + } +} + +sal_Int32 SlideBackgroundInfo::getFillTransparency() const +{ + if (!mxBackground.is()) + return 0; + sal_Int32 nFillTransparency = 0; + mxBackground->getPropertyValue("FillTransparence") >>= nFillTransparency; + return nFillTransparency; +} + +::Color SlideBackgroundInfo::getFillColor() const +{ + if (!mxBackground.is()) + return {}; + if (sal_Int32 nFillColor; mxBackground->getPropertyValue("FillColor") >>= nFillColor) + { + return ::Color(ColorTransparency, nFillColor & 0xffffff); + } + return {}; +} + +OString SlideBackgroundInfo::getFillColorAsRGBA() const +{ + ::Color aColor = getFillColor(); + OString sColor = aColor.AsRGBHEXString().toUtf8(); + sal_uInt32 nAlpha = std::round((100 - getFillTransparency()) * 255 / 100.0); + std::stringstream ss; + ss << std::hex << std::uppercase << std::setfill ('0') << std::setw(2) << nAlpha; + sColor += ss.str().c_str(); + return sColor; +} + +bool SlideBackgroundInfo::getFillStyleImpl(const uno::Reference<drawing::XDrawPage>& xDrawPage) +{ + if( xDrawPage.is() ) + { + uno::Reference< beans::XPropertySet > xPropSet( xDrawPage, uno::UNO_QUERY ); + if( xPropSet.is() ) + { + uno::Reference< beans::XPropertySet > xBackground; + if (xPropSet->getPropertySetInfo()->hasPropertyByName("Background")) + xPropSet->getPropertyValue( "Background" ) >>= xBackground; + if( xBackground.is() ) + { + drawing::FillStyle aFillStyle; + if( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle ) + { + maFillStyle = aFillStyle; + if (aFillStyle != drawing::FillStyle_NONE) + { + mxBackground = xBackground; + return true; + } + } + } + } + } + return false; } +} // end anonymous namespace + SdUnoForbiddenCharsTable::SdUnoForbiddenCharsTable( SdrModel* pModel ) : SvxUnoForbiddenCharsTable( pModel->GetForbiddenCharsTable() ), mpModel( pModel ) { @@ -2475,7 +2590,8 @@ OUString SdXImpressDocument::getPartHash(int nPart) return OUString(); } - return OUString::number(pPage->GetHashCode()); + uno::Reference<drawing::XDrawPage> xDrawPage(pPage->getUnoPage(), uno::UNO_QUERY); + return OUString::fromUtf8(GetInterfaceHash(xDrawPage)); } bool SdXImpressDocument::isMasterViewMode() @@ -2881,6 +2997,90 @@ void SdXImpressDocument::initializeDocument() } } +OString SdXImpressDocument::getPresentationInfo() const +{ + ::tools::JsonWriter aJsonWriter; + + try + { + uno::Reference<container::XIndexAccess> xSlides(mxDrawPagesAccess.get(), uno::UNO_QUERY_THROW); + if (xSlides.is()) + { + // size in twips + Size aDocSize = const_cast<SdXImpressDocument*>(this)->getDocumentSize(); + aJsonWriter.put("docWidth", aDocSize.getWidth()); + aJsonWriter.put("docHeight", aDocSize.getHeight()); + + ::tools::ScopedJsonWriterArray aSlideList = aJsonWriter.startArray("slides"); + sal_Int32 nSlideCount = xSlides->getCount(); + for (sal_Int32 i = 0; i < nSlideCount; ++i) + { + uno::Reference<drawing::XDrawPage> xSlide(xSlides->getByIndex(i), uno::UNO_QUERY_THROW); + if (xSlide.is()) + { + uno::Reference<XPropertySet> xPropSet(xSlide, uno::UNO_QUERY); + if (xPropSet.is()) + { + bool bIsVisible = true; // default visible + xPropSet->getPropertyValue("Visible") >>= bIsVisible; + if (bIsVisible) + { + ::tools::ScopedJsonWriterStruct aSlideNode = aJsonWriter.startStruct(); + std::string sSlideHash = GetInterfaceHash(xSlide); + aJsonWriter.put("hash", sSlideHash); + aJsonWriter.put("index", i); + + uno::Reference<drawing::XShapes> xSlideShapes(xSlide, uno::UNO_QUERY_THROW); + bool bIsDrawPageEmpty = true; + if (xSlideShapes.is()) { + bIsDrawPageEmpty = xSlideShapes->getCount() == 0; + } + aJsonWriter.put("empty", bIsDrawPageEmpty); + + uno::Reference<drawing::XDrawPage> xMasterPage; + uno::Reference<drawing::XMasterPageTarget> xMasterPageTarget(xSlide, uno::UNO_QUERY); + if (xMasterPageTarget.is()) + { + xMasterPage = xMasterPageTarget->getMasterPage(); + if (xMasterPage.is()) + { + std::string sMPHash = GetInterfaceHash(xMasterPage); + aJsonWriter.put("masterPage", sMPHash); + + bool bBackgroundObjectsVisibility = true; // default visible + xPropSet->getPropertyValue("IsBackgroundObjectsVisible") >>= bBackgroundObjectsVisibility; + aJsonWriter.put("masterPageObjectsVisible", bBackgroundObjectsVisibility); + } + } + + bool bBackgroundVisibility = true; // default visible + xPropSet->getPropertyValue("IsBackgroundVisible") >>= bBackgroundVisibility; + if (bBackgroundVisibility) + { + SlideBackgroundInfo aSlideBackgroundInfo(xSlide, xMasterPage); + if (aSlideBackgroundInfo.hasBackground()) + { + ::tools::ScopedJsonWriterNode aBackgroundNode = aJsonWriter.startNode("background"); + aJsonWriter.put("isCustom", aSlideBackgroundInfo.slideHasOwnBackground()); + if (aSlideBackgroundInfo.isSolidColor()) + { + aJsonWriter.put("fillColor", aSlideBackgroundInfo.getFillColorAsRGBA()); + } + } + } + } + } + } + } + } + } + catch (uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "SdXImpressDocument::getSlideShowInfo ... maybe some property can't be retrieved" ); + } + return aJsonWriter.finishAndGetAsOString(); +} + SdrModel& SdXImpressDocument::getSdrModelFromUnoModel() const { OSL_ENSURE(GetDoc(), "No SdrModel in draw/Impress, should not happen");