diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /svx/source/unodraw | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svx/source/unodraw')
32 files changed, 19060 insertions, 0 deletions
diff --git a/svx/source/unodraw/SvxXTextColumns.cxx b/svx/source/unodraw/SvxXTextColumns.cxx new file mode 100644 index 000000000..a0e399bd4 --- /dev/null +++ b/svx/source/unodraw/SvxXTextColumns.cxx @@ -0,0 +1,338 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyVetoException.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/text/ColumnSeparatorStyle.hpp> +#include <com/sun/star/text/XTextColumns.hpp> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/util/Color.hpp> + +#include <cppuhelper/supportsservice.hxx> +#include <o3tl/safeint.hxx> +#include <svl/itemprop.hxx> +#include <svx/SvxXTextColumns.hxx> +#include <tools/UnitConversion.hxx> +#include <vcl/svapp.hxx> + +#include <numeric> + +namespace +{ +enum : sal_uInt16 +{ + WID_TXTCOL_IS_AUTOMATIC, + WID_TXTCOL_AUTO_DISTANCE, + WID_TXTCOL_LINE_WIDTH, + WID_TXTCOL_LINE_COLOR, + WID_TXTCOL_LINE_REL_HGT, + WID_TXTCOL_LINE_ALIGN, + WID_TXTCOL_LINE_IS_ON, + WID_TXTCOL_LINE_STYLE, +}; + +SfxItemPropertyMapEntry const saTextColumns_Impl[] = { + { u"IsAutomatic", WID_TXTCOL_IS_AUTOMATIC, cppu::UnoType<bool>::get(), + css::beans::PropertyAttribute::READONLY, 0 }, + { u"AutomaticDistance", WID_TXTCOL_AUTO_DISTANCE, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"SeparatorLineWidth", WID_TXTCOL_LINE_WIDTH, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"SeparatorLineColor", WID_TXTCOL_LINE_COLOR, + cppu::UnoType<com::sun::star::util::Color>::get(), 0, 0 }, + { u"SeparatorLineRelativeHeight", WID_TXTCOL_LINE_REL_HGT, cppu::UnoType<sal_Int32>::get(), 0, + 0 }, + { u"SeparatorLineVerticalAlignment", WID_TXTCOL_LINE_ALIGN, + cppu::UnoType<css::style::VerticalAlignment>::get(), 0, 0 }, + { u"SeparatorLineIsOn", WID_TXTCOL_LINE_IS_ON, cppu::UnoType<bool>::get(), 0, 0 }, + { u"SeparatorLineStyle", WID_TXTCOL_LINE_STYLE, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"", 0, css::uno::Type(), 0, 0 }, +}; + +class SvxXTextColumns final + : public cppu::WeakImplHelper<css::beans::XPropertySet, css::text::XTextColumns, + css::lang::XServiceInfo> +{ +public: + SvxXTextColumns() = default; + + // XTextColumns + virtual sal_Int32 SAL_CALL getReferenceValue() override; + virtual sal_Int16 SAL_CALL getColumnCount() override; + virtual void SAL_CALL setColumnCount(sal_Int16 nColumns) override; + virtual css::uno::Sequence<css::text::TextColumn> SAL_CALL getColumns() override; + virtual void SAL_CALL + setColumns(const css::uno::Sequence<css::text::TextColumn>& Columns) override; + + // XPropertySet + virtual css::uno::Reference<css::beans::XPropertySetInfo> + SAL_CALL getPropertySetInfo() override; + virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, + const css::uno::Any& aValue) override; + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& PropertyName) override; + virtual void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference<css::beans::XPropertyChangeListener>& xListener) override; + virtual void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference<css::beans::XPropertyChangeListener>& aListener) override; + virtual void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference<css::beans::XVetoableChangeListener>& aListener) override; + virtual void SAL_CALL removeVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference<css::beans::XVetoableChangeListener>& aListener) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + +private: + sal_Int32 m_nReference = USHRT_MAX; + css::uno::Sequence<css::text::TextColumn> m_aTextColumns; + bool m_bIsAutomaticWidth = true; + sal_Int32 m_nAutoDistance = 0; + + const SfxItemPropertySet m_aPropSet = { saTextColumns_Impl }; + + //separator line + sal_Int32 m_nSepLineWidth = 0; + com::sun::star::util::Color m_nSepLineColor = 0; // black + sal_Int32 m_nSepLineHeightRelative = 100; // full height + css::style::VerticalAlignment m_nSepLineVertAlign = css::style::VerticalAlignment_MIDDLE; + bool m_bSepLineIsOn = false; + sal_Int16 m_nSepLineStyle = css::text::ColumnSeparatorStyle::NONE; +}; + +OUString SvxXTextColumns::getImplementationName() { return "com.sun.star.comp.svx.TextColumns"; } + +sal_Bool SvxXTextColumns::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence<OUString> SvxXTextColumns::getSupportedServiceNames() +{ + return { "com.sun.star.text.TextColumns" }; +} + +sal_Int32 SvxXTextColumns::getReferenceValue() +{ + SolarMutexGuard aGuard; + return m_nReference; +} + +sal_Int16 SvxXTextColumns::getColumnCount() +{ + SolarMutexGuard aGuard; + return o3tl::narrowing<sal_Int16>(m_aTextColumns.getLength()); +} + +void SvxXTextColumns::setColumnCount(sal_Int16 nColumns) +{ + SolarMutexGuard aGuard; + if (nColumns <= 0) + throw css::uno::RuntimeException(); + m_bIsAutomaticWidth = true; + m_aTextColumns.realloc(nColumns); + css::text::TextColumn* pCols = m_aTextColumns.getArray(); + m_nReference = USHRT_MAX; + sal_Int32 nWidth = m_nReference / nColumns; + sal_Int32 nDiff = m_nReference - nWidth * nColumns; + sal_Int32 nDist = m_nAutoDistance / 2; + for (sal_Int16 i = 0; i < nColumns; i++) + { + pCols[i].Width = nWidth; + pCols[i].LeftMargin = i == 0 ? 0 : nDist; + pCols[i].RightMargin = i == nColumns - 1 ? 0 : nDist; + } + pCols[nColumns - 1].Width += nDiff; +} + +css::uno::Sequence<css::text::TextColumn> SvxXTextColumns::getColumns() +{ + SolarMutexGuard aGuard; + return m_aTextColumns; +} + +void SvxXTextColumns::setColumns(const css::uno::Sequence<css::text::TextColumn>& rColumns) +{ + SolarMutexGuard aGuard; + sal_Int32 nReferenceTemp = std::accumulate( + rColumns.begin(), rColumns.end(), sal_Int32(0), + [](const sal_Int32 nSum, const css::text::TextColumn& rCol) { return nSum + rCol.Width; }); + m_bIsAutomaticWidth = false; + m_nReference = !nReferenceTemp ? USHRT_MAX : nReferenceTemp; + m_aTextColumns = rColumns; +} + +css::uno::Reference<css::beans::XPropertySetInfo> SvxXTextColumns::getPropertySetInfo() +{ + return m_aPropSet.getPropertySetInfo(); +} + +void SvxXTextColumns::setPropertyValue(const OUString& rPropertyName, const css::uno::Any& aValue) +{ + const SfxItemPropertyMapEntry* pEntry = m_aPropSet.getPropertyMap().getByName(rPropertyName); + if (!pEntry) + throw css::beans::UnknownPropertyException("Unknown property: " + rPropertyName, + static_cast<cppu::OWeakObject*>(this)); + if (pEntry->nFlags & css::beans::PropertyAttribute::READONLY) + throw css::beans::PropertyVetoException("Property is read-only: " + rPropertyName, + static_cast<cppu::OWeakObject*>(this)); + + switch (pEntry->nWID) + { + case WID_TXTCOL_LINE_WIDTH: + { + sal_Int32 nTmp; + if (!(aValue >>= nTmp) || nTmp < 0) + throw css::lang::IllegalArgumentException(); + m_nSepLineWidth = nTmp; + break; + } + case WID_TXTCOL_LINE_COLOR: + if (!(aValue >>= m_nSepLineColor)) + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_LINE_STYLE: + if (!(aValue >>= m_nSepLineStyle)) + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_LINE_REL_HGT: + { + sal_Int32 nTmp; + if (!(aValue >>= nTmp) || nTmp < 0) + throw css::lang::IllegalArgumentException(); + m_nSepLineHeightRelative = nTmp; + break; + } + case WID_TXTCOL_LINE_ALIGN: + if (css::style::VerticalAlignment eAlign; aValue >>= eAlign) + m_nSepLineVertAlign = eAlign; + else if (sal_Int8 nTmp; aValue >>= nTmp) + m_nSepLineVertAlign = static_cast<css::style::VerticalAlignment>(nTmp); + else + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_LINE_IS_ON: + if (!(aValue >>= m_bSepLineIsOn)) + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_AUTO_DISTANCE: + { + sal_Int32 nTmp; + if (!(aValue >>= nTmp) || nTmp < 0 || nTmp >= m_nReference) + throw css::lang::IllegalArgumentException(); + m_nAutoDistance = nTmp; + sal_Int32 nColumns = m_aTextColumns.getLength(); + css::text::TextColumn* pCols = m_aTextColumns.getArray(); + sal_Int32 nDist = m_nAutoDistance / 2; + for (sal_Int32 i = 0; i < nColumns; i++) + { + pCols[i].LeftMargin = i == 0 ? 0 : nDist; + pCols[i].RightMargin = i == nColumns - 1 ? 0 : nDist; + } + break; + } + } +} + +css::uno::Any SvxXTextColumns::getPropertyValue(const OUString& rPropertyName) +{ + const SfxItemPropertyMapEntry* pEntry = m_aPropSet.getPropertyMap().getByName(rPropertyName); + if (!pEntry) + throw css::beans::UnknownPropertyException("Unknown property: " + rPropertyName, + static_cast<cppu::OWeakObject*>(this)); + + css::uno::Any aRet; + switch (pEntry->nWID) + { + case WID_TXTCOL_LINE_WIDTH: + aRet <<= m_nSepLineWidth; + break; + case WID_TXTCOL_LINE_COLOR: + aRet <<= m_nSepLineColor; + break; + case WID_TXTCOL_LINE_STYLE: + aRet <<= m_nSepLineStyle; + break; + case WID_TXTCOL_LINE_REL_HGT: + aRet <<= m_nSepLineHeightRelative; + break; + case WID_TXTCOL_LINE_ALIGN: + aRet <<= m_nSepLineVertAlign; + break; + case WID_TXTCOL_LINE_IS_ON: + aRet <<= m_bSepLineIsOn; + break; + case WID_TXTCOL_IS_AUTOMATIC: + aRet <<= m_bIsAutomaticWidth; + break; + case WID_TXTCOL_AUTO_DISTANCE: + aRet <<= m_nAutoDistance; + break; + } + return aRet; +} + +void SvxXTextColumns::addPropertyChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference<css::beans::XPropertyChangeListener>& /*xListener*/) +{ +} + +void SvxXTextColumns::removePropertyChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference<css::beans::XPropertyChangeListener>& /*xListener*/) +{ +} + +void SvxXTextColumns::addVetoableChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference<css::beans::XVetoableChangeListener>& /*xListener*/) +{ +} + +void SvxXTextColumns::removeVetoableChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference<css::beans::XVetoableChangeListener>& /*xListener*/) +{ +} +} + +css::uno::Reference<css::uno::XInterface> SvxXTextColumns_createInstance() noexcept +{ + return static_cast<cppu::OWeakObject*>(new SvxXTextColumns); +} + +extern "C" SVXCORE_DLLPUBLIC css::uno::XInterface* +com_sun_star_comp_svx_TextColumns_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SvxXTextColumns); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/svx/source/unodraw/UnoGraphicExporter.cxx b/svx/source/unodraw/UnoGraphicExporter.cxx new file mode 100644 index 000000000..0cc43ce70 --- /dev/null +++ b/svx/source/unodraw/UnoGraphicExporter.cxx @@ -0,0 +1,1318 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vector> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XGraphicExportFilter.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/XGraphicRenderer.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionContinuation.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/urlobj.hxx> +#include <comphelper/interaction.hxx> +#include <framework/interaction.hxx> +#include <com/sun/star/drawing/GraphicFilterRequest.hpp> +#include <com/sun/star/util/URL.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <vcl/metaact.hxx> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> +#include <svl/outstrm.hxx> +#include <sdr/contact/objectcontactofobjlistpainter.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <editeng/numitem.hxx> +#include <svx/svdograf.hxx> +#include <svx/xoutbmp.hxx> +#include <vcl/graphicfilter.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmodel.hxx> +#include <svx/fmview.hxx> +#include <svx/fmmodel.hxx> +#include <svx/unopage.hxx> +#include <svx/svdoutl.hxx> +#include <svx/xlineit0.hxx> +#include <editeng/flditem.hxx> +#include <svtools/optionsdrawinglayer.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/sequence.hxx> +#include "UnoGraphicExporter.hxx" +#include <memory> + +#define MAX_EXT_PIX 2048 + +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::task; + +// #i102251# +#include <editeng/editstat.hxx> + +namespace { + + struct ExportSettings + { + OUString maFilterName; + OUString maMediaType; + URL maURL; + css::uno::Reference< css::io::XOutputStream > mxOutputStream; + css::uno::Reference< css::graphic::XGraphicRenderer > mxGraphicRenderer; + css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator; + css::uno::Reference< css::task::XInteractionHandler > mxInteractionHandler; + + sal_Int32 mnWidth; + sal_Int32 mnHeight; + bool mbExportOnlyBackground; + bool mbScrollText; + bool mbUseHighContrast; + bool mbTranslucent; + + Sequence< PropertyValue > maFilterData; + + Fraction maScaleX; + Fraction maScaleY; + + TriState meAntiAliasing = TRISTATE_INDET; + + explicit ExportSettings(const SdrModel* pSdrModel); + }; + + ExportSettings::ExportSettings(const SdrModel* pSdrModel) + : mnWidth( 0 ) + ,mnHeight( 0 ) + ,mbExportOnlyBackground( false ) + ,mbScrollText( false ) + ,mbUseHighContrast( false ) + ,mbTranslucent( false ) + ,maScaleX( 1, 1 ) + ,maScaleY( 1, 1 ) + { + if (pSdrModel) + { + maScaleX = pSdrModel->GetScaleFraction(); + maScaleY = pSdrModel->GetScaleFraction(); + } + } + + /** implements a component to export shapes or pages to external graphic formats. + + @implements com.sun.star.drawing.GraphicExportFilter + */ + class GraphicExporter : public WeakImplHelper< XGraphicExportFilter, XServiceInfo > + { + public: + GraphicExporter(); + + // XFilter + virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) override; + virtual void SAL_CALL cancel( ) override; + + // XExporter + virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XMimeTypeInfo + virtual sal_Bool SAL_CALL supportsMimeType( const OUString& MimeTypeName ) override; + virtual Sequence< OUString > SAL_CALL getSupportedMimeTypeNames( ) override; + + VclPtr<VirtualDevice> CreatePageVDev( SdrPage* pPage, tools::Long nWidthPixel, tools::Long nHeightPixel ) const; + + DECL_LINK( CalcFieldValueHdl, EditFieldInfo*, void ); + + void ParseSettings( const Sequence< PropertyValue >& aDescriptor, ExportSettings& rSettings ); + bool GetGraphic( ExportSettings const & rSettings, Graphic& aGraphic, bool bVectorType ); + + private: + Reference< XShape > mxShape; + Reference< XDrawPage > mxPage; + Reference< XShapes > mxShapes; + Graphic maGraphic; + + SvxDrawPage* mpUnoPage; + + Link<EditFieldInfo*,void> maOldCalcFieldValueHdl; + sal_Int32 mnPageNumber; + SdrPage* mpCurrentPage; + SdrModel* mpDoc; + }; + + /** creates a bitmap that is optionally transparent from a metafile + */ + BitmapEx GetBitmapFromMetaFile( const GDIMetaFile& rMtf, const Size* pSize ) + { + // use new primitive conversion tooling + basegfx::B2DRange aRange(basegfx::B2DPoint(0.0, 0.0)); + sal_uInt32 nMaximumQuadraticPixels(500000); + + if(pSize) + { + // use 100th mm for primitive bitmap converter tool, input is pixel + // use a real OutDev to get the correct DPI, the static LogicToLogic assumes 72dpi which is wrong (!) + const Size aSize100th(Application::GetDefaultDevice()->PixelToLogic(*pSize, MapMode(MapUnit::Map100thMM))); + + aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height())); + + // when explicitly pixels are requested from the GraphicExporter, use a *very* high limit + // of 16gb (4096x4096 pixels), else use the default for the converters + nMaximumQuadraticPixels = std::min(sal_uInt32(4096 * 4096), sal_uInt32(pSize->Width() * pSize->Height())); + } + else + { + // use 100th mm for primitive bitmap converter tool + const Size aSize100th(OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM))); + + aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height())); + } + + return convertMetafileToBitmapEx(rMtf, aRange, nMaximumQuadraticPixels); + } + + Size* CalcSize( sal_Int32 nWidth, sal_Int32 nHeight, const Size& aBoundSize, Size& aOutSize ) + { + if( (nWidth == 0) && (nHeight == 0) ) + return nullptr; + + if( (nWidth == 0) && (nHeight != 0) && (aBoundSize.Height() != 0) ) + { + nWidth = ( nHeight * aBoundSize.Width() ) / aBoundSize.Height(); + } + else if( (nWidth != 0) && (nHeight == 0) && (aBoundSize.Width() != 0) ) + { + nHeight = ( nWidth * aBoundSize.Height() ) / aBoundSize.Width(); + } + + aOutSize.setWidth( nWidth ); + aOutSize.setHeight( nHeight ); + + return &aOutSize; + } + +class ImplExportCheckVisisbilityRedirector : public sdr::contact::ViewObjectContactRedirector +{ +public: + explicit ImplExportCheckVisisbilityRedirector( SdrPage* pCurrentPage ); + + virtual void createRedirectedPrimitive2DSequence( + const sdr::contact::ViewObjectContact& rOriginal, + const sdr::contact::DisplayInfo& rDisplayInfo, + drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) override; + +private: + SdrPage* mpCurrentPage; +}; + +ImplExportCheckVisisbilityRedirector::ImplExportCheckVisisbilityRedirector( SdrPage* pCurrentPage ) +: mpCurrentPage( pCurrentPage ) +{ +} + +void ImplExportCheckVisisbilityRedirector::createRedirectedPrimitive2DSequence( + const sdr::contact::ViewObjectContact& rOriginal, + const sdr::contact::DisplayInfo& rDisplayInfo, + drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) +{ + SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject(); + + if(pObject) + { + SdrPage* pPage = mpCurrentPage; + + if(nullptr == pPage) + { + pPage = pObject->getSdrPageFromSdrObject(); + } + + if( (pPage == nullptr) || pPage->checkVisibility(rOriginal, rDisplayInfo, false) ) + { + return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor); + } + + return; + } + else + { + // not an object, maybe a page + sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor); + } +} + +GraphicExporter::GraphicExporter() +: mpUnoPage( nullptr ), mnPageNumber(-1), mpCurrentPage(nullptr), mpDoc( nullptr ) +{ +} + +IMPL_LINK(GraphicExporter, CalcFieldValueHdl, EditFieldInfo*, pInfo, void) +{ + if( pInfo ) + { + if( mpCurrentPage ) + { + pInfo->SetSdrPage( mpCurrentPage ); + } + else if( mnPageNumber != -1 ) + { + const SvxFieldData* pField = pInfo->GetField().GetField(); + if( dynamic_cast<const SvxPageField*>( pField) ) + { + OUString aPageNumValue; + bool bUpper = false; + + switch(mpDoc->GetPageNumType()) + { + case css::style::NumberingType::CHARS_UPPER_LETTER: + aPageNumValue += OUStringChar( sal_Unicode((mnPageNumber - 1) % 26 + 'A') ); + break; + case css::style::NumberingType::CHARS_LOWER_LETTER: + aPageNumValue += OUStringChar( sal_Unicode((mnPageNumber - 1) % 26 + 'a') ); + break; + case css::style::NumberingType::ROMAN_UPPER: + bUpper = true; + [[fallthrough]]; + case css::style::NumberingType::ROMAN_LOWER: + aPageNumValue += SvxNumberFormat::CreateRomanString(mnPageNumber, bUpper); + break; + case css::style::NumberingType::NUMBER_NONE: + aPageNumValue = " "; + break; + default: + aPageNumValue += OUString::number( mnPageNumber ); + } + + pInfo->SetRepresentation( aPageNumValue ); + + return; + } + } + } + + maOldCalcFieldValueHdl.Call( pInfo ); + + if( pInfo && mpCurrentPage ) + pInfo->SetSdrPage( nullptr ); +} + +/** creates a virtual device for the given page + + @return the returned VirtualDevice is owned by the caller +*/ +VclPtr<VirtualDevice> GraphicExporter::CreatePageVDev( SdrPage* pPage, tools::Long nWidthPixel, tools::Long nHeightPixel ) const +{ + VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); + MapMode aMM( MapUnit::Map100thMM ); + + Point aPoint( 0, 0 ); + Size aPageSize(pPage->GetSize()); + + // use scaling? + if( nWidthPixel != 0 ) + { + const Fraction aFrac( nWidthPixel, pVDev->LogicToPixel( aPageSize, aMM ).Width() ); + + aMM.SetScaleX( aFrac ); + + if( nHeightPixel == 0 ) + aMM.SetScaleY( aFrac ); + } + + if( nHeightPixel != 0 ) + { + const Fraction aFrac( nHeightPixel, pVDev->LogicToPixel( aPageSize, aMM ).Height() ); + + if( nWidthPixel == 0 ) + aMM.SetScaleX( aFrac ); + + aMM.SetScaleY( aFrac ); + } + + pVDev->SetMapMode( aMM ); + bool bSuccess(false); + + // #i122820# If available, use pixel size directly + if(nWidthPixel && nHeightPixel) + { + bSuccess = pVDev->SetOutputSizePixel(Size(nWidthPixel, nHeightPixel)); + } + else + { + bSuccess = pVDev->SetOutputSize(aPageSize); + } + + if(bSuccess) + { + SdrView aView(*mpDoc, pVDev); + + aView.SetPageVisible( false ); + aView.SetBordVisible( false ); + aView.SetGridVisible( false ); + aView.SetHlplVisible( false ); + aView.SetGlueVisible( false ); + aView.ShowSdrPage(pPage); + + vcl::Region aRegion (tools::Rectangle( aPoint, aPageSize ) ); + + ImplExportCheckVisisbilityRedirector aRedirector( mpCurrentPage ); + + aView.CompleteRedraw(pVDev, aRegion, &aRedirector); + } + else + { + OSL_ENSURE(false, "Could not get a VirtualDevice of requested size (!)"); + } + + return pVDev; +} + +void GraphicExporter::ParseSettings(const Sequence<PropertyValue>& rDescriptor, + ExportSettings& rSettings) +{ + Sequence<PropertyValue> aDescriptor = rDescriptor; + if (aDescriptor.hasElements()) + { + comphelper::SequenceAsHashMap aMap(aDescriptor); + Sequence<PropertyValue> aFilterData; + OUString aFilterOptions; + auto it = aMap.find("FilterData"); + if (it != aMap.end()) + { + it->second >>= aFilterData; + } + it = aMap.find("FilterOptions"); + if (it != aMap.end()) + { + it->second >>= aFilterOptions; + } + if (!aFilterData.hasElements() && !aFilterOptions.isEmpty()) + { + // Allow setting filter data keys from the cmdline. + std::vector<PropertyValue> aData + = comphelper::JsonToPropertyValues(aFilterOptions.toUtf8()); + aFilterData = comphelper::containerToSequence(aData); + if (aFilterData.hasElements()) + { + aMap["FilterData"] <<= aFilterData; + aDescriptor = aMap.getAsConstPropertyValueList(); + } + } + } + + for( const PropertyValue& rValue : aDescriptor ) + { + if ( rValue.Name == "FilterName" ) + { + rValue.Value >>= rSettings.maFilterName; + } + else if ( rValue.Name == "MediaType" ) + { + rValue.Value >>= rSettings.maMediaType; + } + else if ( rValue.Name == "URL" ) + { + if( !( rValue.Value >>= rSettings.maURL ) ) + { + rValue.Value >>= rSettings.maURL.Complete; + } + } + else if ( rValue.Name == "OutputStream" ) + { + rValue.Value >>= rSettings.mxOutputStream; + } + else if ( rValue.Name == "GraphicRenderer" ) + { + rValue.Value >>= rSettings.mxGraphicRenderer; + } + else if ( rValue.Name == "StatusIndicator" ) + { + rValue.Value >>= rSettings.mxStatusIndicator; + } + else if ( rValue.Name == "InteractionHandler" ) + { + rValue.Value >>= rSettings.mxInteractionHandler; + } + else if( rValue.Name == "Width" ) // for compatibility reasons, deprecated + { + rValue.Value >>= rSettings.mnWidth; + } + else if( rValue.Name == "Height" ) // for compatibility reasons, deprecated + { + rValue.Value >>= rSettings.mnHeight; + } + else if( rValue.Name == "ExportOnlyBackground" ) // for compatibility reasons, deprecated + { + rValue.Value >>= rSettings.mbExportOnlyBackground; + } + else if ( rValue.Name == "FilterData" ) + { + rValue.Value >>= rSettings.maFilterData; + + for( PropertyValue& rDataValue : asNonConstRange(rSettings.maFilterData) ) + { + if ( rDataValue.Name == "Translucent" ) + { + if ( !( rDataValue.Value >>= rSettings.mbTranslucent ) ) // SJ: TODO: The GIF Transparency is stored as int32 in + { // configuration files, this has to be changed to boolean + sal_Int32 nTranslucent = 0; + if ( rDataValue.Value >>= nTranslucent ) + rSettings.mbTranslucent = nTranslucent != 0; + } + } + else if ( rDataValue.Name == "PixelWidth" ) + { + rDataValue.Value >>= rSettings.mnWidth; + } + else if ( rDataValue.Name == "PixelHeight" ) + { + rDataValue.Value >>= rSettings.mnHeight; + } + else if( rDataValue.Name == "Width" ) // for compatibility reasons, deprecated + { + rDataValue.Value >>= rSettings.mnWidth; + rDataValue.Name = "PixelWidth"; + } + else if( rDataValue.Name == "Height" ) // for compatibility reasons, deprecated + { + rDataValue.Value >>= rSettings.mnHeight; + rDataValue.Name = "PixelHeight"; + } + else if ( rDataValue.Name == "ExportOnlyBackground" ) + { + rDataValue.Value >>= rSettings.mbExportOnlyBackground; + } + else if ( rDataValue.Name == "HighContrast" ) + { + rDataValue.Value >>= rSettings.mbUseHighContrast; + } + else if ( rDataValue.Name == "PageNumber" ) + { + rDataValue.Value >>= mnPageNumber; + } + else if ( rDataValue.Name == "ScrollText" ) + { + // #110496# Read flag solitary scroll text metafile + rDataValue.Value >>= rSettings.mbScrollText; + } + else if ( rDataValue.Name == "CurrentPage" ) + { + Reference< XDrawPage > xPage; + rDataValue.Value >>= xPage; + if( xPage.is() ) + { + SvxDrawPage* pUnoPage = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage ); + if( pUnoPage && pUnoPage->GetSdrPage() ) + mpCurrentPage = pUnoPage->GetSdrPage(); + } + } + else if ( rDataValue.Name == "ScaleXNumerator" ) + { + sal_Int32 nVal = 1; + if( rDataValue.Value >>= nVal ) + rSettings.maScaleX = Fraction( nVal, rSettings.maScaleX.GetDenominator() ); + } + else if ( rDataValue.Name == "ScaleXDenominator" ) + { + sal_Int32 nVal = 1; + if( rDataValue.Value >>= nVal ) + rSettings.maScaleX = Fraction( rSettings.maScaleX.GetNumerator(), nVal ); + } + else if ( rDataValue.Name == "ScaleYNumerator" ) + { + sal_Int32 nVal = 1; + if( rDataValue.Value >>= nVal ) + rSettings.maScaleY = Fraction( nVal, rSettings.maScaleY.GetDenominator() ); + } + else if ( rDataValue.Name == "ScaleYDenominator" ) + { + sal_Int32 nVal = 1; + if( rDataValue.Value >>= nVal ) + rSettings.maScaleY = Fraction( rSettings.maScaleY.GetNumerator(), nVal ); + } + else if (rDataValue.Name == "AntiAliasing") + { + bool bAntiAliasing; + if (rDataValue.Value >>= bAntiAliasing) + rSettings.meAntiAliasing = bAntiAliasing ? TRISTATE_TRUE : TRISTATE_FALSE; + } + } + } + } + + // putting the StatusIndicator that we got from the MediaDescriptor into our local FilterData copy + if ( rSettings.mxStatusIndicator.is() ) + { + int i = rSettings.maFilterData.getLength(); + rSettings.maFilterData.realloc( i + 1 ); + auto pFilterData = rSettings.maFilterData.getArray(); + pFilterData[ i ].Name = "StatusIndicator"; + pFilterData[ i ].Value <<= rSettings.mxStatusIndicator; + } +} + +bool GraphicExporter::GetGraphic( ExportSettings const & rSettings, Graphic& aGraphic, bool bVectorType ) +{ + if( !mpDoc || !mpUnoPage ) + return false; + + SdrPage* pPage = mpUnoPage->GetSdrPage(); + if( !pPage ) + return false; + + ScopedVclPtrInstance< VirtualDevice > aVDev; + const MapMode aMap( mpDoc->GetScaleUnit(), Point(), rSettings.maScaleX, rSettings.maScaleY ); + + SdrOutliner& rOutl=mpDoc->GetDrawOutliner(); + maOldCalcFieldValueHdl = rOutl.GetCalcFieldValueHdl(); + rOutl.SetCalcFieldValueHdl( LINK(this, GraphicExporter, CalcFieldValueHdl) ); + rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor() ); + + // #i102251# + const EEControlBits nOldCntrl(rOutl.GetControlWord()); + EEControlBits nCntrl = nOldCntrl & ~EEControlBits::ONLINESPELLING; + rOutl.SetControlWord(nCntrl); + + SdrObject* pTempBackgroundShape = nullptr; + std::vector< SdrObject* > aShapes; + bool bRet = true; + + // export complete page? + if ( !mxShape.is() ) + { + if( rSettings.mbExportOnlyBackground ) + { + const SdrPageProperties* pCorrectProperties = pPage->getCorrectSdrPageProperties(); + + if(pCorrectProperties) + { + pTempBackgroundShape = new SdrRectObj( + *mpDoc, + tools::Rectangle(Point(0,0), pPage->GetSize())); + pTempBackgroundShape->SetMergedItemSet(pCorrectProperties->GetItemSet()); + pTempBackgroundShape->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE)); + pTempBackgroundShape->NbcSetStyleSheet(pCorrectProperties->GetStyleSheet(), true); + aShapes.push_back(pTempBackgroundShape); + } + } + else + { + const Size aSize( pPage->GetSize() ); + + // generate a bitmap to convert it to a pixel format. + // For gif pictures there can also be a vector format used (bTranslucent) + if ( !bVectorType && !rSettings.mbTranslucent ) + { + tools::Long nWidthPix = 0; + tools::Long nHeightPix = 0; + if ( rSettings.mnWidth > 0 && rSettings.mnHeight > 0 ) + { + nWidthPix = rSettings.mnWidth; + nHeightPix = rSettings.mnHeight; + } + else + { + const Size aSizePix( Application::GetDefaultDevice()->LogicToPixel( aSize, aMap ) ); + if (aSizePix.Width() > MAX_EXT_PIX || aSizePix.Height() > MAX_EXT_PIX) + { + if (aSizePix.Width() > MAX_EXT_PIX) + nWidthPix = MAX_EXT_PIX; + else + nWidthPix = aSizePix.Width(); + if (aSizePix.Height() > MAX_EXT_PIX) + nHeightPix = MAX_EXT_PIX; + else + nHeightPix = aSizePix.Height(); + + double fWidthDif = static_cast<double>(aSizePix.Width()) / nWidthPix; + double fHeightDif = static_cast<double>(aSizePix.Height()) / nHeightPix; + + if (fWidthDif > fHeightDif) + nHeightPix = static_cast<tools::Long>(aSizePix.Height() / fWidthDif); + else + nWidthPix = static_cast<tools::Long>(aSizePix.Width() / fHeightDif); + } + else + { + nWidthPix = aSizePix.Width(); + nHeightPix = aSizePix.Height(); + } + } + + std::unique_ptr<SdrView> xLocalView; + + if (FmFormModel* pFormModel = dynamic_cast<FmFormModel*>(mpDoc)) + { + xLocalView.reset(new FmFormView(*pFormModel, aVDev)); + } + else + { + xLocalView.reset(new SdrView(*mpDoc, aVDev)); + } + + ScopedVclPtr<VirtualDevice> pVDev(CreatePageVDev( pPage, nWidthPix, nHeightPix )); + + if( pVDev ) + { + aGraphic = pVDev->GetBitmapEx( Point(), pVDev->GetOutputSize() ); + aGraphic.SetPrefMapMode( aMap ); + aGraphic.SetPrefSize( aSize ); + } + } + // create a metafile to export a vector format + else + { + GDIMetaFile aMtf; + + aVDev->SetMapMode( aMap ); + if( rSettings.mbUseHighContrast ) + aVDev->SetDrawMode( aVDev->GetDrawMode() | DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient ); + aVDev->EnableOutput( false ); + aMtf.Record( aVDev ); + Size aNewSize; + + // create a view + std::unique_ptr< SdrView > pView; + + if (FmFormModel *pFormModel = dynamic_cast<FmFormModel*>(mpDoc)) + { + pView.reset(new FmFormView(*pFormModel, aVDev)); + } + else + { + pView.reset(new SdrView(*mpDoc, aVDev)); + } + + pView->SetBordVisible( false ); + pView->SetPageVisible( false ); + pView->ShowSdrPage( pPage ); + + // tdf#96922 completely deactivate EditView PageVisualization, including + // PageBackground (formerly 'wiese'). + pView->SetPagePaintingAllowed(false); + + const Point aNewOrg( pPage->GetLeftBorder(), pPage->GetUpperBorder() ); + aNewSize = Size( aSize.Width() - pPage->GetLeftBorder() - pPage->GetRightBorder(), + aSize.Height() - pPage->GetUpperBorder() - pPage->GetLowerBorder() ); + const tools::Rectangle aClipRect( aNewOrg, aNewSize ); + MapMode aVMap( aMap ); + + aVDev->Push(); + aVMap.SetOrigin( Point( -aNewOrg.X(), -aNewOrg.Y() ) ); + aVDev->SetRelativeMapMode( aVMap ); + aVDev->IntersectClipRegion( aClipRect ); + + // Use new StandardCheckVisisbilityRedirector + ImplExportCheckVisisbilityRedirector aRedirector( mpCurrentPage ); + + pView->CompleteRedraw(aVDev, vcl::Region(tools::Rectangle(aNewOrg, aNewSize)), &aRedirector); + + aVDev->Pop(); + + aMtf.Stop(); + aMtf.WindStart(); + aMtf.SetPrefMapMode( aMap ); + aMtf.SetPrefSize( aNewSize ); + + // AW: Here the current version was filtering out the MetaActionType::CLIPREGIONs + // from the metafile. I asked some other developers why this was done, but no + // one knew a direct reason. Since it's in for long time, it may be an old + // piece of code. MetaFiles save and load ClipRegions with polygons with preserving + // the polygons, so a resolution-independent roundtrip is supported. Removed this + // code since it destroys some MetaFiles where ClipRegions are used. Anyways, + // just filtering them out is a hack, at least the encapsulated content would need + // to be clipped geometrically. + aGraphic = Graphic(aMtf); + + pView->HideSdrPage(); + + if( rSettings.mbTranslucent ) + { + Size aOutSize; + aGraphic = GetBitmapFromMetaFile( aGraphic.GetGDIMetaFile(), CalcSize( rSettings.mnWidth, rSettings.mnHeight, aNewSize, aOutSize ) ); + } + } + } + } + + // export only single shape or shape collection + else + { + // build list of SdrObject + if( mxShapes.is() ) + { + Reference< XShape > xShape; + const sal_Int32 nCount = mxShapes->getCount(); + + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + mxShapes->getByIndex( nIndex ) >>= xShape; + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape); + if( pObj ) + aShapes.push_back( pObj ); + } + } + else + { + // only one shape + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(mxShape); + if( pObj ) + aShapes.push_back( pObj ); + } + + if( aShapes.empty() ) + bRet = false; + } + + if( bRet && !aShapes.empty() ) + { + // special treatment for only one SdrGrafObj that has text + bool bSingleGraphic = false; + + if( 1 == aShapes.size() ) + { + if( !bVectorType ) + { + if( auto pGrafObj = dynamic_cast<const SdrGrafObj*>(aShapes.front()) ) + if (pGrafObj->HasText() ) + { + aGraphic = pGrafObj->GetTransformedGraphic(); + if ( aGraphic.GetType() == GraphicType::Bitmap ) + { + Size aSizePixel( aGraphic.GetSizePixel() ); + if( rSettings.mnWidth && rSettings.mnHeight && + ( ( rSettings.mnWidth != aSizePixel.Width() ) || + ( rSettings.mnHeight != aSizePixel.Height() ) ) ) + { + BitmapEx aBmpEx( aGraphic.GetBitmapEx() ); + // export: use highest quality + aBmpEx.Scale( Size( rSettings.mnWidth, rSettings.mnHeight ), BmpScaleFlag::Lanczos ); + aGraphic = aBmpEx; + } + + // #118804# only accept for bitmap graphics, else the + // conversion to bitmap will happen anywhere without size control + // as evtl. defined in rSettings.mnWidth/mnHeight + bSingleGraphic = true; + } + } + } + else if( rSettings.mbScrollText ) + { + SdrObject* pObj = aShapes.front(); + auto pTextObj = dynamic_cast<SdrTextObj*>( pObj); + if( pTextObj && pTextObj->HasText() ) + { + tools::Rectangle aScrollRectangle; + tools::Rectangle aPaintRectangle; + + const std::unique_ptr< GDIMetaFile > pMtf( + pTextObj->GetTextScrollMetaFileAndRectangle( + aScrollRectangle, aPaintRectangle ) ); + + // take the larger one of the two rectangles (that + // should be the bound rect of the retrieved + // metafile) + tools::Rectangle aTextRect; + + if( aScrollRectangle.Contains( aPaintRectangle ) ) + aTextRect = aScrollRectangle; + else + aTextRect = aPaintRectangle; + + // setup pref size and mapmode + pMtf->SetPrefSize( aTextRect.GetSize() ); + + // set actual origin (mtf is at actual shape + // output position) + MapMode aLocalMapMode( aMap ); + aLocalMapMode.SetOrigin( + Point( -aPaintRectangle.Left(), + -aPaintRectangle.Top() ) ); + pMtf->SetPrefMapMode( aLocalMapMode ); + + pMtf->AddAction( new MetaCommentAction( + "XTEXT_SCROLLRECT", 0, + reinterpret_cast<sal_uInt8 const*>(&aScrollRectangle), + sizeof( tools::Rectangle ) ) ); + pMtf->AddAction( new MetaCommentAction( + "XTEXT_PAINTRECT", 0, + reinterpret_cast<sal_uInt8 const*>(&aPaintRectangle), + sizeof( tools::Rectangle ) ) ); + + aGraphic = Graphic( *pMtf ); + + bSingleGraphic = true; + } + } + } + + if( !bSingleGraphic ) + { + // create a metafile for all shapes + ScopedVclPtrInstance< VirtualDevice > aOut; + + // calculate bound rect for all shapes + // tdf#126319 I did not convert all rendering to primities, + // that would be to much for this fix. But I did so for the + // range calculation to get a valid high quality range. + // Based on that the conversion is reliable. With the BoundRect + // fetched from the Metafile it was just not possible to get the + // examples from the task handled in a way to fit all cases - + // due to bad-quality range data from it. + basegfx::B2DRange aBound; + const drawinglayer::geometry::ViewInformation2D aViewInformation2D; + + { + for( SdrObject* pObj : aShapes ) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence; + pObj->GetViewContact().getViewIndependentPrimitive2DContainer(aSequence); + aBound.expand(aSequence.getB2DRange(aViewInformation2D)); + } + } + + aOut->EnableOutput( false ); + aOut->SetMapMode( aMap ); + if( rSettings.mbUseHighContrast ) + aOut->SetDrawMode( aOut->GetDrawMode() | DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient ); + + GDIMetaFile aMtf; + aMtf.Clear(); + aMtf.Record( aOut ); + + MapMode aOutMap( aMap ); + const Size aOnePixelInMtf( + Application::GetDefaultDevice()->PixelToLogic( + Size(1, 1), + aMap)); + const Size aHalfPixelInMtf( + (aOnePixelInMtf.getWidth() + 1) / 2, + (aOnePixelInMtf.getHeight() + 1) / 2); + + // tdf#126319 Immediately add needed offset to create metafile, + // that avoids to do it later by Metafile::Move what would be expensive + aOutMap.SetOrigin( + Point( + basegfx::fround(-aBound.getMinX() - aHalfPixelInMtf.getWidth()), + basegfx::fround(-aBound.getMinY() - aHalfPixelInMtf.getHeight()) ) ); + aOut->SetRelativeMapMode( aOutMap ); + + sdr::contact::DisplayInfo aDisplayInfo; + + if(mpCurrentPage) + { + if(mpCurrentPage->TRG_HasMasterPage() && pPage->IsMasterPage()) + { + // MasterPage is processed as another page's SubContent + aDisplayInfo.SetProcessLayers(mpCurrentPage->TRG_GetMasterPageVisibleLayers()); + aDisplayInfo.SetSubContentActive(true); + } + } + + if(!aShapes.empty()) + { + // more effective way to paint a vector of SdrObjects. Hand over the processed page + // to have it in the + ImplExportCheckVisisbilityRedirector aCheckVisibilityRedirector(mpCurrentPage); + sdr::contact::ObjectContactOfObjListPainter aMultiObjectPainter(*aOut, std::move(aShapes), mpCurrentPage); + aMultiObjectPainter.SetViewObjectContactRedirector(&aCheckVisibilityRedirector); + + aMultiObjectPainter.ProcessDisplay(aDisplayInfo); + } + + aMtf.Stop(); + aMtf.WindStart(); + + // tdf#126319 Immediately add needed size to target's PrefSize + const Size aBoundSize( + basegfx::fround(aBound.getWidth() + aHalfPixelInMtf.getWidth()), + basegfx::fround(aBound.getHeight() + aHalfPixelInMtf.getHeight())); + + aMtf.SetPrefMapMode( aMap ); + aMtf.SetPrefSize( aBoundSize ); + + if( !bVectorType ) + { + Size aOutSize; + aGraphic = GetBitmapFromMetaFile( aMtf, CalcSize( rSettings.mnWidth, rSettings.mnHeight, aBoundSize, aOutSize ) ); + } + else + { + aGraphic = aMtf; + } + } + } + + if(pTempBackgroundShape) + { + SdrObject::Free(pTempBackgroundShape); + } + + rOutl.SetCalcFieldValueHdl( maOldCalcFieldValueHdl ); + + // #i102251# + rOutl.SetControlWord(nOldCntrl); + + return bRet; + +} + +// XFilter +sal_Bool SAL_CALL GraphicExporter::filter( const Sequence< PropertyValue >& aDescriptor ) +{ + ::SolarMutexGuard aGuard; + + if( maGraphic.IsNone() && nullptr == mpUnoPage ) + return false; + + if( maGraphic.IsNone() && ( nullptr == mpUnoPage->GetSdrPage() || nullptr == mpDoc ) ) + return false; + + GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter(); + + // get the arguments from the descriptor + ExportSettings aSettings(mpDoc); + ParseSettings(aDescriptor, aSettings); + + const sal_uInt16 nFilter = !aSettings.maMediaType.isEmpty() + ? rFilter.GetExportFormatNumberForMediaType( aSettings.maMediaType ) + : rFilter.GetExportFormatNumberForShortName( aSettings.maFilterName ); + bool bVectorType = !rFilter.IsExportPixelFormat( nFilter ); + + // create the output stuff + Graphic aGraphic = maGraphic; + + ErrCode nStatus = ERRCODE_NONE; + if (maGraphic.IsNone()) + { + bool bAntiAliasing = SvtOptionsDrawinglayer::IsAntiAliasing(); + AllSettings aAllSettings = Application::GetSettings(); + StyleSettings aStyleSettings = aAllSettings.GetStyleSettings(); + bool bUseFontAAFromSystem = aStyleSettings.GetUseFontAAFromSystem(); + if (aSettings.meAntiAliasing != TRISTATE_INDET) + { + // This is safe to do globally as we own the solar mutex. + SvtOptionsDrawinglayer::SetAntiAliasing(aSettings.meAntiAliasing == TRISTATE_TRUE, /*bTemporary*/true); + // Opt in to have AA affect font rendering as well. + aStyleSettings.SetUseFontAAFromSystem(false); + aAllSettings.SetStyleSettings(aStyleSettings); + Application::SetSettings(aAllSettings); + } + nStatus = GetGraphic( aSettings, aGraphic, bVectorType ) ? ERRCODE_NONE : ERRCODE_GRFILTER_FILTERERROR; + if (aSettings.meAntiAliasing != TRISTATE_INDET) + { + SvtOptionsDrawinglayer::SetAntiAliasing(bAntiAliasing, /*bTemporary*/true); + aStyleSettings.SetUseFontAAFromSystem(bUseFontAAFromSystem); + aAllSettings.SetStyleSettings(aStyleSettings); + Application::SetSettings(aAllSettings); + } + } + + if( nStatus == ERRCODE_NONE ) + { + // export graphic only if it has a size + const Size aGraphSize( aGraphic.GetPrefSize() ); + if ( aGraphSize.IsEmpty() ) + { + nStatus = ERRCODE_GRFILTER_FILTERERROR; + } + else + { + // now we have a graphic, so export it + if( aSettings.mxGraphicRenderer.is() ) + { + // render graphic directly into given renderer + aSettings.mxGraphicRenderer->render( aGraphic.GetXGraphic() ); + } + else if( aSettings.mxOutputStream.is() ) + { + // TODO: Either utilize optional XSeekable functionality for the + // SvOutputStream, or adapt the graphic filter to not seek anymore. + SvMemoryStream aStream( 1024, 1024 ); + + nStatus = rFilter.ExportGraphic( aGraphic, u"", aStream, nFilter, &aSettings.maFilterData ); + + // copy temp stream to XOutputStream + SvOutputStream aOutputStream( aSettings.mxOutputStream ); + aStream.Seek(0); + aOutputStream.WriteStream( aStream ); + } + else + { + INetURLObject aURLObject( aSettings.maURL.Complete ); + DBG_ASSERT( aURLObject.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + nStatus = XOutBitmap::ExportGraphic( aGraphic, aURLObject, rFilter, nFilter, &aSettings.maFilterData ); + } + } + } + + if ( aSettings.mxInteractionHandler.is() && ( nStatus != ERRCODE_NONE ) ) + { + Any aInteraction; + Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations{ + new ::comphelper::OInteractionApprove() + }; + + GraphicFilterRequest aErrorCode; + aErrorCode.ErrCode = sal_uInt32(nStatus); + aInteraction <<= aErrorCode; + aSettings.mxInteractionHandler->handle( framework::InteractionRequest::CreateRequest( aInteraction, lContinuations ) ); + } + return nStatus == ERRCODE_NONE; +} + +void SAL_CALL GraphicExporter::cancel() +{ +} + +// XExporter + +/** the source 'document' could be a XDrawPage, a XShape or a generic XShapes */ +void SAL_CALL GraphicExporter::setSourceDocument( const Reference< lang::XComponent >& xComponent ) +{ + ::SolarMutexGuard aGuard; + + mxShapes = nullptr; + mpUnoPage = nullptr; + + try + { + // any break inside this one loop while will throw an IllegalArgumentException + do + { + mxPage.set( xComponent, UNO_QUERY ); + mxShapes.set( xComponent, UNO_QUERY ); + mxShape.set( xComponent, UNO_QUERY ); + + // Step 1: try a generic XShapes + if( !mxPage.is() && !mxShape.is() && mxShapes.is() ) + { + // we do not support empty shape collections + if( 0 == mxShapes->getCount() ) + break; + + // get first shape to detect corresponding page and model + mxShapes->getByIndex(0) >>= mxShape; + } + else + { + mxShapes = nullptr; + } + + // Step 2: try a shape + if( mxShape.is() ) + { + if (nullptr == SdrObject::getSdrObjectFromXShape(mxShape)) + { + // This is not a Draw shape, let's see if it's a Writer one. + uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); + if (!xPropertySet.is()) + break; + uno::Reference<graphic::XGraphic> xGraphic( + xPropertySet->getPropertyValue("Graphic"), uno::UNO_QUERY); + if (!xGraphic.is()) + break; + + maGraphic = Graphic(xGraphic); + if (!maGraphic.IsNone()) + return; + else + break; + } + + // get page for this shape + Reference< XChild > xChild( mxShape, UNO_QUERY ); + if( !xChild.is() ) + break; + + Reference< XInterface > xInt; + do + { + xInt = xChild->getParent(); + mxPage.set( xInt, UNO_QUERY ); + if( !mxPage.is() ) + xChild.set( xInt, UNO_QUERY ); + } + while( !mxPage.is() && xChild.is() ); + + if( !mxPage.is() ) + break; + } + + // Step 3: check the page + if( !mxPage.is() ) + break; + + mpUnoPage = comphelper::getFromUnoTunnel<SvxDrawPage>( mxPage ); + + if( nullptr == mpUnoPage || nullptr == mpUnoPage->GetSdrPage() ) + break; + + mpDoc = &mpUnoPage->GetSdrPage()->getSdrModelFromSdrPage(); + + // Step 4: If we got a generic XShapes test all contained shapes + // if they belong to the same XDrawPage + + if( mxShapes.is() ) + { + SdrPage* pPage = mpUnoPage->GetSdrPage(); + SdrObject* pObj; + Reference< XShape > xShape; + + bool bOk = true; + + const sal_Int32 nCount = mxShapes->getCount(); + + // test all but the first shape if they have the same page than + // the first shape + for( sal_Int32 nIndex = 1; bOk && ( nIndex < nCount ); nIndex++ ) + { + mxShapes->getByIndex( nIndex ) >>= xShape; + pObj = SdrObject::getSdrObjectFromXShape(xShape); + bOk = pObj && pObj->getSdrPageFromSdrObject() == pPage; + } + + if( !bOk ) + break; + } + + // no errors so far + return; + } + while( false ); + } + catch( Exception& ) + { + } + + throw IllegalArgumentException(); +} + +// XServiceInfo +OUString SAL_CALL GraphicExporter::getImplementationName( ) +{ + return "com.sun.star.comp.Draw.GraphicExporter"; +} + +sal_Bool SAL_CALL GraphicExporter::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +Sequence< OUString > SAL_CALL GraphicExporter::getSupportedServiceNames( ) +{ + Sequence< OUString > aSupportedServiceNames { "com.sun.star.drawing.GraphicExportFilter" }; + return aSupportedServiceNames; +} + +// XMimeTypeInfo +sal_Bool SAL_CALL GraphicExporter::supportsMimeType( const OUString& rMimeTypeName ) +{ + GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter(); + sal_uInt16 nCount = rFilter.GetExportFormatCount(); + sal_uInt16 nFilter; + for( nFilter = 0; nFilter < nCount; nFilter++ ) + { + if( rMimeTypeName == rFilter.GetExportFormatMediaType( nFilter ) ) + { + return true; + } + } + + return false; +} + +Sequence< OUString > SAL_CALL GraphicExporter::getSupportedMimeTypeNames( ) +{ + GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter(); + sal_uInt16 nCount = rFilter.GetExportFormatCount(); + sal_uInt16 nFilter; + sal_uInt16 nFound = 0; + + Sequence< OUString > aSeq( nCount ); + OUString* pStr = aSeq.getArray(); + + for( nFilter = 0; nFilter < nCount; nFilter++ ) + { + OUString aMimeType( rFilter.GetExportFormatMediaType( nFilter ) ); + if( !aMimeType.isEmpty() ) + { + *pStr++ = aMimeType; + nFound++; + } + } + + if( nFound < nCount ) + aSeq.realloc( nFound ); + + return aSeq; +} + +} + +Graphic SvxGetGraphicForShape( SdrObject& rShape ) +{ + Graphic aGraphic; + try + { + rtl::Reference< GraphicExporter > xExporter( new GraphicExporter() ); + Reference< XComponent > xComp( rShape.getUnoShape(), UNO_QUERY_THROW ); + xExporter->setSourceDocument( xComp ); + ExportSettings aSettings(&rShape.getSdrModelFromSdrObject()); + xExporter->GetGraphic( aSettings, aGraphic, true/*bVector*/ ); + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("svx", ""); + } + return aGraphic; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_Draw_GraphicExporter_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new GraphicExporter); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/UnoGraphicExporter.hxx b/svx/source/unodraw/UnoGraphicExporter.hxx new file mode 100644 index 000000000..ace0db252 --- /dev/null +++ b/svx/source/unodraw/UnoGraphicExporter.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVX_SOURCE_UNODRAW_UNOGRAPHICEXPORTER_HXX +#define INCLUDED_SVX_SOURCE_UNODRAW_UNOGRAPHICEXPORTER_HXX + +#include <sal/config.h> + +#include <vcl/graph.hxx> + +class SdrObject; + +Graphic SvxGetGraphicForShape(SdrObject& rShape); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/UnoNameItemTable.cxx b/svx/source/unodraw/UnoNameItemTable.cxx new file mode 100644 index 000000000..67b1dcc7d --- /dev/null +++ b/svx/source/unodraw/UnoNameItemTable.cxx @@ -0,0 +1,282 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <set> + +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <comphelper/profilezone.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <svx/svdmodel.hxx> +#include "UnoNameItemTable.hxx" +#include <vcl/svapp.hxx> + +#include <svx/unoapi.hxx> +#include <memory> + +using namespace ::com::sun::star; +using namespace ::cppu; + +namespace +{ + // We need to override operator== here and specifically bypass the assert + // in SfxPoolItem::operator== in order to make the FindItemSurrogate call + // in SvxUnoNameItemTable::hasByName safe. + class SampleItem : public NameOrIndex + { + public: + SampleItem(sal_uInt16 nWhich, const OUString& rName) : NameOrIndex(TypedWhichId<NameOrIndex>(nWhich), rName) {} + + bool operator==(const SfxPoolItem& rCmp) const + { + assert(dynamic_cast<const NameOrIndex*>(&rCmp) && "comparing different pool item subclasses"); + auto const & rOther = static_cast<const NameOrIndex&>(rCmp); + return GetName() == rOther.GetName() && GetPalIndex() == rOther.GetPalIndex(); + } + }; + +} + + +SvxUnoNameItemTable::SvxUnoNameItemTable( SdrModel* pModel, sal_uInt16 nWhich, sal_uInt8 nMemberId ) noexcept +: mpModel( pModel ), + mpModelPool( pModel ? &pModel->GetItemPool() : nullptr ), + mnWhich( nWhich ), mnMemberId( nMemberId ) +{ + if( pModel ) + StartListening( *pModel ); +} + +SvxUnoNameItemTable::~SvxUnoNameItemTable() noexcept +{ + SolarMutexGuard aGuard; + + if( mpModel ) + EndListening( *mpModel ); + dispose(); +} + +bool SvxUnoNameItemTable::isValid( const NameOrIndex* pItem ) const +{ + return pItem && !pItem->GetName().isEmpty(); +} + +void SvxUnoNameItemTable::dispose() +{ + maItemSetVector.clear(); +} + +void SvxUnoNameItemTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept +{ + if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) + return; + const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); + if( SdrHintKind::ModelCleared == pSdrHint->GetKind() ) + dispose(); +} + +sal_Bool SAL_CALL SvxUnoNameItemTable::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +void SvxUnoNameItemTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement ) +{ + maItemSetVector.push_back( std::make_unique< SfxItemSet >( *mpModelPool, mnWhich, mnWhich ) ); + + std::unique_ptr<NameOrIndex> xNewItem(createItem()); + xNewItem->SetName(aName); + xNewItem->PutValue(aElement, mnMemberId); + xNewItem->SetWhich(mnWhich); + maItemSetVector.back()->Put(std::move(xNewItem)); +} + +// XNameContainer +void SAL_CALL SvxUnoNameItemTable::insertByName( const OUString& aApiName, const uno::Any& aElement ) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SvxUnoNameItemTable::insertByName"); + + if( hasByName( aApiName ) ) + throw container::ElementExistException(); + + OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); + + ImplInsertByName( aName, aElement ); +} + +void SAL_CALL SvxUnoNameItemTable::cancel() +{ + SolarMutexGuard aGuard; + // drop all items that are owned by this service and not the document + // (i.e. they are unused) + dispose(); +} + +void SAL_CALL SvxUnoNameItemTable::removeByName( const OUString& aApiName ) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SvxUnoNameItemTable::removeByName"); + + OUString sName = SvxUnogetInternalNameForItem(mnWhich, aApiName); + + auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(), + [&](const std::unique_ptr<SfxItemSet>& rpItem) { + const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&(rpItem->Get( mnWhich ) )); + return sName == pItem->GetName(); + }); + if (aIter != maItemSetVector.end()) + { + maItemSetVector.erase( aIter ); + return; + } + + if (!hasByName(sName)) + throw container::NoSuchElementException(); +} + +// XNameReplace +void SAL_CALL SvxUnoNameItemTable::replaceByName( const OUString& aApiName, const uno::Any& aElement ) +{ + SolarMutexGuard aGuard; + + OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); + + auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(), + [&](const std::unique_ptr<SfxItemSet>& rpItem) { + const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&(rpItem->Get( mnWhich ) )); + return aName == pItem->GetName(); + }); + if (aIter != maItemSetVector.end()) + { + std::unique_ptr<NameOrIndex> xNewItem(createItem()); + xNewItem->SetName(aName); + if (!xNewItem->PutValue(aElement, mnMemberId) || !isValid(xNewItem.get())) + throw lang::IllegalArgumentException(); + (*aIter)->Put(std::move(xNewItem)); + return; + } + + // if it is not in our own sets, modify the pool! + bool bFound = false; + + if (mpModelPool) + { + SampleItem aSample(mnWhich, aName); + for (const SfxPoolItem* pNameOrIndex : mpModelPool->FindItemSurrogate(mnWhich, aSample)) + if (isValid(static_cast<const NameOrIndex*>(pNameOrIndex))) + { + const_cast<SfxPoolItem*>(pNameOrIndex)->PutValue( aElement, mnMemberId ); + bFound = true; + } + } + + if( !bFound ) + throw container::NoSuchElementException(); + + ImplInsertByName( aName, aElement ); + + if( !hasByName( aName ) ) + throw container::NoSuchElementException(); +} + +// XNameAccess +uno::Any SAL_CALL SvxUnoNameItemTable::getByName( const OUString& aApiName ) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SvxUnoNameItemTable::getByName"); + + OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); + + if (mpModelPool && !aName.isEmpty()) + { + SampleItem aSample(mnWhich, aName); + for (const SfxPoolItem* pFindItem : mpModelPool->FindItemSurrogate(mnWhich, aSample)) + if (isValid(static_cast<const NameOrIndex*>(pFindItem))) + { + uno::Any aAny; + pFindItem->QueryValue( aAny, mnMemberId ); + return aAny; + } + } + + throw container::NoSuchElementException(); +} + +uno::Sequence< OUString > SAL_CALL SvxUnoNameItemTable::getElementNames( ) +{ + SolarMutexGuard aGuard; + + std::set< OUString > aNameSet; + + + if (mpModelPool) + for (const SfxPoolItem* pItem : mpModelPool->GetItemSurrogates(mnWhich)) + { + const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem); + + if( !isValid( pNameOrIndex ) ) + continue; + + OUString aApiName = SvxUnogetApiNameForItem(mnWhich, pNameOrIndex->GetName()); + aNameSet.insert(aApiName); + } + + return comphelper::containerToSequence(aNameSet); +} + +sal_Bool SAL_CALL SvxUnoNameItemTable::hasByName( const OUString& aApiName ) +{ + SolarMutexGuard aGuard; + + OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); + + if (aName.isEmpty()) + return false; + + if (!mpModelPool) + return false; + + SampleItem aSample(mnWhich, aName); + for (const SfxPoolItem* pFindItem : mpModelPool->FindItemSurrogate(mnWhich, aSample)) + if (isValid(static_cast<const NameOrIndex*>(pFindItem))) + return true; + return false; +} + +sal_Bool SAL_CALL SvxUnoNameItemTable::hasElements( ) +{ + SolarMutexGuard aGuard; + + if (mpModelPool) + for (const SfxPoolItem* pItem : mpModelPool->GetItemSurrogates(mnWhich)) + { + const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem); + + if( isValid( pNameOrIndex ) ) + return true; + } + + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/UnoNameItemTable.hxx b/svx/source/unodraw/UnoNameItemTable.hxx new file mode 100644 index 000000000..c1c798869 --- /dev/null +++ b/svx/source/unodraw/UnoNameItemTable.hxx @@ -0,0 +1,94 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVX_SOURCE_UNODRAW_UNONAMEITEMTABLE_HXX +#define INCLUDED_SVX_SOURCE_UNODRAW_UNONAMEITEMTABLE_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <cppuhelper/implbase.hxx> + +#include <memory> +#include <vector> +#include <svl/lstner.hxx> +#include <svx/xit.hxx> + +class SdrModel; +class SfxItemPool; +class SfxItemSet; + +typedef std::vector< std::unique_ptr< SfxItemSet > > ItemPoolVector; +class SvxUnoNameItemTable + : public cppu::WeakImplHelper< + css::util::XCancellable, + css::container::XNameContainer, + css::lang::XServiceInfo > + , public SfxListener +{ +private: + SdrModel* mpModel; + SfxItemPool* mpModelPool; + sal_uInt16 mnWhich; + sal_uInt8 mnMemberId; + + /// vector contains all items that were created by this service and will + /// keep them alive even if nothing in the document references them + ItemPoolVector maItemSetVector; + + void ImplInsertByName( const OUString& aName, const css::uno::Any& aElement ); + +public: + SvxUnoNameItemTable( SdrModel* pModel, sal_uInt16 nWhich, sal_uInt8 nMemberId ) noexcept; + virtual ~SvxUnoNameItemTable() noexcept override; + + virtual NameOrIndex* createItem() const = 0; + virtual bool isValid( const NameOrIndex* pItem ) const; + + void dispose(); + + // SfxListener + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override; + + // XServiceInfo + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + // XCancellable + virtual void SAL_CALL cancel() override; + + // XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override; + virtual void SAL_CALL removeByName( const OUString& Name ) override; + + // XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const css::uno::Any& aElement ) override; + + // XNameAccess + virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override; + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; + + // XElementAccess + virtual sal_Bool SAL_CALL hasElements( ) override; +}; + +#endif // INCLUDED_SVX_SOURCE_UNODRAW_UNONAMEITEMTABLE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/UnoNamespaceMap.cxx b/svx/source/unodraw/UnoNamespaceMap.cxx new file mode 100644 index 000000000..cd49cc0a6 --- /dev/null +++ b/svx/source/unodraw/UnoNamespaceMap.cxx @@ -0,0 +1,275 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <climits> +#include <set> + +#include <svx/UnoNamespaceMap.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <svl/itempool.hxx> +#include <editeng/xmlcnitm.hxx> + +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +namespace svx +{ + namespace { + + /** implements a component to export namespaces of all SvXMLAttrContainerItem inside + one or two pools with a variable count of which ids. + */ + class NamespaceMap : public WeakImplHelper< XNameAccess, XServiceInfo > + { + private: + sal_uInt16* mpWhichIds; + SfxItemPool* mpPool; + + public: + NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool ); + + // XNameAccess + virtual Any SAL_CALL getByName( const OUString& aName ) override; + virtual Sequence< OUString > SAL_CALL getElementNames( ) override; + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; + + // XElementAccess + virtual Type SAL_CALL getElementType( ) override; + virtual sal_Bool SAL_CALL hasElements( ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + }; + + } + + Reference< XInterface > NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool ) + { + return static_cast<XWeak*>(new NamespaceMap( pWhichIds, pPool )); + } + + static Sequence< OUString > NamespaceMap_getSupportedServiceNames() + noexcept + { + Sequence<OUString> aSupportedServiceNames { "com.sun.star.xml.NamespaceMap" }; + return aSupportedServiceNames; + } + + static OUString NamespaceMap_getImplementationName() + noexcept + { + return "com.sun.star.comp.Svx.NamespaceMap"; + } + + namespace { + + class NamespaceIteratorImpl + { + private: + SfxItemPool* mpPool; + + sal_uInt16* mpWhichId; + + std::vector<const SvXMLAttrContainerItem*> mvItems; + sal_Int32 mnItem; + + const SvXMLAttrContainerItem* mpCurrentAttr; + sal_uInt16 mnCurrentAttr; + + public: + + NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool ); + + bool next( OUString& rPrefix, OUString& rURL ); + }; + + } +} + +using namespace ::svx; + + +NamespaceIteratorImpl::NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool ) +{ + mpPool = pPool; + mpCurrentAttr = nullptr; + mnCurrentAttr = 0; + + mpWhichId = pWhichIds; + + mnItem = -1; + if (mpWhichId && (0 != *mpWhichId) && mpPool) + { + mvItems.reserve(mpPool->GetItemCount2( *mpWhichId )); + for (const SfxPoolItem* pItem : mpPool->GetItemSurrogates( *mpWhichId )) + mvItems.push_back(static_cast<const SvXMLAttrContainerItem*>(pItem)); + } +} + +bool NamespaceIteratorImpl::next( OUString& rPrefix, OUString& rURL ) +{ + // we still need to process the current attribute + if( mpCurrentAttr && (mnCurrentAttr != USHRT_MAX) ) + { + rPrefix = mpCurrentAttr->GetPrefix( mnCurrentAttr ); + rURL = mpCurrentAttr->GetNamespace( mnCurrentAttr ); + + mnCurrentAttr = mpCurrentAttr->GetNextNamespaceIndex( mnCurrentAttr ); + return true; + } + + // we need the next namespace item + mpCurrentAttr = nullptr; + mnItem++; + + // are we finished with the current whichid? + if( mnItem == static_cast<sal_Int32>(mvItems.size()) ) + { + mpWhichId++; + + // are we finished with the current pool? + if( 0 == *mpWhichId ) + return false; + + mnItem = -1; + mvItems.clear(); + if (mpPool) + { + mvItems.reserve(mpPool->GetItemCount2( *mpWhichId )); + for (const SfxPoolItem* pItem2 : mpPool->GetItemSurrogates( *mpWhichId )) + mvItems.push_back(static_cast<const SvXMLAttrContainerItem*>(pItem2)); + } + return next( rPrefix, rURL ); + } + + auto pItem = mvItems[mnItem]; + // get that item and see if there namespaces inside + if( pItem->GetAttrCount() > 0 ) + { + mpCurrentAttr = pItem; + mnCurrentAttr = pItem->GetFirstNamespaceIndex(); + } + return next( rPrefix, rURL ); +} + + +NamespaceMap::NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool ) +: mpWhichIds( pWhichIds ), mpPool( pPool ) +{ +} + +// XNameAccess +Any SAL_CALL NamespaceMap::getByName( const OUString& aName ) +{ + NamespaceIteratorImpl aIter( mpWhichIds, mpPool ); + + OUString aPrefix; + OUString aURL; + + bool bFound; + + do + { + bFound = aIter.next( aPrefix, aURL ); + } + while( bFound && (aPrefix != aName ) ); + + if( !bFound ) + throw NoSuchElementException(); + + return Any( aURL ); +} + +Sequence< OUString > SAL_CALL NamespaceMap::getElementNames() +{ + NamespaceIteratorImpl aIter( mpWhichIds, mpPool ); + + OUString aPrefix; + OUString aURL; + + std::set< OUString > aPrefixSet; + + while( aIter.next( aPrefix, aURL ) ) + aPrefixSet.insert( aPrefix ); + + return comphelper::containerToSequence(aPrefixSet); +} + +sal_Bool SAL_CALL NamespaceMap::hasByName( const OUString& aName ) +{ + NamespaceIteratorImpl aIter( mpWhichIds, mpPool ); + + OUString aPrefix; + OUString aURL; + + bool bFound; + + do + { + bFound = aIter.next( aPrefix, aURL ); + } + while( bFound && (aPrefix != aName ) ); + + return bFound; +} + +// XElementAccess +Type SAL_CALL NamespaceMap::getElementType() +{ + return ::cppu::UnoType<OUString>::get(); +} + +sal_Bool SAL_CALL NamespaceMap::hasElements() +{ + NamespaceIteratorImpl aIter( mpWhichIds, mpPool ); + + OUString aPrefix; + OUString aURL; + + return aIter.next( aPrefix, aURL ); +} + +// XServiceInfo +OUString SAL_CALL NamespaceMap::getImplementationName( ) +{ + return NamespaceMap_getImplementationName(); +} + +sal_Bool SAL_CALL NamespaceMap::supportsService( const OUString& serviceName ) +{ + return cppu::supportsService( this, serviceName ); +} + +Sequence< OUString > SAL_CALL NamespaceMap::getSupportedServiceNames( ) +{ + return NamespaceMap_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/XPropertyTable.cxx b/svx/source/unodraw/XPropertyTable.cxx new file mode 100644 index 000000000..56bb13523 --- /dev/null +++ b/svx/source/unodraw/XPropertyTable.cxx @@ -0,0 +1,663 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <memory> +#include <XPropertyTable.hxx> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/drawing/Hatch.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <o3tl/any.hxx> +#include <vcl/svapp.hxx> + +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <svx/xdef.hxx> + +#include <svx/unoapi.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +using namespace com::sun::star; +using namespace ::cppu; + +namespace { + +class SvxUnoXPropertyTable : public WeakImplHelper< container::XNameContainer, lang::XServiceInfo > +{ +private: + XPropertyList& mrList; + sal_Int16 mnWhich; + + tools::Long getCount() const { return mrList.Count(); } + const XPropertyEntry* get(tools::Long index) const; +public: + SvxUnoXPropertyTable( sal_Int16 nWhich, XPropertyList& rList ) noexcept; + + /// @throws uno::RuntimeException + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const = 0; + /// @throws uno::RuntimeException + /// @throws lang::IllegalArgumentException + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const = 0; + + // XServiceInfo + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + // XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override; + virtual void SAL_CALL removeByName( const OUString& Name ) override; + + // XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override; + + // XNameAccess + virtual uno::Any SAL_CALL getByName( const OUString& aName ) override; + virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override; + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; + + // XElementAccess + virtual sal_Bool SAL_CALL hasElements( ) override; +}; + +} + +SvxUnoXPropertyTable::SvxUnoXPropertyTable( sal_Int16 nWhich, XPropertyList& rList ) noexcept +: mrList( rList ), mnWhich( nWhich ) +{ +} + +const XPropertyEntry* SvxUnoXPropertyTable::get(tools::Long index) const +{ + return mrList.Get(index); +} + +// XServiceInfo +sal_Bool SAL_CALL SvxUnoXPropertyTable::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +// XNameContainer +void SAL_CALL SvxUnoXPropertyTable::insertByName( const OUString& aName, const uno::Any& aElement ) +{ + SolarMutexGuard aGuard; + + if( hasByName( aName ) ) + throw container::ElementExistException(); + + OUString aInternalName = SvxUnogetInternalNameForItem(mnWhich, aName); + + std::unique_ptr<XPropertyEntry> pNewEntry(createEntry(aInternalName, aElement)); + if (!pNewEntry) + throw lang::IllegalArgumentException(); + + mrList.Insert(std::move(pNewEntry)); +} + +void SAL_CALL SvxUnoXPropertyTable::removeByName( const OUString& Name ) +{ + SolarMutexGuard aGuard; + + OUString aInternalName = SvxUnogetInternalNameForItem(mnWhich, Name); + + const tools::Long nCount = getCount(); + tools::Long i; + for( i = 0; i < nCount; i++ ) + { + const XPropertyEntry* pEntry = get(i); + if (pEntry && aInternalName == pEntry->GetName()) + { + mrList.Remove(i); + return; + } + } + + throw container::NoSuchElementException(); +} + +// XNameReplace +void SAL_CALL SvxUnoXPropertyTable::replaceByName( const OUString& aName, const uno::Any& aElement ) +{ + SolarMutexGuard aGuard; + + OUString aInternalName = SvxUnogetInternalNameForItem(mnWhich, aName); + + const tools::Long nCount = getCount(); + tools::Long i; + for( i = 0; i < nCount; i++ ) + { + const XPropertyEntry* pEntry = get(i); + if (pEntry && aInternalName == pEntry->GetName()) + { + std::unique_ptr<XPropertyEntry> pNewEntry(createEntry(aInternalName, aElement)); + if (!pNewEntry) + throw lang::IllegalArgumentException(); + + mrList.Replace(std::move(pNewEntry), i); + return; + } + } + + throw container::NoSuchElementException(); +} + +// XNameAccess +uno::Any SAL_CALL SvxUnoXPropertyTable::getByName( const OUString& aName ) +{ + SolarMutexGuard aGuard; + + OUString aInternalName = SvxUnogetInternalNameForItem(mnWhich, aName); + + const tools::Long nCount = getCount(); + tools::Long i; + for( i = 0; i < nCount; i++ ) + { + const XPropertyEntry* pEntry = get(i); + + if (pEntry && aInternalName == pEntry->GetName()) + return getAny( pEntry ); + } + + throw container::NoSuchElementException(); +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXPropertyTable::getElementNames() +{ + SolarMutexGuard aGuard; + + const tools::Long nCount = getCount(); + uno::Sequence< OUString > aNames( nCount ); + OUString* pNames = aNames.getArray(); + tools::Long i; + for( i = 0; i < nCount; i++ ) + { + const XPropertyEntry* pEntry = get(i); + + if (pEntry) + *pNames++ = SvxUnogetApiNameForItem(mnWhich, pEntry->GetName()); + } + + return aNames; +} + +sal_Bool SAL_CALL SvxUnoXPropertyTable::hasByName( const OUString& aName ) +{ + SolarMutexGuard aGuard; + + OUString aInternalName = SvxUnogetInternalNameForItem(mnWhich, aName); + + const tools::Long nCount = mrList.Count(); + tools::Long i; + for( i = 0; i < nCount; i++ ) + { + const XPropertyEntry* pEntry = get(i); + if (pEntry && aInternalName == pEntry->GetName()) + return true; + } + + return false; +} + +// XElementAccess +sal_Bool SAL_CALL SvxUnoXPropertyTable::hasElements( ) +{ + SolarMutexGuard aGuard; + + return getCount() != 0; +} + +namespace { + +class SvxUnoXColorTable : public SvxUnoXPropertyTable +{ +public: + explicit SvxUnoXColorTable( XPropertyList& rList ) noexcept : SvxUnoXPropertyTable( XATTR_LINECOLOR, rList ) {}; + + // SvxUnoXPropertyTable + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const noexcept override; + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +} + +uno::Reference< container::XNameContainer > SvxUnoXColorTable_createInstance( XPropertyList& rList ) noexcept +{ + return new SvxUnoXColorTable( rList ); +} + +// SvxUnoXPropertyTable +uno::Any SvxUnoXColorTable::getAny( const XPropertyEntry* pEntry ) const noexcept +{ + return uno::Any( static_cast<sal_Int32>(static_cast<const XColorEntry*>(pEntry)->GetColor()) ); +} + +std::unique_ptr<XPropertyEntry> SvxUnoXColorTable::createEntry(const OUString& rName, const uno::Any& rAny) const +{ + Color aColor; + if( !(rAny >>= aColor) ) + return std::unique_ptr<XPropertyEntry>(); + + return std::make_unique<XColorEntry>(aColor, rName); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoXColorTable::getElementType() +{ + return ::cppu::UnoType<sal_Int32>::get(); +} + +// XServiceInfo +OUString SAL_CALL SvxUnoXColorTable::getImplementationName( ) +{ + return "SvxUnoXColorTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXColorTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.ColorTable" }; +} + +namespace { + +class SvxUnoXLineEndTable : public SvxUnoXPropertyTable +{ +public: + explicit SvxUnoXLineEndTable( XPropertyList& rTable ) noexcept : SvxUnoXPropertyTable( XATTR_LINEEND, rTable ) {}; + + // SvxUnoXPropertyTable + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const noexcept override; + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +} + +uno::Reference< container::XNameContainer > SvxUnoXLineEndTable_createInstance( XPropertyList& rTable ) noexcept +{ + return new SvxUnoXLineEndTable( rTable ); +} + +// SvxUnoXPropertyTable +uno::Any SvxUnoXLineEndTable::getAny( const XPropertyEntry* pEntry ) const noexcept +{ + drawing::PolyPolygonBezierCoords aBezier; + basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd(), + aBezier ); + return uno::Any(aBezier); +} + +std::unique_ptr<XPropertyEntry> SvxUnoXLineEndTable::createEntry(const OUString& rName, const uno::Any& rAny) const +{ + auto pCoords = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(rAny); + if( !pCoords ) + return std::unique_ptr<XLineEndEntry>(); + + basegfx::B2DPolyPolygon aPolyPolygon; + if( pCoords->Coordinates.getLength() > 0 ) + aPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords ); + + // #86265# make sure polygon is closed + aPolyPolygon.setClosed(true); + + return std::make_unique<XLineEndEntry>(aPolyPolygon, rName); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoXLineEndTable::getElementType() +{ + return cppu::UnoType<drawing::PolyPolygonBezierCoords>::get(); +} + +// XServiceInfo +OUString SAL_CALL SvxUnoXLineEndTable::getImplementationName( ) +{ + return "SvxUnoXLineEndTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXLineEndTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.LineEndTable" }; +} + +namespace { + +class SvxUnoXDashTable : public SvxUnoXPropertyTable +{ +public: + explicit SvxUnoXDashTable( XPropertyList& rTable ) noexcept : SvxUnoXPropertyTable( XATTR_LINEDASH, rTable ) {}; + + // SvxUnoXPropertyTable + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const noexcept override; + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +} + +uno::Reference< container::XNameContainer > SvxUnoXDashTable_createInstance( XPropertyList& rTable ) noexcept +{ + return new SvxUnoXDashTable( rTable ); +} + +// SvxUnoXPropertyTable +uno::Any SvxUnoXDashTable::getAny( const XPropertyEntry* pEntry ) const noexcept +{ + const XDash& rXD = static_cast<const XDashEntry*>(pEntry)->GetDash(); + + drawing::LineDash aLineDash; + + aLineDash.Style = static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(rXD.GetDashStyle())); + aLineDash.Dots = rXD.GetDots(); + aLineDash.DotLen = rXD.GetDotLen(); + aLineDash.Dashes = rXD.GetDashes(); + aLineDash.DashLen = rXD.GetDashLen(); + aLineDash.Distance = rXD.GetDistance(); + + return uno::Any(aLineDash); +} + +std::unique_ptr<XPropertyEntry> SvxUnoXDashTable::createEntry(const OUString& rName, const uno::Any& rAny) const +{ + drawing::LineDash aLineDash; + if(!(rAny >>= aLineDash)) + return std::unique_ptr<XDashEntry>(); + + XDash aXDash; + + aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(aLineDash.Style))); + aXDash.SetDots(aLineDash.Dots); + aXDash.SetDotLen(aLineDash.DotLen); + aXDash.SetDashes(aLineDash.Dashes); + aXDash.SetDashLen(aLineDash.DashLen); + aXDash.SetDistance(aLineDash.Distance); + + return std::make_unique<XDashEntry>(aXDash, rName); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoXDashTable::getElementType() +{ + return cppu::UnoType<drawing::LineDash>::get(); +} + +// XServiceInfo +OUString SAL_CALL SvxUnoXDashTable::getImplementationName( ) +{ + return "SvxUnoXDashTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXDashTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.DashTable" }; +} + +namespace { + +class SvxUnoXHatchTable : public SvxUnoXPropertyTable +{ +public: + explicit SvxUnoXHatchTable( XPropertyList& rTable ) noexcept : SvxUnoXPropertyTable( XATTR_FILLHATCH, rTable ) {}; + + // SvxUnoXPropertyTable + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const noexcept override; + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +} + +uno::Reference< container::XNameContainer > SvxUnoXHatchTable_createInstance( XPropertyList& rTable ) noexcept +{ + return new SvxUnoXHatchTable( rTable ); +} + +// SvxUnoXPropertyTable +uno::Any SvxUnoXHatchTable::getAny( const XPropertyEntry* pEntry ) const noexcept +{ + const XHatch& aHatch = static_cast<const XHatchEntry*>(pEntry)->GetHatch(); + + drawing::Hatch aUnoHatch; + + aUnoHatch.Style = aHatch.GetHatchStyle(); + aUnoHatch.Color = sal_Int32(aHatch.GetColor()); + aUnoHatch.Distance = aHatch.GetDistance(); + aUnoHatch.Angle = aHatch.GetAngle().get(); + + return uno::Any(aUnoHatch); +} + +std::unique_ptr<XPropertyEntry> SvxUnoXHatchTable::createEntry(const OUString& rName, const uno::Any& rAny) const +{ + drawing::Hatch aUnoHatch; + if(!(rAny >>= aUnoHatch)) + return std::unique_ptr<XHatchEntry>(); + + XHatch aXHatch; + aXHatch.SetHatchStyle( aUnoHatch.Style ); + aXHatch.SetColor( Color(ColorTransparency, aUnoHatch.Color) ); + aXHatch.SetDistance( aUnoHatch.Distance ); + aXHatch.SetAngle( Degree10(aUnoHatch.Angle) ); + + return std::make_unique<XHatchEntry>(aXHatch, rName); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoXHatchTable::getElementType() +{ + return cppu::UnoType<drawing::Hatch>::get(); +} + +// XServiceInfo +OUString SAL_CALL SvxUnoXHatchTable::getImplementationName( ) +{ + return "SvxUnoXHatchTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXHatchTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.HatchTable" }; +} + +namespace { + +class SvxUnoXGradientTable : public SvxUnoXPropertyTable +{ +public: + explicit SvxUnoXGradientTable( XPropertyList& rTable ) noexcept : SvxUnoXPropertyTable( XATTR_FILLGRADIENT, rTable ) {}; + + // SvxUnoXPropertyTable + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const noexcept override; + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +} + +uno::Reference< container::XNameContainer > SvxUnoXGradientTable_createInstance( XPropertyList& rTable ) noexcept +{ + return new SvxUnoXGradientTable( rTable ); +} + +// SvxUnoXPropertyTable +uno::Any SvxUnoXGradientTable::getAny( const XPropertyEntry* pEntry ) const noexcept +{ + const XGradient& aXGradient = static_cast<const XGradientEntry*>(pEntry)->GetGradient(); + awt::Gradient aGradient; + + aGradient.Style = aXGradient.GetGradientStyle(); + aGradient.StartColor = static_cast<sal_Int32>(aXGradient.GetStartColor()); + aGradient.EndColor = static_cast<sal_Int32>(aXGradient.GetEndColor()); + aGradient.Angle = static_cast<short>(aXGradient.GetAngle()); + aGradient.Border = aXGradient.GetBorder(); + aGradient.XOffset = aXGradient.GetXOffset(); + aGradient.YOffset = aXGradient.GetYOffset(); + aGradient.StartIntensity = aXGradient.GetStartIntens(); + aGradient.EndIntensity = aXGradient.GetEndIntens(); + aGradient.StepCount = aXGradient.GetSteps(); + + return uno::Any(aGradient); +} + +std::unique_ptr<XPropertyEntry> SvxUnoXGradientTable::createEntry(const OUString& rName, const uno::Any& rAny) const +{ + awt::Gradient aGradient; + if(!(rAny >>= aGradient)) + return std::unique_ptr<XPropertyEntry>(); + + XGradient aXGradient; + + aXGradient.SetGradientStyle( aGradient.Style ); + aXGradient.SetStartColor( Color(ColorTransparency, aGradient.StartColor) ); + aXGradient.SetEndColor( Color(ColorTransparency, aGradient.EndColor) ); + aXGradient.SetAngle( Degree10(aGradient.Angle) ); + aXGradient.SetBorder( aGradient.Border ); + aXGradient.SetXOffset( aGradient.XOffset ); + aXGradient.SetYOffset( aGradient.YOffset ); + aXGradient.SetStartIntens( aGradient.StartIntensity ); + aXGradient.SetEndIntens( aGradient.EndIntensity ); + aXGradient.SetSteps( aGradient.StepCount ); + + return std::make_unique<XGradientEntry>(aXGradient, rName); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoXGradientTable::getElementType() +{ + return cppu::UnoType<awt::Gradient>::get(); +} + +// XServiceInfo +OUString SAL_CALL SvxUnoXGradientTable::getImplementationName( ) +{ + return "SvxUnoXGradientTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXGradientTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.GradientTable" }; +} + +namespace { + +class SvxUnoXBitmapTable : public SvxUnoXPropertyTable +{ +public: + explicit SvxUnoXBitmapTable( XPropertyList& rTable ) noexcept : SvxUnoXPropertyTable( XATTR_FILLBITMAP, rTable ) {}; + + // SvxUnoXPropertyTable + virtual uno::Any getAny( const XPropertyEntry* pEntry ) const override; + virtual std::unique_ptr<XPropertyEntry> createEntry(const OUString& rName, const uno::Any& rAny) const override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +} + +uno::Reference< container::XNameContainer > SvxUnoXBitmapTable_createInstance( XPropertyList& rTable ) noexcept +{ + return new SvxUnoXBitmapTable( rTable ); +} + +// SvxUnoXPropertyTable +uno::Any SvxUnoXBitmapTable::getAny( const XPropertyEntry* pEntry ) const +{ + auto xBitmapEntry = static_cast<const XBitmapEntry*>(pEntry); + css::uno::Reference<css::awt::XBitmap> xBitmap(xBitmapEntry->GetGraphicObject().GetGraphic().GetXGraphic(), uno::UNO_QUERY); + return uno::Any(xBitmap); +} + +std::unique_ptr<XPropertyEntry> SvxUnoXBitmapTable::createEntry(const OUString& rName, const uno::Any& rAny) const +{ + if (!rAny.has<uno::Reference<awt::XBitmap>>()) + return std::unique_ptr<XPropertyEntry>(); + + auto xBitmap = rAny.get<uno::Reference<awt::XBitmap>>(); + if (!xBitmap.is()) + return nullptr; + + uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY); + if (!xGraphic.is()) + return nullptr; + + Graphic aGraphic(xGraphic); + if (aGraphic.IsNone()) + return nullptr; + + GraphicObject aGraphicObject(aGraphic); + return std::make_unique<XBitmapEntry>(aGraphicObject, rName); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoXBitmapTable::getElementType() +{ + return ::cppu::UnoType<awt::XBitmap>::get(); +} + +// XServiceInfo +OUString SAL_CALL SvxUnoXBitmapTable::getImplementationName( ) +{ + return "SvxUnoXBitmapTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoXBitmapTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.BitmapTable" }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/gluepts.cxx b/svx/source/unodraw/gluepts.cxx new file mode 100644 index 000000000..584effb73 --- /dev/null +++ b/svx/source/unodraw/gluepts.cxx @@ -0,0 +1,513 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/container/XIdentifierContainer.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/drawing/GluePoint2.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> + +#include <cppuhelper/implbase.hxx> +#include <tools/weakbase.hxx> + +#include <svx/svdobj.hxx> +#include <svx/svdglue.hxx> + +#include "gluepts.hxx" + +using namespace ::com::sun::star; +using namespace ::cppu; + +const sal_uInt16 NON_USER_DEFINED_GLUE_POINTS = 4; + +namespace { + +class SvxUnoGluePointAccess : public WeakImplHelper< container::XIndexContainer, container::XIdentifierContainer > +{ +private: + tools::WeakReference<SdrObject> mpObject; + +public: + explicit SvxUnoGluePointAccess( SdrObject* pObject ) noexcept; + + // XIdentifierContainer + virtual sal_Int32 SAL_CALL insert( const uno::Any& aElement ) override; + virtual void SAL_CALL removeByIdentifier( sal_Int32 Identifier ) override; + + // XIdentifierReplace + virtual void SAL_CALL replaceByIdentifer( sal_Int32 Identifier, const uno::Any& aElement ) override; + + // XIdentifierReplace + virtual uno::Any SAL_CALL getByIdentifier( sal_Int32 Identifier ) override; + virtual uno::Sequence< sal_Int32 > SAL_CALL getIdentifiers( ) override; + + /* deprecated */ + // XIndexContainer + virtual void SAL_CALL insertByIndex( sal_Int32 Index, const uno::Any& Element ) override; + virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override; + + /* deprecated */ + // XIndexReplace + virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const uno::Any& Element ) override; + + /* deprecated */ + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount( ) override; + virtual uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType( ) override; + virtual sal_Bool SAL_CALL hasElements( ) override; +}; + +} + +static void convert( const SdrGluePoint& rSdrGlue, drawing::GluePoint2& rUnoGlue ) noexcept +{ + rUnoGlue.Position.X = rSdrGlue.GetPos().X(); + rUnoGlue.Position.Y = rSdrGlue.GetPos().Y(); + rUnoGlue.IsRelative = rSdrGlue.IsPercent(); + + SdrAlign eAlign = rSdrGlue.GetAlign(); + if (eAlign == (SdrAlign::VERT_TOP|SdrAlign::HORZ_LEFT)) + rUnoGlue.PositionAlignment = drawing::Alignment_TOP_LEFT; + else if (eAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_TOP)) + rUnoGlue.PositionAlignment = drawing::Alignment_TOP; + else if (eAlign == (SdrAlign::VERT_TOP|SdrAlign::HORZ_RIGHT)) + rUnoGlue.PositionAlignment = drawing::Alignment_TOP_RIGHT; + else if (eAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER)) + rUnoGlue.PositionAlignment = drawing::Alignment_CENTER; + else if (eAlign == (SdrAlign::HORZ_RIGHT|SdrAlign::VERT_CENTER)) + rUnoGlue.PositionAlignment = drawing::Alignment_RIGHT; + else if (eAlign == (SdrAlign::HORZ_LEFT|SdrAlign::VERT_BOTTOM)) + rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM_LEFT; + else if (eAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_BOTTOM)) + rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM; + else if (eAlign == (SdrAlign::HORZ_RIGHT|SdrAlign::VERT_BOTTOM)) + rUnoGlue.PositionAlignment = drawing::Alignment_BOTTOM_RIGHT; + else { + rUnoGlue.PositionAlignment = drawing::Alignment_LEFT; + } + + switch( rSdrGlue.GetEscDir() ) + { + case SdrEscapeDirection::LEFT: + rUnoGlue.Escape = drawing::EscapeDirection_LEFT; + break; + case SdrEscapeDirection::RIGHT: + rUnoGlue.Escape = drawing::EscapeDirection_RIGHT; + break; + case SdrEscapeDirection::TOP: + rUnoGlue.Escape = drawing::EscapeDirection_UP; + break; + case SdrEscapeDirection::BOTTOM: + rUnoGlue.Escape = drawing::EscapeDirection_DOWN; + break; + case SdrEscapeDirection::HORZ: + rUnoGlue.Escape = drawing::EscapeDirection_HORIZONTAL; + break; + case SdrEscapeDirection::VERT: + rUnoGlue.Escape = drawing::EscapeDirection_VERTICAL; + break; +// case SdrEscapeDirection::SMART: + default: + rUnoGlue.Escape = drawing::EscapeDirection_SMART; + break; + } +} + +static void convert( const drawing::GluePoint2& rUnoGlue, SdrGluePoint& rSdrGlue ) noexcept +{ + rSdrGlue.SetPos( Point( rUnoGlue.Position.X, rUnoGlue.Position.Y ) ); + rSdrGlue.SetPercent( rUnoGlue.IsRelative ); + + switch( rUnoGlue.PositionAlignment ) + { + case drawing::Alignment_TOP_LEFT: + rSdrGlue.SetAlign( SdrAlign::VERT_TOP|SdrAlign::HORZ_LEFT ); + break; + case drawing::Alignment_TOP: + rSdrGlue.SetAlign( SdrAlign::HORZ_CENTER|SdrAlign::VERT_TOP ); + break; + case drawing::Alignment_TOP_RIGHT: + rSdrGlue.SetAlign( SdrAlign::VERT_TOP|SdrAlign::HORZ_RIGHT ); + break; + case drawing::Alignment_CENTER: + rSdrGlue.SetAlign( SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER ); + break; + case drawing::Alignment_RIGHT: + rSdrGlue.SetAlign( SdrAlign::HORZ_RIGHT|SdrAlign::VERT_CENTER ); + break; + case drawing::Alignment_BOTTOM_LEFT: + rSdrGlue.SetAlign( SdrAlign::HORZ_LEFT|SdrAlign::VERT_BOTTOM ); + break; + case drawing::Alignment_BOTTOM: + rSdrGlue.SetAlign( SdrAlign::HORZ_CENTER|SdrAlign::VERT_BOTTOM ); + break; + case drawing::Alignment_BOTTOM_RIGHT: + rSdrGlue.SetAlign( SdrAlign::HORZ_RIGHT|SdrAlign::VERT_BOTTOM ); + break; +// case SdrAlign::HORZ_LEFT: + default: + rSdrGlue.SetAlign( SdrAlign::HORZ_LEFT ); + break; + } + switch( rUnoGlue.Escape ) + { + case drawing::EscapeDirection_LEFT: + rSdrGlue.SetEscDir(SdrEscapeDirection::LEFT); + break; + case drawing::EscapeDirection_RIGHT: + rSdrGlue.SetEscDir(SdrEscapeDirection::RIGHT); + break; + case drawing::EscapeDirection_UP: + rSdrGlue.SetEscDir(SdrEscapeDirection::TOP); + break; + case drawing::EscapeDirection_DOWN: + rSdrGlue.SetEscDir(SdrEscapeDirection::BOTTOM); + break; + case drawing::EscapeDirection_HORIZONTAL: + rSdrGlue.SetEscDir(SdrEscapeDirection::HORZ); + break; + case drawing::EscapeDirection_VERTICAL: + rSdrGlue.SetEscDir(SdrEscapeDirection::VERT); + break; +// case drawing::EscapeDirection_SMART: + default: + rSdrGlue.SetEscDir(SdrEscapeDirection::SMART); + break; + } +} + +SvxUnoGluePointAccess::SvxUnoGluePointAccess( SdrObject* pObject ) noexcept +: mpObject( pObject ) +{ +} + +// XIdentifierContainer +sal_Int32 SAL_CALL SvxUnoGluePointAccess::insert( const uno::Any& aElement ) +{ + if( mpObject.is() ) + { + SdrGluePointList* pList = mpObject->ForceGluePointList(); + if( pList ) + { + // second, insert the new gluepoint + drawing::GluePoint2 aUnoGlue; + + if( aElement >>= aUnoGlue ) + { + SdrGluePoint aSdrGlue; + convert( aUnoGlue, aSdrGlue ); + sal_uInt16 nId = pList->Insert( aSdrGlue ); + + // only repaint, no objectchange + mpObject->ActionChanged(); + // mpObject->BroadcastObjectChange(); + + return static_cast<sal_Int32>((*pList)[nId].GetId() + NON_USER_DEFINED_GLUE_POINTS) - 1; + } + + throw lang::IllegalArgumentException(); + } + } + + return -1; +} + +void SAL_CALL SvxUnoGluePointAccess::removeByIdentifier( sal_Int32 Identifier ) +{ + if( mpObject.is() && ( Identifier >= NON_USER_DEFINED_GLUE_POINTS )) + { + const sal_uInt16 nId = static_cast<sal_uInt16>(Identifier - NON_USER_DEFINED_GLUE_POINTS) + 1; + + SdrGluePointList* pList = const_cast<SdrGluePointList*>(mpObject->GetGluePointList()); + const sal_uInt16 nCount = pList ? pList->GetCount() : 0; + sal_uInt16 i; + + for( i = 0; i < nCount; i++ ) + { + if( (*pList)[i].GetId() == nId ) + { + pList->Delete( i ); + + // only repaint, no objectchange + mpObject->ActionChanged(); + // mpObject->BroadcastObjectChange(); + + return; + } + } + } + + throw container::NoSuchElementException(); +} + +// XIdentifierReplace +void SAL_CALL SvxUnoGluePointAccess::replaceByIdentifer( sal_Int32 Identifier, const uno::Any& aElement ) +{ + if( !mpObject.is() ) + return; + + struct drawing::GluePoint2 aGluePoint; + if( (Identifier < NON_USER_DEFINED_GLUE_POINTS) || !(aElement >>= aGluePoint)) + throw lang::IllegalArgumentException(); + + const sal_uInt16 nId = static_cast<sal_uInt16>( Identifier - NON_USER_DEFINED_GLUE_POINTS ) + 1; + + SdrGluePointList* pList = const_cast< SdrGluePointList* >( mpObject->GetGluePointList() ); + const sal_uInt16 nCount = pList ? pList->GetCount() : 0; + sal_uInt16 i; + for( i = 0; i < nCount; i++ ) + { + if( (*pList)[i].GetId() == nId ) + { + // change the gluepoint + SdrGluePoint& rTempPoint = (*pList)[i]; + convert( aGluePoint, rTempPoint ); + + // only repaint, no objectchange + mpObject->ActionChanged(); + // mpObject->BroadcastObjectChange(); + + return; + } + } + + throw container::NoSuchElementException(); +} + +// XIdentifierAccess +uno::Any SAL_CALL SvxUnoGluePointAccess::getByIdentifier( sal_Int32 Identifier ) +{ + if( mpObject.is() ) + { + struct drawing::GluePoint2 aGluePoint; + + if( Identifier < NON_USER_DEFINED_GLUE_POINTS ) // default gluepoint? + { + SdrGluePoint aTempPoint = mpObject->GetVertexGluePoint( static_cast<sal_uInt16>(Identifier) ); + aGluePoint.IsUserDefined = false; + convert( aTempPoint, aGluePoint ); + return uno::Any( aGluePoint ); + } + else + { + const sal_uInt16 nId = static_cast<sal_uInt16>( Identifier - NON_USER_DEFINED_GLUE_POINTS ) + 1; + + const SdrGluePointList* pList = mpObject->GetGluePointList(); + const sal_uInt16 nCount = pList ? pList->GetCount() : 0; + for( sal_uInt16 i = 0; i < nCount; i++ ) + { + const SdrGluePoint& rTempPoint = (*pList)[i]; + if( rTempPoint.GetId() == nId ) + { + // #i38892# + if(rTempPoint.IsUserDefined()) + { + aGluePoint.IsUserDefined = true; + } + + convert( rTempPoint, aGluePoint ); + return uno::Any( aGluePoint ); + } + } + } + } + + throw container::NoSuchElementException(); +} + +uno::Sequence< sal_Int32 > SAL_CALL SvxUnoGluePointAccess::getIdentifiers() +{ + if( mpObject.is() ) + { + const SdrGluePointList* pList = mpObject->GetGluePointList(); + const sal_uInt16 nCount = pList ? pList->GetCount() : 0; + + sal_uInt16 i; + + uno::Sequence< sal_Int32 > aIdSequence( nCount + NON_USER_DEFINED_GLUE_POINTS ); + sal_Int32 *pIdentifier = aIdSequence.getArray(); + + for( i = 0; i < NON_USER_DEFINED_GLUE_POINTS; i++ ) + *pIdentifier++ = static_cast<sal_Int32>(i); + + for( i = 0; i < nCount; i++ ) + *pIdentifier++ = static_cast<sal_Int32>( (*pList)[i].GetId() + NON_USER_DEFINED_GLUE_POINTS ) - 1; + + return aIdSequence; + } + else + { + uno::Sequence< sal_Int32 > aEmpty; + return aEmpty; + } +} + +/* deprecated */ + +// XIndexContainer +void SAL_CALL SvxUnoGluePointAccess::insertByIndex( sal_Int32, const uno::Any& Element ) +{ + if( mpObject.is() ) + { + SdrGluePointList* pList = mpObject->ForceGluePointList(); + if( pList ) + { + drawing::GluePoint2 aUnoGlue; + + if( Element >>= aUnoGlue ) + { + SdrGluePoint aSdrGlue; + convert( aUnoGlue, aSdrGlue ); + pList->Insert( aSdrGlue ); + + // only repaint, no objectchange + mpObject->ActionChanged(); + // mpObject->BroadcastObjectChange(); + + return; + } + + throw lang::IllegalArgumentException(); + } + } + + throw lang::IndexOutOfBoundsException(); +} + +void SAL_CALL SvxUnoGluePointAccess::removeByIndex( sal_Int32 Index ) +{ + if( mpObject.is() ) + { + SdrGluePointList* pList = mpObject->ForceGluePointList(); + if( pList ) + { + Index -= 4; + if( Index >= 0 && Index < pList->GetCount() ) + { + pList->Delete( static_cast<sal_uInt16>(Index) ); + + // only repaint, no objectchange + mpObject->ActionChanged(); + // mpObject->BroadcastObjectChange(); + + return; + } + } + } + + throw lang::IndexOutOfBoundsException(); +} + +// XIndexReplace +void SAL_CALL SvxUnoGluePointAccess::replaceByIndex( sal_Int32 Index, const uno::Any& Element ) +{ + drawing::GluePoint2 aUnoGlue; + if(!(Element >>= aUnoGlue)) + throw lang::IllegalArgumentException(); + + Index -= 4; + if( mpObject.is() && Index >= 0 ) + { + SdrGluePointList* pList = const_cast< SdrGluePointList* >( mpObject->GetGluePointList() ); + if( pList && Index < pList->GetCount() ) + { + SdrGluePoint& rGlue = (*pList)[static_cast<sal_uInt16>(Index)]; + convert( aUnoGlue, rGlue ); + + // only repaint, no objectchange + mpObject->ActionChanged(); + // mpObject->BroadcastObjectChange(); + } + } + + throw lang::IndexOutOfBoundsException(); +} + +// XIndexAccess +sal_Int32 SAL_CALL SvxUnoGluePointAccess::getCount() +{ + sal_Int32 nCount = 0; + if( mpObject.is() ) + { + // each node has a default of 4 gluepoints + // and any number of user defined gluepoints + nCount += 4; + + const SdrGluePointList* pList = mpObject->GetGluePointList(); + if( pList ) + nCount += pList->GetCount(); + } + + return nCount; +} + +uno::Any SAL_CALL SvxUnoGluePointAccess::getByIndex( sal_Int32 Index ) +{ + if( Index >= 0 && mpObject.is() ) + { + struct drawing::GluePoint2 aGluePoint; + + if( Index < 4 ) // default gluepoint? + { + SdrGluePoint aTempPoint = mpObject->GetVertexGluePoint( static_cast<sal_uInt16>(Index) ); + aGluePoint.IsUserDefined = false; + convert( aTempPoint, aGluePoint ); + return uno::Any(aGluePoint); + } + else + { + Index -= 4; + const SdrGluePointList* pList = mpObject->GetGluePointList(); + if( pList && Index < pList->GetCount() ) + { + const SdrGluePoint& rTempPoint = (*pList)[static_cast<sal_uInt16>(Index)]; + aGluePoint.IsUserDefined = true; + convert( rTempPoint, aGluePoint ); + return uno::Any(aGluePoint); + } + } + } + + throw lang::IndexOutOfBoundsException(); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoGluePointAccess::getElementType() +{ + return cppu::UnoType<drawing::GluePoint2>::get(); +} + +sal_Bool SAL_CALL SvxUnoGluePointAccess::hasElements() +{ + return mpObject.is(); +} + +/** + * Create a SvxUnoGluePointAccess + */ +uno::Reference< uno::XInterface > SvxUnoGluePointAccess_createInstance( SdrObject* pObject ) +{ + return *new SvxUnoGluePointAccess(pObject); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/gluepts.hxx b/svx/source/unodraw/gluepts.hxx new file mode 100644 index 000000000..303f7213e --- /dev/null +++ b/svx/source/unodraw/gluepts.hxx @@ -0,0 +1,37 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVX_SOURCE_UNODRAW_GLUEPTS_HXX +#define INCLUDED_SVX_SOURCE_UNODRAW_GLUEPTS_HXX + +#include <sal/config.h> + +#include <com/sun/star/uno/Reference.hxx> + +namespace com::sun::star::uno +{ +class XInterface; +} +class SdrObject; + +css::uno::Reference<css::uno::XInterface> SvxUnoGluePointAccess_createInstance(SdrObject* pObject); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/recoveryui.cxx b/svx/source/unodraw/recoveryui.cxx new file mode 100644 index 000000000..56550fd7f --- /dev/null +++ b/svx/source/unodraw/recoveryui.cxx @@ -0,0 +1,331 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_folders.h> + +#include <docrecovery.hxx> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XSynchronousDispatch.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> +#include <osl/file.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/ref.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <vcl/svapp.hxx> + +namespace svxdr = svx::DocRecovery; +using namespace ::osl; + +namespace { + +class RecoveryUI : public ::cppu::WeakImplHelper< css::lang::XServiceInfo , + css::frame::XSynchronousDispatch > // => XDispatch! +{ + + // const, types, etcpp. + private: + + /** @short TODO */ + enum EJob + { + E_JOB_UNKNOWN, + E_DO_EMERGENCY_SAVE, + E_DO_RECOVERY, + E_DO_BRINGTOFRONT, + }; + + + // member + private: + + /** @short TODO */ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + /** @short TODO */ + weld::Window* m_pParentWindow; + + /** @short TODO */ + RecoveryUI::EJob m_eJob; + + // Active dialog + weld::Dialog* m_pDialog; + + // interface + public: + + + /** @short TODO */ + explicit RecoveryUI(const css::uno::Reference< css::uno::XComponentContext >& xContext); + + // css.lang.XServiceInfo + + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + + virtual css::uno::Any SAL_CALL dispatchWithReturnValue(const css::util::URL& aURL, + const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override; + + void SetActiveDialog(weld::Dialog* pDialog) + { + m_pDialog = pDialog; + } + + // helper + private: + + EJob impl_classifyJob(const css::util::URL& aURL); + + bool impl_doEmergencySave(); + + bool impl_doRecovery(); + + void impl_showAllRecoveredDocs(); + + bool impl_doBringToFront(); +}; + +RecoveryUI::RecoveryUI(const css::uno::Reference< css::uno::XComponentContext >& xContext) + : m_xContext(xContext) + , m_pParentWindow(nullptr) + , m_eJob(RecoveryUI::E_JOB_UNKNOWN) + , m_pDialog(nullptr) +{ +} + +OUString SAL_CALL RecoveryUI::getImplementationName() +{ + return "com.sun.star.comp.svx.RecoveryUI"; +} + +sal_Bool SAL_CALL RecoveryUI::supportsService(const OUString& sServiceName) +{ + return cppu::supportsService(this, sServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL RecoveryUI::getSupportedServiceNames() +{ + return { "com.sun.star.dialog.RecoveryUI" }; +} + +css::uno::Any SAL_CALL RecoveryUI::dispatchWithReturnValue(const css::util::URL& aURL, + const css::uno::Sequence< css::beans::PropertyValue >& ) +{ + // Internally we use VCL ... every call into vcl based code must + // be guarded by locking the global solar mutex. + ::SolarMutexGuard aSolarLock; + + css::uno::Any aRet; + RecoveryUI::EJob eJob = impl_classifyJob(aURL); + // TODO think about outside arguments + + switch(eJob) + { + case RecoveryUI::E_DO_EMERGENCY_SAVE: + { + bool bRet = impl_doEmergencySave(); + aRet <<= bRet; + break; + } + + case RecoveryUI::E_DO_RECOVERY: + { + bool bRet = impl_doRecovery(); + aRet <<= bRet; + break; + } + + case RecoveryUI::E_DO_BRINGTOFRONT: + { + bool bRet = impl_doBringToFront(); + aRet <<= bRet; + break; + } + + default: + { + aRet <<= false; + break; + } + } + + return aRet; +} + + +OUString GetCrashConfigDir() +{ + +#if defined(_WIN32) + OUString ustrValue = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/bootstrap.ini:UserInstallation}"; +#elif defined(MACOSX) + OUString ustrValue = "~"; +#else + OUString ustrValue = "$SYSUSERCONFIG"; +#endif + rtl::Bootstrap::expandMacros( ustrValue ); + +#if defined(_WIN32) + ustrValue += "/user/crashdata"; +#endif + return ustrValue; +} + + +#if defined(_WIN32) +#define LCKFILE "crashdat.lck" +#else +#define LCKFILE ".crash_report_unsent" +#endif + + +OUString GetUnsentURL() +{ + OUString aURL = GetCrashConfigDir() + "/" LCKFILE; + return aURL; +} + + +bool delete_pending_crash() +{ + OUString aUnsentURL = GetUnsentURL(); + return ( FileBase::E_None == File::remove( aUnsentURL ) ); +} + +RecoveryUI::EJob RecoveryUI::impl_classifyJob(const css::util::URL& aURL) +{ + m_eJob = RecoveryUI::E_JOB_UNKNOWN; + if (aURL.Protocol == RECOVERY_CMDPART_PROTOCOL) + { + if (aURL.Path == RECOVERY_CMDPART_DO_EMERGENCY_SAVE) + m_eJob = RecoveryUI::E_DO_EMERGENCY_SAVE; + else if (aURL.Path == RECOVERY_CMDPART_DO_RECOVERY) + m_eJob = RecoveryUI::E_DO_RECOVERY; + else if (aURL.Path == RECOVERY_CMDPART_DO_BRINGTOFRONT) + m_eJob = RecoveryUI::E_DO_BRINGTOFRONT; + } + + return m_eJob; +} + +struct DialogReleaseGuard +{ + RecoveryUI& m_rRecoveryUI; + + DialogReleaseGuard(RecoveryUI& rRecoveryUI, weld::Dialog* p) + : m_rRecoveryUI(rRecoveryUI) + { + m_rRecoveryUI.SetActiveDialog(p); + } + ~DialogReleaseGuard() + { + m_rRecoveryUI.SetActiveDialog(nullptr); + } +}; + +bool RecoveryUI::impl_doEmergencySave() +{ + // create core service, which implements the real "emergency save" algorithm. + rtl::Reference<svxdr::RecoveryCore> pCore = new svxdr::RecoveryCore(m_xContext, true); + + // create dialog for this operation and bind it to the used core service + std::unique_ptr<svxdr::SaveDialog> xDialog(new svxdr::SaveDialog(m_pParentWindow, pCore.get())); + DialogReleaseGuard dialogReleaseGuard(*this, xDialog->getDialog()); + + // start the dialog + short nRet = xDialog->run(); + return (nRet==DLG_RET_OK_AUTOLUNCH); +} + +bool RecoveryUI::impl_doRecovery() +{ + // create core service, which implements the real "emergency save" algorithm. + rtl::Reference<svxdr::RecoveryCore> pCore = new svxdr::RecoveryCore(m_xContext, false); + + // create all needed dialogs for this operation + // and bind it to the used core service + std::unique_ptr<svxdr::RecoveryDialog> xDialog(new svxdr::RecoveryDialog(m_pParentWindow, pCore.get())); + DialogReleaseGuard dialogReleaseGuard(*this, xDialog->getDialog()); + + // start the dialog + short nRet = xDialog->run(); + + impl_showAllRecoveredDocs(); + + delete_pending_crash(); + + return nRet != RET_CANCEL; +} + +void RecoveryUI::impl_showAllRecoveredDocs() +{ + css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( m_xContext ); + + css::uno::Reference< css::container::XIndexAccess > xTaskContainer( + xDesktop->getFrames(), + css::uno::UNO_QUERY_THROW); + + sal_Int32 c = xTaskContainer->getCount(); + sal_Int32 i = 0; + for (i=0; i<c; ++i) + { + try + { + css::uno::Reference< css::frame::XFrame > xTask; + xTaskContainer->getByIndex(i) >>= xTask; + if (!xTask.is()) + continue; + + css::uno::Reference< css::awt::XWindow > xWindow = xTask->getContainerWindow(); + if (!xWindow.is()) + continue; + + xWindow->setVisible(true); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { continue; } + } +} + +bool RecoveryUI::impl_doBringToFront() +{ + if (!m_pDialog || !m_pDialog->get_visible()) + return false; + m_pDialog->present(); + return true; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_RecoveryUI_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new RecoveryUI(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/shapeimpl.hxx b/svx/source/unodraw/shapeimpl.hxx new file mode 100644 index 000000000..68189814f --- /dev/null +++ b/svx/source/unodraw/shapeimpl.hxx @@ -0,0 +1,96 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SVX_SOURCE_UNODRAW_SHAPEIMPL_HXX +#define INCLUDED_SVX_SOURCE_UNODRAW_SHAPEIMPL_HXX + +#include <svx/unoprov.hxx> +#include <svx/unoshape.hxx> + +class SvxShapeCaption : public SvxShapeText +{ +public: + explicit SvxShapeCaption(SdrObject* pObj); + virtual ~SvxShapeCaption() noexcept override; +}; +class SvxPluginShape : public SvxOle2Shape +{ +protected: + // override these for special property handling in subcasses. Return true if property is handled + virtual bool setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) override; + virtual bool getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) override; + +public: + explicit SvxPluginShape(SdrObject* pObj); + virtual ~SvxPluginShape() noexcept override; + + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + using SvxUnoTextRangeBase::setPropertyValue; + + virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override; + + virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override; +}; +class SvxAppletShape : public SvxOle2Shape +{ +protected: + // override these for special property handling in subcasses. Return true if property is handled + virtual bool setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) override; + virtual bool getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) override; + +public: + explicit SvxAppletShape(SdrObject* pObj); + virtual ~SvxAppletShape() noexcept override; + + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + using SvxUnoTextRangeBase::setPropertyValue; + + virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override; + + virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override; +}; + +class SvxFrameShape : public SvxOle2Shape +{ +private: + OUString m_sInitialFrameURL; +protected: + // override these for special property handling in subcasses. Return true if property is handled + virtual bool setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) override; + virtual bool getPropertyValueImpl(const OUString& rName, const SfxItemPropertyMapEntry* pProperty, + css::uno::Any& rValue) override; + +public: + explicit SvxFrameShape(SdrObject* pObj); + virtual ~SvxFrameShape() noexcept override; + + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + using SvxUnoTextRangeBase::setPropertyValue; + + virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override; + + virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override; + + virtual OUString GetAndClearInitialFrameURL() override; +}; + +SvxUnoPropertyMapProvider& getSvxMapProvider(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/shapepropertynotifier.cxx b/svx/source/unodraw/shapepropertynotifier.cxx new file mode 100644 index 000000000..a19a5fd96 --- /dev/null +++ b/svx/source/unodraw/shapepropertynotifier.cxx @@ -0,0 +1,143 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <svx/shapepropertynotifier.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <cppuhelper/weak.hxx> +#include <tools/diagnose_ex.h> + +namespace +{ + +} + + +namespace svx +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + using ::com::sun::star::beans::PropertyChangeEvent; + using ::com::sun::star::beans::XPropertyChangeListener; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::beans::XPropertySet; + + PropertyValueProvider::~PropertyValueProvider() + { + } + + //= PropertyValueProvider + + + const OUString & PropertyValueProvider::getPropertyName() const + { + return m_sPropertyName; + } + + + void PropertyValueProvider::getCurrentValue( Any& _out_rValue ) const + { + Reference< XPropertySet > xContextProps( const_cast< PropertyValueProvider* >( this )->m_rContext, UNO_QUERY_THROW ); + _out_rValue = xContextProps->getPropertyValue( getPropertyName() ); + } + + PropertyChangeNotifier::PropertyChangeNotifier( ::cppu::OWeakObject& _rOwner, ::osl::Mutex& _rMutex ) + :m_rContext( _rOwner ) + ,m_aPropertyChangeListeners( _rMutex ) + { + } + + PropertyChangeNotifier::~PropertyChangeNotifier() + { + } + + void PropertyChangeNotifier::registerProvider(const ShapePropertyProviderId _eProperty, std::unique_ptr<PropertyValueProvider> _rProvider) + { + assert( _rProvider && "NULL factory not allowed." ); + + assert( ! m_aProviders[_eProperty] && + "PropertyChangeNotifier::registerProvider: factory for this ID already present!" ); + + m_aProviders[ _eProperty ] = std::move(_rProvider); + } + + void PropertyChangeNotifier::notifyPropertyChange( const ShapePropertyProviderId _eProperty ) const + { + auto & provPos = m_aProviders[ _eProperty ]; + OSL_ENSURE( provPos, "PropertyChangeNotifier::notifyPropertyChange: no factory!" ); + if (!provPos) + return; + + const OUString & sPropertyName( provPos->getPropertyName() ); + + ::comphelper::OInterfaceContainerHelper3<XPropertyChangeListener>* pPropListeners = m_aPropertyChangeListeners.getContainer( sPropertyName ); + ::comphelper::OInterfaceContainerHelper3<XPropertyChangeListener>* pAllListeners = m_aPropertyChangeListeners.getContainer( OUString() ); + if ( !pPropListeners && !pAllListeners ) + return; + + try + { + PropertyChangeEvent aEvent; + aEvent.Source = m_rContext; + // Handle/OldValue not supported + aEvent.PropertyName = provPos->getPropertyName(); + provPos->getCurrentValue( aEvent.NewValue ); + + if ( pPropListeners ) + pPropListeners->notifyEach( &XPropertyChangeListener::propertyChange, aEvent ); + if ( pAllListeners ) + pAllListeners->notifyEach( &XPropertyChangeListener::propertyChange, aEvent ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("svx"); + } + } + + + void PropertyChangeNotifier::addPropertyChangeListener( const OUString& _rPropertyName, const Reference< XPropertyChangeListener >& _rxListener ) + { + m_aPropertyChangeListeners.addInterface( _rPropertyName, _rxListener ); + } + + + void PropertyChangeNotifier::removePropertyChangeListener( const OUString& _rPropertyName, const Reference< XPropertyChangeListener >& _rxListener ) + { + m_aPropertyChangeListeners.removeInterface( _rPropertyName, _rxListener ); + } + + + void PropertyChangeNotifier::disposing() + { + EventObject aEvent; + aEvent.Source = m_rContext; + m_aPropertyChangeListeners.disposeAndClear( aEvent ); + } + + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/tableshape.cxx b/svx/source/unodraw/tableshape.cxx new file mode 100644 index 000000000..b92205164 --- /dev/null +++ b/svx/source/unodraw/tableshape.cxx @@ -0,0 +1,178 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include "UnoGraphicExporter.hxx" +#include "shapeimpl.hxx" +#include <svx/unodraw/SvxTableShape.hxx> +#include <svx/unoshprp.hxx> +#include <svx/svdotable.hxx> +#include <svx/svdpool.hxx> + + +using namespace ::osl; +using namespace ::cppu; +using namespace sdr::table; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; + +SvxTableShape::SvxTableShape(SdrObject* pObj) +: SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_TABLE), getSvxMapProvider().GetPropertySet(SVXMAP_TABLE, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ + SetShapeType( "com.sun.star.drawing.TableShape" ); +} + +SvxTableShape::~SvxTableShape() noexcept +{ +} + +bool SvxTableShape::setPropertyValueImpl( + const OUString& rName, + const SfxItemPropertyMapEntry* pProperty, + const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_TABLETEMPLATE: + { + Reference< XIndexAccess > xTemplate; + + if( !(rValue >>= xTemplate) ) + throw IllegalArgumentException(); + + if( HasSdrObject() ) + static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->setTableStyle(xTemplate); + + return true; + } + case OWN_ATTR_TABLETEMPLATE_FIRSTROW: + case OWN_ATTR_TABLETEMPLATE_LASTROW: + case OWN_ATTR_TABLETEMPLATE_FIRSTCOLUMN: + case OWN_ATTR_TABLETEMPLATE_LASTCOLUMN: + case OWN_ATTR_TABLETEMPLATE_BANDINGROWS: + case OWN_ATTR_TABLETEMPLATE_BANDINGCOLUMNS: + { + if( HasSdrObject() ) + { + TableStyleSettings aSettings( static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->getTableStyleSettings() ); + + switch( pProperty->nWID ) + { + case OWN_ATTR_TABLETEMPLATE_FIRSTROW: rValue >>= aSettings.mbUseFirstRow; break; + case OWN_ATTR_TABLETEMPLATE_LASTROW: rValue >>= aSettings.mbUseLastRow; break; + case OWN_ATTR_TABLETEMPLATE_FIRSTCOLUMN: rValue >>= aSettings.mbUseFirstColumn; break; + case OWN_ATTR_TABLETEMPLATE_LASTCOLUMN: rValue >>= aSettings.mbUseLastColumn; break; + case OWN_ATTR_TABLETEMPLATE_BANDINGROWS: rValue >>= aSettings.mbUseRowBanding; break; + case OWN_ATTR_TABLETEMPLATE_BANDINGCOLUMNS: rValue >>= aSettings.mbUseColumnBanding; break; + } + + static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->setTableStyleSettings(aSettings); + } + + return true; + } + default: + { + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + } +} + +bool SvxTableShape::getPropertyValueImpl( + const OUString& rName, + const SfxItemPropertyMapEntry* pProperty, + css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_OLEMODEL: + { + if( HasSdrObject() ) + { + rValue <<= static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->getTable(); + } + return true; + } + case OWN_ATTR_TABLETEMPLATE: + { + if( HasSdrObject() ) + { + rValue <<= static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->getTableStyle(); + } + return true; + } + case OWN_ATTR_REPLACEMENT_GRAPHIC: + { + if( HasSdrObject() ) + { + Graphic aGraphic( SvxGetGraphicForShape( *GetSdrObject() ) ); + rValue <<= aGraphic.GetXGraphic(); + } + return true; + } + case OWN_ATTR_TABLETEMPLATE_FIRSTROW: + case OWN_ATTR_TABLETEMPLATE_LASTROW: + case OWN_ATTR_TABLETEMPLATE_FIRSTCOLUMN: + case OWN_ATTR_TABLETEMPLATE_LASTCOLUMN: + case OWN_ATTR_TABLETEMPLATE_BANDINGROWS: + case OWN_ATTR_TABLETEMPLATE_BANDINGCOLUMNS: + { + if( HasSdrObject() ) + { + TableStyleSettings aSettings( static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->getTableStyleSettings() ); + + switch( pProperty->nWID ) + { + case OWN_ATTR_TABLETEMPLATE_FIRSTROW: rValue <<= aSettings.mbUseFirstRow; break; + case OWN_ATTR_TABLETEMPLATE_LASTROW: rValue <<= aSettings.mbUseLastRow; break; + case OWN_ATTR_TABLETEMPLATE_FIRSTCOLUMN: rValue <<= aSettings.mbUseFirstColumn; break; + case OWN_ATTR_TABLETEMPLATE_LASTCOLUMN: rValue <<= aSettings.mbUseLastColumn; break; + case OWN_ATTR_TABLETEMPLATE_BANDINGROWS: rValue <<= aSettings.mbUseRowBanding; break; + case OWN_ATTR_TABLETEMPLATE_BANDINGCOLUMNS: rValue <<= aSettings.mbUseColumnBanding; break; + } + } + + return true; + } + default: + { + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + } +} + +void SvxTableShape::lock() +{ + SvxShape::lock(); + if( HasSdrObject() ) + static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->uno_lock(); +} + +void SvxTableShape::unlock() +{ + if( HasSdrObject() ) + static_cast< sdr::table::SdrTableObj* >( GetSdrObject() )->uno_unlock(); + SvxShape::unlock(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unobrushitemhelper.cxx b/svx/source/unodraw/unobrushitemhelper.cxx new file mode 100644 index 000000000..bc9d04747 --- /dev/null +++ b/svx/source/unodraw/unobrushitemhelper.cxx @@ -0,0 +1,342 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <algorithm> + +#include <osl/diagnose.h> +#include <svl/itemset.hxx> +#include <svx/unobrushitemhelper.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xflbmpit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbckit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xfltrit.hxx> + +using namespace com::sun::star; + +void setSvxBrushItemAsFillAttributesToTargetSet(const SvxBrushItem& rBrush, SfxItemSet& rToSet) +{ + // Clear all items from the DrawingLayer FillStyle range (if we have any). All + // items that need to be set will be set as hard attributes + for(sal_uInt16 a(XATTR_FILL_FIRST); rToSet.Count() && a < XATTR_FILL_LAST; a++) + { + rToSet.ClearItem(a); + } + + const sal_uInt8 nTransparency(255 - rBrush.GetColor().GetAlpha()); + + // tdf#89478 check for image first + if (GPOS_NONE != rBrush.GetGraphicPos()) + { + // we have a graphic fill, set fill style + rToSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + + // set graphic (if available) + const Graphic* pGraphic = rBrush.GetGraphic(); + + if(pGraphic) + { + rToSet.Put(XFillBitmapItem(OUString(), *pGraphic)); + } + else + { + OSL_ENSURE(false, "Could not get Graphic from SvxBrushItem (!)"); + } + + if(GPOS_AREA == rBrush.GetGraphicPos()) + { + // stretch, also means no tile (both items are defaulted to true) + rToSet.Put(XFillBmpStretchItem(true)); + rToSet.Put(XFillBmpTileItem(false)); + + // default for stretch is also top-left, but this will not be visible + rToSet.Put(XFillBmpPosItem(RectPoint::LT)); + } + else if(GPOS_TILED == rBrush.GetGraphicPos()) + { + // tiled, also means no stretch (both items are defaulted to true) + rToSet.Put(XFillBmpStretchItem(false)); + rToSet.Put(XFillBmpTileItem(true)); + + // default for tiled is top-left + rToSet.Put(XFillBmpPosItem(RectPoint::LT)); + } + else + { + // everything else means no tile and no stretch + rToSet.Put(XFillBmpStretchItem(false)); + rToSet.Put(XFillBmpTileItem(false)); + + RectPoint aRectPoint(RectPoint::MM); + + switch(rBrush.GetGraphicPos()) + { + case GPOS_LT: aRectPoint = RectPoint::LT; break; + case GPOS_MT: aRectPoint = RectPoint::MT; break; + case GPOS_RT: aRectPoint = RectPoint::RT; break; + case GPOS_LM: aRectPoint = RectPoint::LM; break; + case GPOS_MM: aRectPoint = RectPoint::MM; break; + case GPOS_RM: aRectPoint = RectPoint::RM; break; + case GPOS_LB: aRectPoint = RectPoint::LB; break; + case GPOS_MB: aRectPoint = RectPoint::MB; break; + case GPOS_RB: aRectPoint = RectPoint::RB; break; + default: break; // GPOS_NONE, GPOS_AREA and GPOS_TILED already handled + } + + rToSet.Put(XFillBmpPosItem(aRectPoint)); + } + + // check for graphic's transparency + const sal_Int8 nGraphicTransparency(rBrush.getGraphicTransparency()); + + if(0 != nGraphicTransparency) + { + // nGraphicTransparency is in range [0..100] + rToSet.Put(XFillTransparenceItem(nGraphicTransparency)); + } + } + else if (0xff != nTransparency) + { + // we have a color fill + const Color aColor(rBrush.GetColor().GetRGBColor()); + + rToSet.Put(XFillStyleItem(drawing::FillStyle_SOLID)); + rToSet.Put(XFillColorItem(OUString(), aColor)); + + // #125189# nTransparency is in range [0..254], convert to [0..100] which is used in + // XFillTransparenceItem (caution with the range which is in an *item-specific* range) + rToSet.Put(XFillTransparenceItem(((static_cast<sal_Int32>(nTransparency) * 100) + 127) / 254)); + } + else + { + // GPOS_NONE == rBrush.GetGraphicPos() && 0xff == rBrush.GetColor().GetTransparency(), + // still need to rescue the color used. There are sequences used on the UNO API at + // import time (OLE. e.g. chart) which first set RGB color (MID_BACK_COLOR_R_G_B, + // color stays transparent) and then set transparency (MID_BACK_COLOR_TRANSPARENCY) + // to zero later. When not saving the color, it will be lost. + // Also need to set the FillStyle to NONE to express the 0xff transparency flag; this + // is needed when e.g. first transparency is set to 0xff and then a Graphic gets set. + // When not changing the FillStyle, the next getSvxBrushItemFromSourceSet *will* return + // to drawing::FillStyle_SOLID with the rescued color. + const Color aColor(rBrush.GetColor().GetRGBColor()); + + rToSet.Put(XFillStyleItem(drawing::FillStyle_NONE)); + rToSet.Put(XFillColorItem(OUString(), aColor)); + } +} + +static sal_uInt16 getTransparenceForSvxBrushItem(const SfxItemSet& rSourceSet, bool bSearchInParents) +{ + sal_uInt16 nFillTransparence(rSourceSet.Get(XATTR_FILLTRANSPARENCE, bSearchInParents).GetValue()); + const XFillFloatTransparenceItem* pGradientItem = nullptr; + + if((pGradientItem = rSourceSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE, bSearchInParents)) + && pGradientItem->IsEnabled()) + { + const XGradient& rGradient = pGradientItem->GetGradientValue(); + const sal_uInt16 nStartLuminance(rGradient.GetStartColor().GetLuminance()); + const sal_uInt16 nEndLuminance(rGradient.GetEndColor().GetLuminance()); + + // luminance is [0..255], transparence needs to be in [0..100].Maximum is 51200, thus sal_uInt16 is okay to use + nFillTransparence = static_cast< sal_uInt16 >(((nStartLuminance + nEndLuminance) * 100) / 512); + } + + return nFillTransparence; +} + +static std::unique_ptr<SvxBrushItem> getSvxBrushItemForSolid(const SfxItemSet& rSourceSet, bool bSearchInParents, sal_uInt16 nBackgroundID) +{ + Color aFillColor(rSourceSet.Get(XATTR_FILLCOLOR, bSearchInParents).GetColorValue()); + + // get evtl. mixed transparence + const sal_uInt16 nFillTransparence(getTransparenceForSvxBrushItem(rSourceSet, bSearchInParents)); + + if(0 != nFillTransparence) + { + // #i125189# nFillTransparence is in range [0..100] and needs to be in [0..254] unsigned + // It is necessary to use the maximum of 0xfe for transparence for the SvxBrushItem + // since the oxff value is used for special purposes (like no fill and derive from parent) + const sal_uInt8 aTargetTrans(std::min(sal_uInt8(0xfe), static_cast< sal_uInt8 >((nFillTransparence * 254) / 100))); + + aFillColor.SetAlpha(255 - aTargetTrans); + } + + return std::make_unique<SvxBrushItem>(aFillColor, nBackgroundID); +} + +std::unique_ptr<SvxBrushItem> getSvxBrushItemFromSourceSet(const SfxItemSet& rSourceSet, sal_uInt16 nBackgroundID, bool bSearchInParents, bool bXMLImportHack) +{ + const XFillStyleItem* pXFillStyleItem(rSourceSet.GetItem<XFillStyleItem>(XATTR_FILLSTYLE, bSearchInParents)); + + if(!pXFillStyleItem || drawing::FillStyle_NONE == pXFillStyleItem->GetValue()) + { + // no fill, still need to rescue the evtl. set RGB color, but use as transparent color (we have drawing::FillStyle_NONE) + Color aFillColor(rSourceSet.Get(XATTR_FILLCOLOR, bSearchInParents).GetColorValue()); + + // for writerfilter: when fill style is none, then don't allow anything other than 0 or auto. + if (!bXMLImportHack && aFillColor != Color(0)) + aFillColor = COL_AUTO; + + aFillColor.SetAlpha(0); + + return std::make_unique<SvxBrushItem>(aFillColor, nBackgroundID); + } + + std::unique_ptr<SvxBrushItem> xRetval; + + switch(pXFillStyleItem->GetValue()) + { + case drawing::FillStyle_NONE: + { + // already handled above, can not happen again + break; + } + case drawing::FillStyle_SOLID: + { + // create SvxBrushItem with fill color + xRetval = getSvxBrushItemForSolid(rSourceSet, bSearchInParents, nBackgroundID); + break; + } + case drawing::FillStyle_GRADIENT: + { + // cannot be directly supported, but do the best possible + const XGradient aXGradient(rSourceSet.Get(XATTR_FILLGRADIENT).GetGradientValue()); + const basegfx::BColor aStartColor(aXGradient.GetStartColor().getBColor() * (aXGradient.GetStartIntens() * 0.01)); + const basegfx::BColor aEndColor(aXGradient.GetEndColor().getBColor() * (aXGradient.GetEndIntens() * 0.01)); + + // use half/half mixed color from gradient start and end + Color aMixedColor((aStartColor + aEndColor) * 0.5); + + // get evtl. mixed transparence + const sal_uInt16 nFillTransparence(getTransparenceForSvxBrushItem(rSourceSet, bSearchInParents)); + + if(0 != nFillTransparence) + { + // #i125189# nFillTransparence is in range [0..100] and needs to be in [0..254] unsigned + // It is necessary to use the maximum of 0xfe for transparence for the SvxBrushItem + // since the oxff value is used for special purposes (like no fill and derive from parent) + const sal_uInt8 aTargetTrans(std::min(sal_uInt8(0xfe), static_cast< sal_uInt8 >((nFillTransparence * 254) / 100))); + + aMixedColor.SetAlpha(255 - aTargetTrans); + } + + xRetval = std::make_unique<SvxBrushItem>(aMixedColor, nBackgroundID); + break; + } + case drawing::FillStyle_HATCH: + { + // cannot be directly supported, but do the best possible + const XHatch& rHatch(rSourceSet.Get(XATTR_FILLHATCH).GetHatchValue()); + const bool bFillBackground(rSourceSet.Get(XATTR_FILLBACKGROUND).GetValue()); + + if(bFillBackground) + { + // hatch is background-filled, use FillColor as if drawing::FillStyle_SOLID + xRetval = getSvxBrushItemForSolid(rSourceSet, bSearchInParents, nBackgroundID); + } + else + { + // hatch is not background-filled and using hatch color would be too dark; compensate + // somewhat by making it more transparent + Color aHatchColor(rHatch.GetColor()); + + // get evtl. mixed transparence + sal_uInt16 nFillTransparence(getTransparenceForSvxBrushItem(rSourceSet, bSearchInParents)); + + // take half orig transparence, add half transparent, clamp result + nFillTransparence = std::clamp(static_cast<sal_uInt16>((nFillTransparence / 2) + 50), sal_uInt16(0), sal_uInt16(255)); + + // #i125189# nFillTransparence is in range [0..100] and needs to be in [0..254] unsigned + // It is necessary to use the maximum of 0xfe for transparence for the SvxBrushItem + // since the oxff value is used for special purposes (like no fill and derive from parent) + const sal_uInt8 aTargetTrans(std::min(sal_uInt8(0xfe), static_cast< sal_uInt8 >((nFillTransparence * 254) / 100))); + + aHatchColor.SetAlpha(255 - aTargetTrans); + xRetval = std::make_unique<SvxBrushItem>(aHatchColor, nBackgroundID); + } + + break; + } + case drawing::FillStyle_BITMAP: + { + // create SvxBrushItem with bitmap info and flags + const XFillBitmapItem& rBmpItm = rSourceSet.Get(XATTR_FILLBITMAP, bSearchInParents); + const Graphic aGraphic(rBmpItm.GetGraphicObject().GetGraphic()); + + // continue independent of evtl. GraphicType::NONE as aGraphic.GetType(), we still need to rescue positions + SvxGraphicPosition aSvxGraphicPosition(GPOS_NONE); + const XFillBmpStretchItem& rStretchItem = rSourceSet.Get(XATTR_FILLBMP_STRETCH, bSearchInParents); + const XFillBmpTileItem& rTileItem = rSourceSet.Get(XATTR_FILLBMP_TILE, bSearchInParents); + + if(rTileItem.GetValue()) + { + aSvxGraphicPosition = GPOS_TILED; + } + else if(rStretchItem.GetValue()) + { + aSvxGraphicPosition = GPOS_AREA; + } + else + { + const XFillBmpPosItem& rPosItem = rSourceSet.Get(XATTR_FILLBMP_POS, bSearchInParents); + + switch(rPosItem.GetValue()) + { + case RectPoint::LT: aSvxGraphicPosition = GPOS_LT; break; + case RectPoint::MT: aSvxGraphicPosition = GPOS_MT; break; + case RectPoint::RT: aSvxGraphicPosition = GPOS_RT; break; + case RectPoint::LM: aSvxGraphicPosition = GPOS_LM; break; + case RectPoint::MM: aSvxGraphicPosition = GPOS_MM; break; + case RectPoint::RM: aSvxGraphicPosition = GPOS_RM; break; + case RectPoint::LB: aSvxGraphicPosition = GPOS_LB; break; + case RectPoint::MB: aSvxGraphicPosition = GPOS_MB; break; + case RectPoint::RB: aSvxGraphicPosition = GPOS_RB; break; + } + } + + // create with given graphic and position + xRetval = std::make_unique<SvxBrushItem>(aGraphic, aSvxGraphicPosition, nBackgroundID); + + // get evtl. mixed transparence + const sal_uInt16 nFillTransparence(getTransparenceForSvxBrushItem(rSourceSet, bSearchInParents)); + + if(0 != nFillTransparence) + { + // #i125189# nFillTransparence is in range [0..100] and needs to be in [0..100] signed + xRetval->setGraphicTransparency(static_cast< sal_Int8 >(nFillTransparence)); + } + + break; + } + default: + xRetval = std::make_unique<SvxBrushItem>(nBackgroundID); + break; + } + + return xRetval; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unobtabl.cxx b/svx/source/unodraw/unobtabl.cxx new file mode 100644 index 000000000..bba7bdbff --- /dev/null +++ b/svx/source/unodraw/unobtabl.cxx @@ -0,0 +1,102 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/xit.hxx> +#include "UnoNameItemTable.hxx" + +#include <svx/xbtmpit.hxx> +#include <svx/svdmodel.hxx> +#include <svx/unomid.hxx> +#include <svx/unofill.hxx> +#include <com/sun/star/awt/XBitmap.hpp> + +using namespace ::com::sun::star; +using namespace ::cppu; + +namespace { + +class SvxUnoBitmapTable : public SvxUnoNameItemTable +{ +public: + explicit SvxUnoBitmapTable( SdrModel* pModel ) noexcept; + + virtual NameOrIndex* createItem() const override; + virtual bool isValid( const NameOrIndex* pItem ) const override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType( ) override; +}; + +} + +SvxUnoBitmapTable::SvxUnoBitmapTable( SdrModel* pModel ) noexcept +: SvxUnoNameItemTable( pModel, XATTR_FILLBITMAP, MID_BITMAP ) +{ +} + +bool SvxUnoBitmapTable::isValid( const NameOrIndex* pItem ) const +{ + if( SvxUnoNameItemTable::isValid( pItem ) ) + { + const XFillBitmapItem* pBitmapItem = dynamic_cast< const XFillBitmapItem* >( pItem ); + if( pBitmapItem ) + { + const Graphic& rGraphic = pBitmapItem->GetGraphicObject().GetGraphic(); + + return rGraphic.GetSizeBytes() > 0; + } + } + + return false; +} + +OUString SAL_CALL SvxUnoBitmapTable::getImplementationName() +{ + return "SvxUnoBitmapTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoBitmapTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.BitmapTable" }; +} + +NameOrIndex* SvxUnoBitmapTable::createItem() const +{ + return new XFillBitmapItem(); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoBitmapTable::getElementType( ) +{ + return ::cppu::UnoType<awt::XBitmap>::get(); +} + +/** + * Create a bitmaptable + */ +uno::Reference< uno::XInterface > SvxUnoBitmapTable_createInstance( SdrModel* pModel ) +{ + return *new SvxUnoBitmapTable(pModel); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoctabl.cxx b/svx/source/unodraw/unoctabl.cxx new file mode 100644 index 000000000..1d50a7c32 --- /dev/null +++ b/svx/source/unodraw/unoctabl.cxx @@ -0,0 +1,181 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <unotools/pathoptions.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <rtl/ref.hxx> +#include <svx/xtable.hxx> + +using namespace ::com::sun::star; + +namespace { + +class SvxUnoColorTable : public cppu::WeakImplHelper< container::XNameContainer, lang::XServiceInfo > +{ +private: + XColorListRef pList; + +public: + SvxUnoColorTable(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override; + virtual void SAL_CALL removeByName( const OUString& Name ) override; + + // XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override; + + // XNameAccess + virtual uno::Any SAL_CALL getByName( const OUString& aName ) override; + + virtual uno::Sequence< OUString > SAL_CALL getElementNames() override; + + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; + virtual sal_Bool SAL_CALL hasElements() override; +}; + +SvxUnoColorTable::SvxUnoColorTable() + : pList(XPropertyList::AsColorList( + XPropertyList::CreatePropertyList( + XPropertyListType::Color, SvtPathOptions().GetPalettePath(), ""))) +{ +} + +sal_Bool SAL_CALL SvxUnoColorTable::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +OUString SAL_CALL SvxUnoColorTable::getImplementationName() +{ + return "com.sun.star.drawing.SvxUnoColorTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoColorTable::getSupportedServiceNames() +{ + uno::Sequence<OUString> aSNS { "com.sun.star.drawing.ColorTable" }; + return aSNS; +} + +// XNameContainer +void SAL_CALL SvxUnoColorTable::insertByName( const OUString& aName, const uno::Any& aElement ) +{ + if( hasByName( aName ) ) + throw container::ElementExistException(); + + Color aColor; + if( !(aElement >>= aColor) ) + throw lang::IllegalArgumentException(); + + if( pList.is() ) + { + pList->Insert(std::make_unique<XColorEntry>(aColor, aName)); + } +} + +void SAL_CALL SvxUnoColorTable::removeByName( const OUString& Name ) +{ + tools::Long nIndex = pList.is() ? pList->GetIndex( Name ) : -1; + if( nIndex == -1 ) + throw container::NoSuchElementException(); + + pList->Remove( nIndex ); +} + +// XNameReplace +void SAL_CALL SvxUnoColorTable::replaceByName( const OUString& aName, const uno::Any& aElement ) +{ + Color nColor; + if( !(aElement >>= nColor) ) + throw lang::IllegalArgumentException(); + + tools::Long nIndex = pList.is() ? pList->GetIndex( aName ) : -1; + if( nIndex == -1 ) + throw container::NoSuchElementException(); + + pList->Replace(nIndex, std::make_unique<XColorEntry>(nColor, aName )); +} + +// XNameAccess +uno::Any SAL_CALL SvxUnoColorTable::getByName( const OUString& aName ) +{ + tools::Long nIndex = pList.is() ? pList->GetIndex( aName ) : -1; + if( nIndex == -1 ) + throw container::NoSuchElementException(); + + const XColorEntry* pEntry = pList->GetColor(nIndex); + return uno::Any( static_cast<sal_Int32>(pEntry->GetColor().GetRGBColor()) ); +} + +uno::Sequence< OUString > SAL_CALL SvxUnoColorTable::getElementNames() +{ + const tools::Long nCount = pList.is() ? pList->Count() : 0; + + uno::Sequence< OUString > aSeq( nCount ); + OUString* pStrings = aSeq.getArray(); + + for( tools::Long nIndex = 0; nIndex < nCount; nIndex++ ) + { + const XColorEntry* pEntry = pList->GetColor(nIndex); + pStrings[nIndex] = pEntry->GetName(); + } + + return aSeq; +} + +sal_Bool SAL_CALL SvxUnoColorTable::hasByName( const OUString& aName ) +{ + tools::Long nIndex = pList.is() ? pList->GetIndex( aName ) : -1; + return nIndex != -1; +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoColorTable::getElementType() +{ + return ::cppu::UnoType<sal_Int32>::get(); +} + +sal_Bool SAL_CALL SvxUnoColorTable::hasElements() +{ + return pList.is() && pList->Count() != 0; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_drawing_SvxUnoColorTable_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SvxUnoColorTable); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unodtabl.cxx b/svx/source/unodraw/unodtabl.cxx new file mode 100644 index 000000000..c460bbd7c --- /dev/null +++ b/svx/source/unodraw/unodtabl.cxx @@ -0,0 +1,83 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/drawing/LineDash.hpp> + +#include "UnoNameItemTable.hxx" +#include <svx/xlndsit.hxx> +#include <svx/unomid.hxx> + +#include <svx/svdmodel.hxx> +#include <svx/unofill.hxx> + +using namespace ::com::sun::star; +using namespace ::cppu; + +namespace +{ +class SvxUnoDashTable : public SvxUnoNameItemTable +{ +public: + explicit SvxUnoDashTable(SdrModel* pModel) noexcept; + + virtual NameOrIndex* createItem() const override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; +}; +} + +SvxUnoDashTable::SvxUnoDashTable(SdrModel* pModel) noexcept + : SvxUnoNameItemTable(pModel, XATTR_LINEDASH, MID_LINEDASH) +{ +} + +OUString SAL_CALL SvxUnoDashTable::getImplementationName() { return "SvxUnoDashTable"; } + +uno::Sequence<OUString> SAL_CALL SvxUnoDashTable::getSupportedServiceNames() +{ + return { "com.sun.star.drawing.DashTable" }; +} + +NameOrIndex* SvxUnoDashTable::createItem() const +{ + XLineDashItem* pNewItem = new XLineDashItem(); + pNewItem->SetWhich(XATTR_LINEDASH); // set which id for pooling + return pNewItem; +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoDashTable::getElementType() +{ + return cppu::UnoType<drawing::LineDash>::get(); +} + +/** + * Create a gradienttable + */ +uno::Reference<uno::XInterface> SvxUnoDashTable_createInstance(SdrModel* pModel) +{ + return *new SvxUnoDashTable(pModel); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unogtabl.cxx b/svx/source/unodraw/unogtabl.cxx new file mode 100644 index 000000000..7939ccfd0 --- /dev/null +++ b/svx/source/unodraw/unogtabl.cxx @@ -0,0 +1,79 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/awt/Gradient.hpp> +#include "UnoNameItemTable.hxx" + +#include <svx/svdmodel.hxx> +#include <svx/xdef.hxx> +#include <svx/xflgrit.hxx> +#include <svx/unofill.hxx> +#include <svx/unomid.hxx> + +using namespace ::com::sun::star; +using namespace ::cppu; + +namespace +{ +class SvxUnoGradientTable : public SvxUnoNameItemTable +{ +public: + explicit SvxUnoGradientTable(SdrModel* pModel) noexcept; + + virtual NameOrIndex* createItem() const override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; +}; +} + +SvxUnoGradientTable::SvxUnoGradientTable(SdrModel* pModel) noexcept + : SvxUnoNameItemTable(pModel, XATTR_FILLGRADIENT, MID_FILLGRADIENT) +{ +} + +OUString SAL_CALL SvxUnoGradientTable::getImplementationName() { return "SvxUnoGradientTable"; } + +uno::Sequence<OUString> SAL_CALL SvxUnoGradientTable::getSupportedServiceNames() +{ + return { "com.sun.star.drawing.GradientTable" }; +} + +// XNameContainer +NameOrIndex* SvxUnoGradientTable::createItem() const { return new XFillGradientItem(); } + +// XElementAccess +uno::Type SAL_CALL SvxUnoGradientTable::getElementType() +{ + return cppu::UnoType<awt::Gradient>::get(); +} + +/** + * Create a gradienttable + */ +uno::Reference<uno::XInterface> SvxUnoGradientTable_createInstance(SdrModel* pModel) +{ + return *new SvxUnoGradientTable(pModel); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unohtabl.cxx b/svx/source/unodraw/unohtabl.cxx new file mode 100644 index 000000000..cb36192bd --- /dev/null +++ b/svx/source/unodraw/unohtabl.cxx @@ -0,0 +1,86 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/drawing/Hatch.hpp> +#include "UnoNameItemTable.hxx" + +#include <svx/svdmodel.hxx> +#include <svx/xdef.hxx> +#include <svx/xflhtit.hxx> +#include <svx/unomid.hxx> +#include <svx/unofill.hxx> + +using namespace ::com::sun::star; +using namespace ::cppu; + +namespace { + +class SvxUnoHatchTable : public SvxUnoNameItemTable +{ +public: + explicit SvxUnoHatchTable( SdrModel* pModel ) noexcept; + + virtual NameOrIndex* createItem() const override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType( ) override; +}; + +} + +SvxUnoHatchTable::SvxUnoHatchTable( SdrModel* pModel ) noexcept +: SvxUnoNameItemTable( pModel, XATTR_FILLHATCH, MID_FILLHATCH ) +{ +} + +OUString SAL_CALL SvxUnoHatchTable::getImplementationName() +{ + return "SvxUnoHatchTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoHatchTable::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.HatchTable" }; +} + +NameOrIndex* SvxUnoHatchTable::createItem() const +{ + return new XFillHatchItem(); +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoHatchTable::getElementType( ) +{ + return cppu::UnoType<drawing::Hatch>::get(); +} + +/** + * Create a hatchtable + */ +uno::Reference< uno::XInterface > SvxUnoHatchTable_createInstance( SdrModel* pModel ) +{ + return *new SvxUnoHatchTable(pModel); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unomlstr.cxx b/svx/source/unodraw/unomlstr.cxx new file mode 100644 index 000000000..781b3dc38 --- /dev/null +++ b/svx/source/unodraw/unomlstr.cxx @@ -0,0 +1,60 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/svdobj.hxx> +#include <vcl/svapp.hxx> + +#include <unomlstr.hxx> + +using namespace ::com::sun::star; + +SvxUnoShapeModifyListener::SvxUnoShapeModifyListener( SdrObject* pObj ) noexcept +{ + mpObj = pObj; +} + +SvxUnoShapeModifyListener::~SvxUnoShapeModifyListener() noexcept +{ +} + +// css::util::XModifyListener +void SAL_CALL SvxUnoShapeModifyListener::modified(const lang::EventObject& ) +{ + SolarMutexGuard aGuard; + if( mpObj ) + { + mpObj->SetChanged(); + mpObj->BroadcastObjectChange(); + } +} + +// css::lang::XEventListener +void SvxUnoShapeModifyListener::disposing(const lang::EventObject& ) +{ + invalidate(); +} + +// internal +void SvxUnoShapeModifyListener::invalidate() noexcept +{ + mpObj = nullptr; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unomod.cxx b/svx/source/unodraw/unomod.cxx new file mode 100644 index 000000000..b36eb09a5 --- /dev/null +++ b/svx/source/unodraw/unomod.cxx @@ -0,0 +1,670 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <vcl/svapp.hxx> +#include <svl/itempool.hxx> +#include <svtools/unoevent.hxx> +#include <comphelper/sequence.hxx> +#include <o3tl/string_view.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <cppuhelper/implbase.hxx> +#include <svx/unofill.hxx> +#include <editeng/unonrule.hxx> +#include <svtools/unoimap.hxx> +#include <sfx2/event.hxx> +#include <svx/fmdpage.hxx> +#include <svx/fmmodel.hxx> +#include <svx/fmpage.hxx> +#include <svx/unoapi.hxx> + +#include <svx/svdmodel.hxx> +#include <svx/unoprov.hxx> +#include <svx/unopage.hxx> +#include <editeng/unofield.hxx> +#include <svx/unomod.hxx> +#include <svx/unomodel.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/SvxXTextColumns.hxx> +#include <svx/unoshape.hxx> +#include <svx/xmlgrhlp.hxx> + +#include <com/sun/star/text/textfield/Type.hpp> + +//- + +using namespace ::com::sun::star; + +//- + +#define QUERYINT( xint ) \ + if( rType == cppu::UnoType<xint>::get() ) \ + aAny <<= uno::Reference< xint >(this) + +//- + +class SvxUnoDrawPagesAccess : public ::cppu::WeakImplHelper< css::drawing::XDrawPages, css::lang::XServiceInfo > +{ +private: + SvxUnoDrawingModel& mrModel; + +public: + explicit SvxUnoDrawPagesAccess( SvxUnoDrawingModel& rMyModel ) noexcept; + + // XDrawPages + virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL insertNewByIndex( sal_Int32 nIndex ) override; + virtual void SAL_CALL remove( const css::uno::Reference< css::drawing::XDrawPage >& xPage ) override; + + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount() override ; + virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override; + + // XElementAccess + virtual css::uno::Type SAL_CALL getElementType() override; + virtual sal_Bool SAL_CALL hasElements() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; +//- + +static const SvEventDescription* ImplGetSupportedMacroItems() +{ + static const SvEventDescription aMacroDescriptionsImpl[] = + { + { SvMacroItemId::OnMouseOver, "OnMouseOver" }, + { SvMacroItemId::OnMouseOut, "OnMouseOut" }, + { SvMacroItemId::NONE, nullptr } + }; + + return aMacroDescriptionsImpl; +} + +//- + +/** fills the given EventObject from the given SdrHint. + @returns + true if the SdrHint could be translated to an EventObject<br> + false if not +*/ +bool SvxUnoDrawMSFactory::createEvent( const SdrModel* pDoc, const SdrHint* pSdrHint, css::document::EventObject& aEvent ) +{ + const SdrObject* pObj = nullptr; + const SdrPage* pPage = nullptr; + + switch( pSdrHint->GetKind() ) + { +// case SdrHintKind::LayerChange: // layer definition changed +// case SdrHintKind::LayerOrderChange: // layer order changed (Insert/Remove/ChangePos) +// case HINT_LAYERSETCHG: // layer set changed +// case HINT_LAYERSETORDERCHG: // layer set order changed (Insert/Remove/ChangePos) + +// case HINT_PAGECHG: // page changed +// aEvent.EventName = "PageModified"; +// pPage = pSdrHint->GetPage(); +// break; + case SdrHintKind::PageOrderChange: // draw or master page order changed (Insert/Remove/ChangePos) + aEvent.EventName = "PageOrderModified"; + pPage = pSdrHint->GetPage(); + break; + case SdrHintKind::ObjectChange: // object changed + aEvent.EventName = "ShapeModified"; + pObj = pSdrHint->GetObject(); + break; + case SdrHintKind::ObjectInserted: // add new draw object + aEvent.EventName = "ShapeInserted"; + pObj = pSdrHint->GetObject(); + break; + case SdrHintKind::ObjectRemoved: // removed draw object from list + aEvent.EventName = "ShapeRemoved"; + pObj = pSdrHint->GetObject(); + break; +// SdrHintKind::DefaultTabChange, // default tab width changed +// SdrHintKind::SwitchToPage, // #94278# UNDO/REDO at an object evtl. on another page +// HINT_OBJLISTCLEAR // Is called before an SdrObjList will be cleared + default: + return false; + } + + if( pObj ) + aEvent.Source = const_cast<SdrObject*>(pObj)->getUnoShape(); + else if( pPage ) + aEvent.Source = const_cast<SdrPage*>(pPage)->getUnoPage(); + else + aEvent.Source = const_cast<SdrModel*>(pDoc)->getUnoModel(); + + return true; +} + +namespace { + +css::uno::Reference<css::uno::XInterface> create( + OUString const & rServiceSpecifier, OUString const & referer) +{ + if( rServiceSpecifier.startsWith("com.sun.star.drawing.") ) + { + std::optional<SdrObjKind> nType = UHashMap::getId( rServiceSpecifier ); + if( nType ) + { + SdrInventor nI = IsInventorE3D(*nType) ? SdrInventor::E3d : SdrInventor::Default; + + return uno::Reference< uno::XInterface >( static_cast<drawing::XShape*>(SvxDrawPage::CreateShapeByTypeAndInventor( *nType, nI, nullptr, nullptr, referer ).get()) ); + } + } + else if (rServiceSpecifier == "com.sun.star.document.ImportGraphicStorageHandler") + { + rtl::Reference<SvXMLGraphicHelper> pGraphicHelper = SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode::Read ); + uno::Reference< uno::XInterface> xRet( static_cast< ::cppu::OWeakObject* >( pGraphicHelper.get() ) ); + return xRet; + } + else if (rServiceSpecifier == "com.sun.star.text.TextColumns") + { + return SvxXTextColumns_createInstance(); + } + + uno::Reference< uno::XInterface > xRet( SvxUnoDrawMSFactory::createTextField( rServiceSpecifier ) ); + if( !xRet.is() ) + throw lang::ServiceNotRegisteredException("unknown service: " + rServiceSpecifier); + + return xRet; +} + +} + +uno::Reference< uno::XInterface > SAL_CALL SvxUnoDrawMSFactory::createInstance( const OUString& rServiceSpecifier ) +{ + return create(rServiceSpecifier, ""); +} + +uno::Reference< uno::XInterface > SvxUnoDrawMSFactory::createTextField( std::u16string_view ServiceSpecifier ) +{ + return SvxUnoTextCreateTextField( ServiceSpecifier ); +} + +uno::Reference< uno::XInterface > SAL_CALL SvxUnoDrawMSFactory::createInstanceWithArguments( const OUString& ServiceSpecifier, const uno::Sequence< css::uno::Any >& Arguments ) +{ + OUString arg; + if ((ServiceSpecifier == "com.sun.star.drawing.GraphicObjectShape" + || ServiceSpecifier == "com.sun.star.drawing.MediaShape") + && Arguments.getLength() == 1 && (Arguments[0] >>= arg)) + { + return create(ServiceSpecifier, arg); + } + throw lang::NoSupportException(); +} + +uno::Sequence< OUString > SAL_CALL SvxUnoDrawMSFactory::getAvailableServiceNames() +{ + return UHashMap::getServiceNames(); +} + +SdrModel& SvxUnoDrawingModel::getSdrModelFromUnoModel() const +{ + OSL_ENSURE(mpDoc, "No SdrModel in UnoDrawingModel, should not happen"); + return *mpDoc; +} + +SvxUnoDrawingModel::SvxUnoDrawingModel(SdrModel* pDoc) noexcept +: SfxBaseModel(nullptr), + mpDoc(pDoc) +{ +} + +SvxUnoDrawingModel::~SvxUnoDrawingModel() noexcept +{ +} + +uno::Any SAL_CALL SvxUnoDrawingModel::queryInterface( const uno::Type & rType ) +{ + uno::Any aAny; + + QUERYINT(lang::XServiceInfo); + else QUERYINT(lang::XMultiServiceFactory); + else QUERYINT(drawing::XDrawPagesSupplier); + else QUERYINT(css::ucb::XAnyCompareFactory); + else + return SfxBaseModel::queryInterface( rType ); + + return aAny; +} + +// XTypeProvider +uno::Sequence< uno::Type > SAL_CALL SvxUnoDrawingModel::getTypes( ) +{ + if( !maTypeSequence.hasElements() ) + { + maTypeSequence = comphelper::concatSequences( SfxBaseModel::getTypes(), + uno::Sequence { + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XMultiServiceFactory>::get(), + cppu::UnoType<drawing::XDrawPagesSupplier>::get(), + cppu::UnoType<css::ucb::XAnyCompareFactory>::get() }); + } + return maTypeSequence; +} + +uno::Sequence< sal_Int8 > SAL_CALL SvxUnoDrawingModel::getImplementationId( ) +{ + return css::uno::Sequence<sal_Int8>(); +} + +void SAL_CALL SvxUnoDrawingModel::lockControllers( ) +{ + if( mpDoc ) + mpDoc->setLock(true); +} + +void SAL_CALL SvxUnoDrawingModel::unlockControllers( ) +{ + if( mpDoc && mpDoc->isLocked() ) + { + mpDoc->setLock(false); + } +} + +sal_Bool SAL_CALL SvxUnoDrawingModel::hasControllersLocked( ) +{ + return mpDoc && mpDoc->isLocked(); +} + +// XDrawPagesSupplier +uno::Reference< drawing::XDrawPages > SAL_CALL SvxUnoDrawingModel::getDrawPages() +{ + ::SolarMutexGuard aGuard; + + uno::Reference< drawing::XDrawPages > xDrawPages( mxDrawPagesAccess ); + + if( !xDrawPages.is() ) + mxDrawPagesAccess = xDrawPages = new SvxUnoDrawPagesAccess(*this); + + return xDrawPages; +} + +// XMultiServiceFactory ( SvxFmMSFactory ) +uno::Reference< uno::XInterface > SAL_CALL SvxUnoDrawingModel::createInstance( const OUString& aServiceSpecifier ) +{ + ::SolarMutexGuard aGuard; + + if( aServiceSpecifier == "com.sun.star.drawing.DashTable" ) + { + if( !mxDashTable.is() ) + mxDashTable = SvxUnoDashTable_createInstance( mpDoc ); + return mxDashTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.GradientTable" ) + { + if( !mxGradientTable.is() ) + mxGradientTable = SvxUnoGradientTable_createInstance( mpDoc ); + return mxGradientTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.HatchTable" ) + { + if( !mxHatchTable.is() ) + mxHatchTable = SvxUnoHatchTable_createInstance( mpDoc ); + return mxHatchTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" ) + { + if( !mxBitmapTable.is() ) + mxBitmapTable = SvxUnoBitmapTable_createInstance( mpDoc ); + return mxBitmapTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" ) + { + if( !mxTransGradientTable.is() ) + mxTransGradientTable = SvxUnoTransGradientTable_createInstance( mpDoc ); + return mxTransGradientTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" ) + { + if( !mxMarkerTable.is() ) + mxMarkerTable = SvxUnoMarkerTable_createInstance( mpDoc ); + return mxMarkerTable; + } + if( aServiceSpecifier == "com.sun.star.text.NumberingRules" ) + { + return uno::Reference< uno::XInterface >( SvxCreateNumRule( mpDoc ), uno::UNO_QUERY ); + } + + if ( aServiceSpecifier == "com.sun.star.image.ImageMapRectangleObject" ) + { + return SvUnoImageMapRectangleObject_createInstance( ImplGetSupportedMacroItems() ); + } + + if ( aServiceSpecifier == "com.sun.star.image.ImageMapCircleObject" ) + { + return SvUnoImageMapCircleObject_createInstance( ImplGetSupportedMacroItems() ); + } + + if ( aServiceSpecifier == "com.sun.star.image.ImageMapPolygonObject" ) + { + return SvUnoImageMapPolygonObject_createInstance( ImplGetSupportedMacroItems() ); + } + + if( aServiceSpecifier == "com.sun.star.text.TextField.DateTime" ) + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField(text::textfield::Type::DATE)); + } + + uno::Reference< uno::XInterface > xRet; + + static const OUStringLiteral aPackagePrefix( u"com.sun.star.presentation." ); + if( aServiceSpecifier.startsWith( aPackagePrefix ) ) + { + SvxShape* pShape = nullptr; + + SdrObjKind nType = SdrObjKind::Text; + std::u16string_view aTypeName = aServiceSpecifier.subView( aPackagePrefix.getLength() ); + // create a shape wrapper + if( o3tl::starts_with(aTypeName, u"TitleTextShape") ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"OutlinerShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"SubtitleShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"GraphicObjectShape" ) ) + { + nType = SdrObjKind::Graphic; + } + else if( o3tl::starts_with(aTypeName, u"PageShape" ) ) + { + nType = SdrObjKind::Page; + } + else if( o3tl::starts_with(aTypeName, u"OLE2Shape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aTypeName, u"ChartShape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aTypeName, u"OrgChartShape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aTypeName, u"NotesShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"HandoutShape" ) ) + { + nType = SdrObjKind::Page; + } + else if( o3tl::starts_with(aTypeName, u"FooterShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"HeaderShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"SlideNumberShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"DateTimeShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aTypeName, u"TableShape" ) ) + { + nType = SdrObjKind::Table; + } + else + { + throw lang::ServiceNotRegisteredException(); + } + + // create the API wrapper + rtl::Reference<SvxShape> xNewShape = CreateSvxShapeByTypeAndInventor( nType, SdrInventor::Default, "" ); + pShape = xNewShape.get(); + + // set shape type + if( pShape ) + pShape->SetShapeType(aServiceSpecifier); + + xRet = static_cast<uno::XWeak*>(pShape); + } + else + { + xRet = SvxFmMSFactory::createInstance( aServiceSpecifier ); + } + + return xRet; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoDrawingModel::getAvailableServiceNames() +{ + const uno::Sequence< OUString > aSNS_ORG( SvxFmMSFactory::getAvailableServiceNames() ); + + uno::Sequence< OUString > aSNS{ + "com.sun.star.drawing.DashTable", + "com.sun.star.drawing.GradientTable", + "com.sun.star.drawing.HatchTable", + "com.sun.star.drawing.BitmapTable", + "com.sun.star.drawing.TransparencyGradientTable", + "com.sun.star.drawing.MarkerTable", + "com.sun.star.text.NumberingRules", + "com.sun.star.image.ImageMapRectangleObject", + "com.sun.star.image.ImageMapCircleObject", + "com.sun.star.image.ImageMapPolygonObject", + + "com.sun.star.presentation.TitleTextShape", + "com.sun.star.presentation.OutlinerShape", + "com.sun.star.presentation.SubtitleShape", + "com.sun.star.presentation.GraphicObjectShape", + "com.sun.star.presentation.ChartShape", + "com.sun.star.presentation.PageShape", + "com.sun.star.presentation.OLE2Shape", + "com.sun.star.presentation.TableShape", + "com.sun.star.presentation.OrgChartShape", + "com.sun.star.presentation.NotesShape", + "com.sun.star.presentation.HandoutShape" + }; + + return comphelper::concatSequences( aSNS_ORG, aSNS ); +} + +// lang::XServiceInfo +OUString SAL_CALL SvxUnoDrawingModel::getImplementationName() +{ + return "SvxUnoDrawingModel"; +} + +sal_Bool SAL_CALL SvxUnoDrawingModel::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +uno::Sequence< OUString > SAL_CALL SvxUnoDrawingModel::getSupportedServiceNames() +{ + return { "com.sun.star.drawing.DrawingDocument" }; +} + +// XAnyCompareFactory +uno::Reference< css::ucb::XAnyCompare > SAL_CALL SvxUnoDrawingModel::createAnyCompareByName( const OUString& ) +{ + return SvxCreateNumRuleCompare(); +} + +SvxUnoDrawPagesAccess::SvxUnoDrawPagesAccess( SvxUnoDrawingModel& rMyModel ) noexcept +: mrModel(rMyModel) +{ +} + +// XIndexAccess +sal_Int32 SAL_CALL SvxUnoDrawPagesAccess::getCount() +{ + ::SolarMutexGuard aGuard; + + sal_Int32 nCount = 0; + + if( mrModel.mpDoc ) + nCount = mrModel.mpDoc->GetPageCount(); + + return nCount; +} + +uno::Any SAL_CALL SvxUnoDrawPagesAccess::getByIndex( sal_Int32 Index ) +{ + ::SolarMutexGuard aGuard; + + uno::Any aAny; + + if( mrModel.mpDoc ) + { + if( (Index < 0) || (Index >= mrModel.mpDoc->GetPageCount() ) ) + throw lang::IndexOutOfBoundsException(); + + SdrPage* pPage = mrModel.mpDoc->GetPage( static_cast<sal_uInt16>(Index) ); + if( pPage ) + { + uno::Reference< uno::XInterface > xPage( pPage->mxUnoPage ); + + if( !xPage.is() ) + { + if( dynamic_cast<FmFormModel*>( mrModel.mpDoc ) ) + xPage = static_cast<drawing::XDrawPage*>(new SvxFmDrawPage( pPage )); + else + xPage = static_cast<drawing::XDrawPage*>(new SvxDrawPage( pPage )); + + pPage->mxUnoPage = xPage; + } + + aAny <<= xPage; + } + } + return aAny; +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoDrawPagesAccess::getElementType() +{ + return cppu::UnoType<drawing::XDrawPage>::get(); +} + +sal_Bool SAL_CALL SvxUnoDrawPagesAccess::hasElements() +{ + return getCount() > 0; +} + +// XDrawPages + +// create a new page with model at given position +// and return corresponding SdDrawPage +uno::Reference< drawing::XDrawPage > SAL_CALL SvxUnoDrawPagesAccess::insertNewByIndex( sal_Int32 nIndex ) +{ + ::SolarMutexGuard aGuard; + + uno::Reference< drawing::XDrawPage > xDrawPage; + + if( mrModel.mpDoc ) + { + rtl::Reference<SdrPage> pPage; + + if( auto pFormModel = dynamic_cast<FmFormModel*>( mrModel.mpDoc ) ) + pPage = new FmFormPage(*pFormModel); + else + pPage = new SdrPage(*mrModel.mpDoc); + + mrModel.mpDoc->InsertPage( pPage.get(), static_cast<sal_uInt16>(nIndex) ); + xDrawPage.set( pPage->getUnoPage(), uno::UNO_QUERY ); + } + + return xDrawPage; +} + +void SAL_CALL SvxUnoDrawPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage ) +{ + ::SolarMutexGuard aGuard; + + sal_uInt16 nPageCount = mrModel.mpDoc->GetPageCount(); + if( nPageCount <= 1 ) + return; + + // get pPage from xPage and get Id (nPos) + SvxDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage ); + if( pSvxPage ) + { + SdrPage* pPage = pSvxPage->GetSdrPage(); + if(pPage) + { + sal_uInt16 nPage = pPage->GetPageNum(); + mrModel.mpDoc->DeletePage( nPage ); + } + } +} + +// XServiceInfo + +OUString SAL_CALL SvxUnoDrawPagesAccess::getImplementationName( ) +{ + return "SvxUnoDrawPagesAccess"; +} + +sal_Bool SAL_CALL SvxUnoDrawPagesAccess::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL SvxUnoDrawPagesAccess::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.DrawPages" }; +} + +css::uno::Reference< css::container::XIndexReplace > SvxCreateNumRule(SdrModel* pModel) +{ + const SvxNumRule* pDefaultRule = nullptr; + if( pModel ) + { + const SvxNumBulletItem* pItem = pModel->GetItemPool().GetSecondaryPool()->GetPoolDefaultItem(EE_PARA_NUMBULLET); + if( pItem ) + { + pDefaultRule = &pItem->GetNumRule(); + } + } + + if( pDefaultRule ) + { + return SvxCreateNumRule( *pDefaultRule ); + } + else + { + SvxNumRule aTempRule( SvxNumRuleFlags::NONE, 10, false ); + return SvxCreateNumRule( aTempRule ); + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unomtabl.cxx b/svx/source/unodraw/unomtabl.cxx new file mode 100644 index 000000000..60b858f38 --- /dev/null +++ b/svx/source/unodraw/unomtabl.cxx @@ -0,0 +1,423 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <memory> +#include <set> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/drawing/PointSequence.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <svl/lstner.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/svdmodel.hxx> +#include <svx/xdef.hxx> + +#include <vector> +#include <vcl/svapp.hxx> + + +#include <svx/unofill.hxx> + +#include <svx/unoapi.hxx> + +using namespace ::com::sun::star; +using namespace ::cppu; + +typedef std::vector<std::unique_ptr<SfxItemSet>> ItemPoolVector; + +namespace { + +class SvxUnoMarkerTable + : public WeakImplHelper< + util::XCancellable, + container::XNameContainer, + lang::XServiceInfo> + , public SfxListener +{ +private: + SdrModel* mpModel; + SfxItemPool* mpModelPool; + + ItemPoolVector maItemSetVector; + +public: + explicit SvxUnoMarkerTable( SdrModel* pModel ) noexcept; + virtual ~SvxUnoMarkerTable() noexcept override; + + void dispose(); + + // SfxListener + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override; + + void ImplInsertByName( const OUString& aName, const uno::Any& aElement ); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XCancellable + virtual void SAL_CALL cancel() override; + + // XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override; + virtual void SAL_CALL removeByName( const OUString& Name ) override; + + // XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override; + + // XNameAccess + virtual uno::Any SAL_CALL getByName( const OUString& aName ) override; + virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override; + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType( ) override; + virtual sal_Bool SAL_CALL hasElements( ) override; +}; + +} + +SvxUnoMarkerTable::SvxUnoMarkerTable( SdrModel* pModel ) noexcept +: mpModel( pModel ), + mpModelPool( pModel ? &pModel->GetItemPool() : nullptr ) +{ + if( pModel ) + StartListening( *pModel ); +} + +SvxUnoMarkerTable::~SvxUnoMarkerTable() noexcept +{ + SolarMutexGuard aGuard; + + if( mpModel ) + EndListening( *mpModel ); + dispose(); +} + +void SvxUnoMarkerTable::dispose() +{ + maItemSetVector.clear(); +} + +// SfxListener +void SvxUnoMarkerTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept +{ + if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint) + { + const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); + if( SdrHintKind::ModelCleared == pSdrHint->GetKind() ) + dispose(); + } +} + +sal_Bool SAL_CALL SvxUnoMarkerTable::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +OUString SAL_CALL SvxUnoMarkerTable::getImplementationName() +{ + return "SvxUnoMarkerTable"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getSupportedServiceNames( ) +{ + uno::Sequence<OUString> aSNS { "com.sun.star.drawing.MarkerTable" }; + return aSNS; +} + +void SvxUnoMarkerTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement ) +{ + maItemSetVector.push_back( + std::make_unique<SfxItemSetFixed<XATTR_LINESTART, XATTR_LINEEND>>( *mpModelPool )); + auto pInSet = maItemSetVector.back().get(); + + XLineEndItem aEndMarker(XATTR_LINEEND); + aEndMarker.SetName( aName ); + aEndMarker.PutValue( aElement, 0 ); + + pInSet->Put( aEndMarker ); + + XLineStartItem aStartMarker(XATTR_LINESTART); + aStartMarker.SetName( aName ); + aStartMarker.PutValue( aElement, 0 ); + + pInSet->Put( aStartMarker ); +} + +// XNameContainer +void SAL_CALL SvxUnoMarkerTable::insertByName( const OUString& aApiName, const uno::Any& aElement ) +{ + SolarMutexGuard aGuard; + + if( hasByName( aApiName ) ) + throw container::ElementExistException(); + + OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName); + + ImplInsertByName( aName, aElement ); +} + +void SAL_CALL SvxUnoMarkerTable::cancel() +{ + SolarMutexGuard aGuard; + // drop all items that are owned by this service and not the document + // (i.e. they are unused) + dispose(); +} + +void SAL_CALL SvxUnoMarkerTable::removeByName( const OUString& aApiName ) +{ + SolarMutexGuard aGuard; + + OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName); + + auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(), + [&aName](const std::unique_ptr<SfxItemSet>& rpItem) { + const NameOrIndex *pItem = &(rpItem->Get( XATTR_LINEEND ) ); + return pItem->GetName() == aName; + }); + if (aIter != maItemSetVector.end()) + { + maItemSetVector.erase( aIter ); + return; + } + + if( !hasByName( aName ) ) + throw container::NoSuchElementException(); +} + +// XNameReplace +void SAL_CALL SvxUnoMarkerTable::replaceByName( const OUString& aApiName, const uno::Any& aElement ) +{ + SolarMutexGuard aGuard; + + const OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName); + + auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(), + [&aName](const std::unique_ptr<SfxItemSet>& rpItem) { + const NameOrIndex *pItem = &(rpItem->Get( XATTR_LINEEND ) ); + return pItem->GetName() == aName; + }); + if (aIter != maItemSetVector.end()) + { + XLineEndItem aEndMarker(XATTR_LINEEND); + aEndMarker.SetName( aName ); + if( !aEndMarker.PutValue( aElement, 0 ) ) + throw lang::IllegalArgumentException(); + + (*aIter)->Put( aEndMarker ); + + XLineStartItem aStartMarker(XATTR_LINESTART); + aStartMarker.SetName( aName ); + aStartMarker.PutValue( aElement, 0 ); + + (*aIter)->Put( aStartMarker ); + return; + } + + // if it is not in our own sets, modify the pool! + bool bFound = false; + + if (mpModelPool) + for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINESTART)) + { + NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(p)); + if( pItem && pItem->GetName() == aName ) + { + pItem->PutValue( aElement, 0 ); + bFound = true; + break; + } + } + + if (mpModelPool) + for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINEEND)) + { + NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(p)); + if( pItem && pItem->GetName() == aName ) + { + pItem->PutValue( aElement, 0 ); + bFound = true; + break; + } + } + + if( !bFound ) + throw container::NoSuchElementException(); + + ImplInsertByName( aName, aElement ); +} + +static bool getByNameFromPool( std::u16string_view rSearchName, SfxItemPool const * pPool, sal_uInt16 nWhich, uno::Any& rAny ) +{ + if (pPool) + for (const SfxPoolItem* p : pPool->GetItemSurrogates(nWhich)) + { + const NameOrIndex *pItem = static_cast<const NameOrIndex*>(p); + + if( pItem && pItem->GetName() == rSearchName ) + { + pItem->QueryValue( rAny ); + return true; + } + } + + return false; +} + +// XNameAccess +uno::Any SAL_CALL SvxUnoMarkerTable::getByName( const OUString& aApiName ) +{ + SolarMutexGuard aGuard; + + OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName); + + uno::Any aAny; + + if (mpModelPool && !aName.isEmpty()) + { + do + { + if (getByNameFromPool(aName, mpModelPool, XATTR_LINESTART, aAny)) + break; + + if (getByNameFromPool(aName, mpModelPool, XATTR_LINEEND, aAny)) + break; + + throw container::NoSuchElementException(); + } + while(false); + } + + return aAny; +} + +static void createNamesForPool( SfxItemPool const * pPool, sal_uInt16 nWhich, std::set< OUString >& rNameSet ) +{ + for (const SfxPoolItem* p : pPool->GetItemSurrogates(nWhich)) + { + const NameOrIndex* pItem = static_cast<const NameOrIndex*>(p); + + if( pItem == nullptr || pItem->GetName().isEmpty() ) + continue; + + OUString aName = SvxUnogetApiNameForItem(XATTR_LINEEND, pItem->GetName()); + rNameSet.insert( aName ); + } +} + +uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getElementNames() +{ + SolarMutexGuard aGuard; + + std::set< OUString > aNameSet; + + // search model pool for line starts + createNamesForPool( mpModelPool, XATTR_LINESTART, aNameSet ); + + // search model pool for line ends + createNamesForPool( mpModelPool, XATTR_LINEEND, aNameSet ); + + return comphelper::containerToSequence(aNameSet); +} + +sal_Bool SAL_CALL SvxUnoMarkerTable::hasByName( const OUString& aName ) +{ + SolarMutexGuard aGuard; + + if( aName.isEmpty() ) + return false; + + OUString aSearchName; + + const NameOrIndex *pItem; + + aSearchName = SvxUnogetInternalNameForItem(XATTR_LINESTART, aName); + if (mpModelPool) + for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINESTART)) + { + pItem = static_cast<const NameOrIndex*>(p); + if( pItem && pItem->GetName() == aSearchName ) + return true; + } + + aSearchName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aName); + if (mpModelPool) + for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINEEND)) + { + pItem = static_cast<const NameOrIndex*>(p); + if( pItem && pItem->GetName() == aSearchName ) + return true; + } + + return false; +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoMarkerTable::getElementType( ) +{ + return cppu::UnoType<drawing::PointSequence>::get(); +} + +sal_Bool SAL_CALL SvxUnoMarkerTable::hasElements( ) +{ + SolarMutexGuard aGuard; + + const NameOrIndex *pItem; + + if (mpModelPool) + for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINESTART)) + { + pItem = static_cast<const NameOrIndex*>(p); + if( pItem && !pItem->GetName().isEmpty() ) + return true; + } + + if (mpModelPool) + for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINEEND)) + { + pItem = static_cast<const NameOrIndex*>(p); + if( pItem && !pItem->GetName().isEmpty() ) + return true; + } + + return false; +} + +/** + * Create a hatchtable + */ +uno::Reference< uno::XInterface > SvxUnoMarkerTable_createInstance( SdrModel* pModel ) +{ + return *new SvxUnoMarkerTable(pModel); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unopage.cxx b/svx/source/unodraw/unopage.cxx new file mode 100644 index 000000000..ee91c36c9 --- /dev/null +++ b/svx/source/unodraw/unopage.cxx @@ -0,0 +1,898 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <com/sun/star/document/EventObject.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <o3tl/safeint.hxx> +#include <osl/mutex.hxx> +#include <comphelper/classids.hxx> +#include <comphelper/embeddedobjectcontainer.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <svx/svdpool.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmodel.hxx> +#include <svx/strings.hrc> +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdundo.hxx> +#include <svx/unopage.hxx> +#include "shapeimpl.hxx" +#include <svx/unodraw/SvxTableShape.hxx> +#include <svx/dialmgr.hxx> +#include <svx/svdobjkind.hxx> +#include <svx/unoprov.hxx> +#include <svx/unoapi.hxx> +#include <extrud3d.hxx> +#include <svx/lathe3d.hxx> +#include <svx/scene3d.hxx> +#include <vcl/svapp.hxx> +#include <tools/diagnose_ex.h> +#include <tools/globname.hxx> +#include <sal/log.hxx> + +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::drawing; + +UNO3_GETIMPLEMENTATION_IMPL( SvxDrawPage ); + +SvxDrawPage::SvxDrawPage(SdrPage* pInPage) // TTTT should be reference +: mrBHelper(m_aMutex) + ,mpPage(pInPage) + ,mpModel(&pInPage->getSdrModelFromSdrPage()) // register at broadcaster + ,mpView(new SdrView(pInPage->getSdrModelFromSdrPage())) // create (hidden) view +{ + mpView->SetDesignMode(); +} + +SvxDrawPage::~SvxDrawPage() noexcept +{ + if( !mrBHelper.bDisposed ) + { + assert(!"SvxDrawPage must be disposed!"); + acquire(); + dispose(); + } +} + +// XInterface +void SvxDrawPage::release() noexcept +{ + OWeakAggObject::release(); +} + +// XComponent +void SvxDrawPage::disposing() noexcept +{ + if( mpModel ) + { + mpModel = nullptr; + } + + mpView.reset(); + mpPage = nullptr; +} + +// XComponent +void SvxDrawPage::dispose() +{ + SolarMutexGuard aSolarGuard; + + // An frequently programming error is to release the last + // reference to this object in the disposing message. + // Make it robust, hold a self Reference. + uno::Reference< lang::XComponent > xSelf( this ); + + // Guard dispose against multiple threading + // Remark: It is an error to call dispose more than once + bool bDoDispose = false; + { + osl::MutexGuard aGuard( mrBHelper.rMutex ); + if( !mrBHelper.bDisposed && !mrBHelper.bInDispose ) + { + // only one call go into this section + mrBHelper.bInDispose = true; + bDoDispose = true; + } + } + + // Do not hold the mutex because we are broadcasting + if( !bDoDispose ) + return; + + // Create an event with this as sender + try + { + uno::Reference< uno::XInterface > xSource( uno::Reference< uno::XInterface >::query( static_cast<lang::XComponent *>(this) ) ); + css::document::EventObject aEvt; + aEvt.Source = xSource; + // inform all listeners to release this object + // The listener container are automatically cleared + mrBHelper.aLC.disposeAndClear( aEvt ); + // notify subclasses to do their dispose + disposing(); + } + catch(const css::uno::Exception&) + { + // catch exception and throw again but signal that + // the object was disposed. Dispose should be called + // only once. + osl::MutexGuard aGuard( mrBHelper.rMutex ); + mrBHelper.bDisposed = true; + mrBHelper.bInDispose = false; + throw; + } + + osl::MutexGuard aGuard( mrBHelper.rMutex ); + mrBHelper.bDisposed = true; + mrBHelper.bInDispose = false; + +} + +void SAL_CALL SvxDrawPage::addEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) +{ + SolarMutexGuard aGuard; + + if( mpModel == nullptr ) + throw lang::DisposedException(); + + mrBHelper.addListener( cppu::UnoType<decltype(aListener)>::get() , aListener ); +} + +void SAL_CALL SvxDrawPage::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) +{ + SolarMutexGuard aGuard; + + if( mpModel == nullptr ) + throw lang::DisposedException(); + + mrBHelper.removeListener( cppu::UnoType<decltype(aListener)>::get() , aListener ); +} + +void SAL_CALL SvxDrawPage::add( const uno::Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + if ( ( mpModel == nullptr ) || ( mpPage == nullptr ) ) + throw lang::DisposedException(); + + SvxShape* pShape = comphelper::getFromUnoTunnel<SvxShape>( xShape ); + + if( nullptr == pShape ) + return; + + SdrObject *pObj = pShape->GetSdrObject(); + bool bNeededToClone(false); + + if(nullptr != pObj && &pObj->getSdrModelFromSdrObject() != &mpPage->getSdrModelFromSdrPage()) + { + // TTTT UNO API tries to add an existing SvxShape to this SvxDrawPage, + // but these use different SdrModels. It was possible before to completely + // 'change' a SdrObject to another SdrModel (including dangerous MigrateItemPool + // stuff), but is no longer. We need to Clone the SdrObject to the target model + // and ::Create a new SvxShape (set SdrObject there, take obver values, ...) + SdrObject* pClonedSdrShape(pObj->CloneSdrObject(mpPage->getSdrModelFromSdrPage())); + pObj->setUnoShape(nullptr); + pClonedSdrShape->setUnoShape(xShape); + // pShape->InvalidateSdrObject(); + // pShape->Create(pClonedSdrShape, this); + SdrObject::Free(pObj); + pObj = pClonedSdrShape; + bNeededToClone = true; + } + + if(!pObj) + { + pObj = CreateSdrObject( xShape ); + ENSURE_OR_RETURN_VOID( pObj != nullptr, "SvxDrawPage::add: no SdrObject was created!" ); + } + else if ( !pObj->IsInserted() ) + { + mpPage->InsertObject( pObj ); + + if(bNeededToClone) + { + // TTTT Unfortunately in SdrObject::SetPage (see there) the + // xShape/UnoShape at the newly cloned SDrObject is *removed* again, + // so re-set it here, the caller *may need it* (e.g. Writer) + uno::Reference< uno::XInterface > xShapeCheck(pObj->getWeakUnoShape()); + + if( !xShapeCheck.is() ) + { + pObj->setUnoShape(xShape); + } + } + } + + pShape->Create( pObj, this ); + OSL_ENSURE( pShape->GetSdrObject() == pObj, "SvxDrawPage::add: shape does not know about its newly created SdrObject!" ); + + if ( !pObj->IsInserted() ) + { + mpPage->InsertObject( pObj ); + } + + mpModel->SetChanged(); +} + +void SAL_CALL SvxDrawPage::addTop( const uno::Reference< drawing::XShape >& xShape ) +{ + add(xShape); +} + +void SAL_CALL SvxDrawPage::addBottom( const uno::Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + if ( ( mpModel == nullptr ) || ( mpPage == nullptr ) ) + throw lang::DisposedException(); + + SvxShape* pShape = comphelper::getFromUnoTunnel<SvxShape>( xShape ); + + if( nullptr == pShape ) + return; + + SdrObject *pObj = pShape->GetSdrObject(); + + if(!pObj) + { + pObj = CreateSdrObject( xShape, true ); + ENSURE_OR_RETURN_VOID( pObj != nullptr, "SvxDrawPage::add: no SdrObject was created!" ); + } + else if ( !pObj->IsInserted() ) + { + mpPage->InsertObject( pObj, 0 ); + } + + pShape->Create( pObj, this ); + OSL_ENSURE( pShape->GetSdrObject() == pObj, "SvxDrawPage::add: shape does not know about its newly created SdrObject!" ); + + if ( !pObj->IsInserted() ) + { + mpPage->InsertObject( pObj, 0 ); + } + + mpModel->SetChanged(); +} + +void SAL_CALL SvxDrawPage::remove( const Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + if( (mpModel == nullptr) || (mpPage == nullptr) ) + throw lang::DisposedException(); + + SdrObject* pObj = SdrObject::getSdrObjectFromXShape( xShape ); + if (!pObj) + return; + + // remove SdrObject from page + const size_t nCount = mpPage->GetObjCount(); + for( size_t nNum = 0; nNum < nCount; ++nNum ) + { + if(mpPage->GetObj(nNum) == pObj) + { + const bool bUndoEnabled = mpModel->IsUndoEnabled(); + + if (bUndoEnabled) + { + mpModel->BegUndo(SvxResId(STR_EditDelete), + pObj->TakeObjNameSingul(), SdrRepeatFunc::Delete); + + mpModel->AddUndo(mpModel->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj)); + } + + OSL_VERIFY( mpPage->RemoveObject( nNum ) == pObj ); + + if (!bUndoEnabled) + SdrObject::Free(pObj); + + if (bUndoEnabled) + mpModel->EndUndo(); + + break; + } + } + + mpModel->SetChanged(); +} + +void SvxDrawPage::sort( const css::uno::Sequence< sal_Int32 >& sortOrder ) +{ + SolarMutexGuard aGuard; + + if ((mpModel == nullptr) || (mpPage == nullptr)) + throw lang::DisposedException(); + + auto newOrder = comphelper::sequenceToContainer<std::vector<sal_Int32>>(sortOrder); + mpPage->sort(newOrder); +} + +// css::container::XIndexAccess +sal_Int32 SAL_CALL SvxDrawPage::getCount() +{ + SolarMutexGuard aGuard; + + if( (mpModel == nullptr) || (mpPage == nullptr) ) + throw lang::DisposedException(); + + return static_cast<sal_Int32>( mpPage->GetObjCount() ); +} + +uno::Any SAL_CALL SvxDrawPage::getByIndex( sal_Int32 Index ) +{ + SolarMutexGuard aGuard; + + if( (mpModel == nullptr) || (mpPage == nullptr) ) + throw lang::DisposedException("Model or Page was already disposed!"); + + if ( Index < 0 || o3tl::make_unsigned(Index) >= mpPage->GetObjCount() ) + throw lang::IndexOutOfBoundsException("Index (" + OUString::number(Index) + + ") needs to be a positive integer smaller than the shape count (" + + OUString::number(mpPage->GetObjCount()) + ")!"); + + SdrObject* pObj = mpPage->GetObj( Index ); + if( pObj == nullptr ) + throw uno::RuntimeException("Runtime exception thrown while getting a ref to the SdrObject at index: " + + OUString::number(Index)); + + + return Any(Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY )); +} + +// css::container::XElementAccess +uno::Type SAL_CALL SvxDrawPage::getElementType() +{ + return cppu::UnoType<drawing::XShape>::get(); +} + +sal_Bool SAL_CALL SvxDrawPage::hasElements() +{ + SolarMutexGuard aGuard; + + if( (mpModel == nullptr) || (mpPage == nullptr) ) + throw lang::DisposedException(); + + return mpPage && mpPage->GetObjCount()>0; +} + +namespace +{ + void lcl_markSdrObjectOfShape( const Reference< drawing::XShape >& _rxShape, SdrView& _rView, SdrPageView& _rPageView ) + { + SdrObject* pObj = SdrObject::getSdrObjectFromXShape( _rxShape ); + if ( !pObj ) + return; + + _rView.MarkObj( pObj, &_rPageView ); + } +} + +// ATTENTION: SelectObjectsInView selects the css::drawing::Shapes +// only in the given SdrPageView. It hasn't to be the visible SdrPageView. +void SvxDrawPage::SelectObjectsInView( const Reference< drawing::XShapes > & aShapes, SdrPageView* pPageView ) noexcept +{ + SAL_WARN_IF(!pPageView, "svx", "SdrPageView is NULL!"); + SAL_WARN_IF(!mpView, "svx", "SdrView is NULL!"); + + if(pPageView==nullptr || mpView==nullptr) + return; + + mpView->UnmarkAllObj( pPageView ); + + tools::Long nCount = aShapes->getCount(); + for( tools::Long i = 0; i < nCount; i++ ) + { + uno::Any aAny( aShapes->getByIndex(i) ); + Reference< drawing::XShape > xShape; + if( aAny >>= xShape ) + lcl_markSdrObjectOfShape( xShape, *mpView, *pPageView ); + } +} + +// ATTENTION: SelectObjectInView selects the shape only in the given SdrPageView. +// It hasn't to be the visible SdrPageView. +void SvxDrawPage::SelectObjectInView( const Reference< drawing::XShape > & xShape, SdrPageView* pPageView ) noexcept +{ + SAL_WARN_IF(!pPageView, "svx", "SdrPageView is NULL!"); + SAL_WARN_IF(!mpView, "svx", "SdrView is NULL!"); + + if(pPageView!=nullptr && mpView != nullptr) + { + mpView->UnmarkAllObj( pPageView ); + lcl_markSdrObjectOfShape( xShape, *mpView, *pPageView ); + } +} + +Reference< drawing::XShapeGroup > SAL_CALL SvxDrawPage::group( const Reference< drawing::XShapes >& xShapes ) +{ + SolarMutexGuard aGuard; + + if( (mpModel == nullptr) || (mpPage == nullptr) ) + throw lang::DisposedException(); + + SAL_WARN_IF(!mpPage , "svx", "SdrPage is NULL!"); + SAL_WARN_IF(!mpView, "svx", "SdrView is NULL!"); + + Reference< css::drawing::XShapeGroup > xShapeGroup; + if(mpPage==nullptr||mpView==nullptr||!xShapes.is()) + return xShapeGroup; + + SdrPageView* pPageView = mpView->ShowSdrPage( mpPage ); + + SelectObjectsInView( xShapes, pPageView ); + + mpView->GroupMarked(); + + mpView->AdjustMarkHdl(); + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if( pObj ) + xShapeGroup.set( pObj->getUnoShape(), UNO_QUERY ); + } + + mpView->HideSdrPage(); + + if( mpModel ) + mpModel->SetChanged(); + + return xShapeGroup; +} + +void SAL_CALL SvxDrawPage::ungroup( const Reference< drawing::XShapeGroup >& aGroup ) +{ + SolarMutexGuard aGuard; + + if( (mpModel == nullptr) || (mpPage == nullptr) ) + throw lang::DisposedException(); + + SAL_WARN_IF(!mpPage, "svx", "SdrPage is NULL!"); + SAL_WARN_IF(!mpView, "svx", "SdrView is NULL!"); + + if(mpPage==nullptr||mpView==nullptr||!aGroup.is()) + return; + + SdrPageView* pPageView = mpView->ShowSdrPage( mpPage ); + + SelectObjectInView( aGroup, pPageView ); + mpView->UnGroupMarked(); + + mpView->HideSdrPage(); + + if( mpModel ) + mpModel->SetChanged(); +} + +SdrObject* SvxDrawPage::CreateSdrObject_(const Reference< drawing::XShape > & xShape) +{ + SdrObjKind nType = SdrObjKind::NONE; + SdrInventor nInventor; + + GetTypeAndInventor( nType, nInventor, xShape->getShapeType() ); + if (nType == SdrObjKind::NONE) + return nullptr; + + awt::Size aSize = xShape->getSize(); + aSize.Width += 1; + aSize.Height += 1; + awt::Point aPos = xShape->getPosition(); + tools::Rectangle aRect( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ); + + SdrObject* pNewObj = SdrObjFactory::MakeNewObject( + *mpModel, + nInventor, + nType, + &aRect); + + if (!pNewObj) + return nullptr; + + if( auto pScene = dynamic_cast<E3dScene* >(pNewObj) ) + { + // initialise scene + + double fW = static_cast<double>(aSize.Width); + double fH = static_cast<double>(aSize.Height); + + Camera3D aCam(pScene->GetCamera()); + aCam.SetAutoAdjustProjection(false); + aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH); + basegfx::B3DPoint aLookAt; + basegfx::B3DPoint aCamPos(0.0, 0.0, 10000.0); + aCam.SetPosAndLookAt(aCamPos, aLookAt); + aCam.SetFocalLength(100.0); + pScene->SetCamera(aCam); + + pScene->SetBoundAndSnapRectsDirty(); + } + else if(auto pObj = dynamic_cast<E3dExtrudeObj* >(pNewObj)) + { + basegfx::B2DPolygon aNewPolygon; + aNewPolygon.append(basegfx::B2DPoint(0.0, 0.0)); + aNewPolygon.append(basegfx::B2DPoint(0.0, 1.0)); + aNewPolygon.append(basegfx::B2DPoint(1.0, 0.0)); + aNewPolygon.setClosed(true); + pObj->SetExtrudePolygon(basegfx::B2DPolyPolygon(aNewPolygon)); + + // #107245# pObj->SetExtrudeCharacterMode(sal_True); + pObj->SetMergedItem(Svx3DCharacterModeItem(true)); + } + else if(auto pLatheObj = dynamic_cast<E3dLatheObj* >(pNewObj)) + { + basegfx::B2DPolygon aNewPolygon; + aNewPolygon.append(basegfx::B2DPoint(0.0, 0.0)); + aNewPolygon.append(basegfx::B2DPoint(0.0, 1.0)); + aNewPolygon.append(basegfx::B2DPoint(1.0, 0.0)); + aNewPolygon.setClosed(true); + pLatheObj->SetPolyPoly2D(basegfx::B2DPolyPolygon(aNewPolygon)); + + // #107245# pObj->SetLatheCharacterMode(sal_True); + pLatheObj->SetMergedItem(Svx3DCharacterModeItem(true)); + } + + return pNewObj; +} + +void SvxDrawPage::GetTypeAndInventor( SdrObjKind& rType, SdrInventor& rInventor, const OUString& aName ) noexcept +{ + std::optional<SdrObjKind> nTempType = UHashMap::getId( aName ); + + if( !nTempType ) + { + if( aName == "com.sun.star.drawing.TableShape" || + aName == "com.sun.star.presentation.TableShape" ) + { + rInventor = SdrInventor::Default; + rType = SdrObjKind::Table; + } +#if HAVE_FEATURE_AVMEDIA + else if ( aName == "com.sun.star.presentation.MediaShape" ) + { + rInventor = SdrInventor::Default; + rType = SdrObjKind::Media; + } +#endif + } + else if( IsInventorE3D(*nTempType) ) + { + rInventor = SdrInventor::E3d; + rType = *nTempType; + } + else + { + rInventor = SdrInventor::Default; + rType = *nTempType; + + switch( rType ) + { + case SdrObjKind::OLEPluginFrame: + case SdrObjKind::OLE2Plugin: + case SdrObjKind::OLE2Applet: + rType = SdrObjKind::OLE2; + break; + default: + break; + } + } +} + +rtl::Reference<SvxShape> SvxDrawPage::CreateShapeByTypeAndInventor( SdrObjKind nType, SdrInventor nInventor, SdrObject *pObj, SvxDrawPage *mpPage, OUString const & referer ) +{ + rtl::Reference<SvxShape> pRet; + + switch( nInventor ) + { + case SdrInventor::E3d: + { + switch( nType ) + { + case SdrObjKind::E3D_Scene : + pRet = new Svx3DSceneObject( pObj, mpPage ); + break; + case SdrObjKind::E3D_Cube : + pRet = new Svx3DCubeObject( pObj ); + break; + case SdrObjKind::E3D_Sphere : + pRet = new Svx3DSphereObject( pObj ); + break; + case SdrObjKind::E3D_Lathe : + pRet = new Svx3DLatheObject( pObj ); + break; + case SdrObjKind::E3D_Extrusion : + pRet = new Svx3DExtrudeObject( pObj ); + break; + case SdrObjKind::E3D_Polygon : + pRet = new Svx3DPolygonObject( pObj ); + break; + default: // unknown 3D-object on page + assert(false && "the IsInventor3D function must be wrong"); + pRet = new SvxShape( pObj ); + break; + } + break; + } + case SdrInventor::Default: + { + switch( nType ) + { + case SdrObjKind::Group: + pRet = new SvxShapeGroup( pObj, mpPage ); + break; + case SdrObjKind::Line: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::Rectangle: + pRet = new SvxShapeRect( pObj ); + break; + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::CircleSection: + case SdrObjKind::CircleArc: + case SdrObjKind::CircleCut: + pRet = new SvxShapeCircle( pObj ); + break; + case SdrObjKind::Polygon: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::PolyLine: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::SplineLine: + case SdrObjKind::PathLine: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::SplineFill: + case SdrObjKind::PathFill: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::FreehandLine: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::FreehandFill: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::Caption: + pRet = new SvxShapeCaption( pObj ); + break; + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + case SdrObjKind::Text: + pRet = new SvxShapeText( pObj ); + break; + case SdrObjKind::Graphic: + pRet = new SvxGraphicObject( pObj ); + break; + case SdrObjKind::OLEPluginFrame: + pRet = new SvxFrameShape( pObj ); + break; + case SdrObjKind::OLE2Applet: + pRet = new SvxAppletShape( pObj ); + break; + case SdrObjKind::OLE2Plugin: + pRet = new SvxPluginShape( pObj ); + break; + case SdrObjKind::OLE2: + { + if( pObj && !pObj->IsEmptyPresObj() && mpPage ) + { + SdrPage* pSdrPage = mpPage->GetSdrPage(); + if( pSdrPage ) + { + SdrModel& rSdrModel(pSdrPage->getSdrModelFromSdrPage()); + ::comphelper::IEmbeddedHelper *pPersist = rSdrModel.GetPersist(); + + if( pPersist ) + { + uno::Reference < embed::XEmbeddedObject > xObject = pPersist->getEmbeddedObjectContainer(). + GetEmbeddedObject( static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ); + + // TODO CL->KA: Why is this not working anymore? + if( xObject.is() ) + { + SvGlobalName aClassId( xObject->getClassID() ); + + const SvGlobalName aAppletClassId( SO3_APPLET_CLASSID ); + const SvGlobalName aPluginClassId( SO3_PLUGIN_CLASSID ); + const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID ); + + if( aPluginClassId == aClassId ) + { + pRet = new SvxPluginShape( pObj ); + nType = SdrObjKind::OLE2Plugin; + } + else if( aAppletClassId == aClassId ) + { + pRet = new SvxAppletShape( pObj ); + nType = SdrObjKind::OLE2Applet; + } + else if( aIFrameClassId == aClassId ) + { + pRet = new SvxFrameShape( pObj ); + nType = SdrObjKind::OLEPluginFrame; + } + } + } + } + } + if( pRet == nullptr ) + { + SvxUnoPropertyMapProvider& rSvxMapProvider = getSvxMapProvider(); + pRet = new SvxOle2Shape( pObj, rSvxMapProvider.GetMap(SVXMAP_OLE2), rSvxMapProvider.GetPropertySet(SVXMAP_OLE2, SdrObject::GetGlobalDrawObjectItemPool()) ); + } + } + break; + case SdrObjKind::Edge: + pRet = new SvxShapeConnector( pObj ); + break; + case SdrObjKind::PathPoly: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::PathPolyLine: + pRet = new SvxShapePolyPolygon( pObj ); + break; + case SdrObjKind::Page: + { + SvxUnoPropertyMapProvider& rSvxMapProvider = getSvxMapProvider(); + pRet = new SvxShape( pObj, rSvxMapProvider.GetMap(SVXMAP_PAGE), rSvxMapProvider.GetPropertySet(SVXMAP_PAGE, SdrObject::GetGlobalDrawObjectItemPool()) ); + } + break; + case SdrObjKind::Measure: + pRet = new SvxShapeDimensioning( pObj ); + break; + case SdrObjKind::UNO: + pRet = new SvxShapeControl( pObj ); + break; + case SdrObjKind::CustomShape: + pRet = new SvxCustomShape( pObj ); + break; + case SdrObjKind::Media: + pRet = new SvxMediaShape( pObj, referer ); + break; + case SdrObjKind::Table: + pRet = new SvxTableShape( pObj ); + break; + default: // unknown 2D-object on page + assert(false && "Not implemented Starone-Shape created"); + pRet = new SvxShapeText( pObj ); + break; + } + break; + } + default: // unknown inventor + { + assert(false && "Unknown Inventor in SvxDrawPage::CreateShape()"); + break; + } + } + + if(pRet) + { + SdrObjKind nObjId = nType; + + switch(nObjId) + { + case SdrObjKind::CircleCut: // segment of circle + case SdrObjKind::CircleArc: // arc of circle + case SdrObjKind::CircleSection: // sector + nObjId = SdrObjKind::CircleOrEllipse; + break; + + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + nObjId = SdrObjKind::Text; + break; + default: ; + } + + pRet->setShapeKind(nObjId); + } + + return pRet; +} + +Reference< drawing::XShape > SvxDrawPage::CreateShape( SdrObject *pObj ) const +{ + Reference< drawing::XShape > xShape( CreateShapeByTypeAndInventor(pObj->GetObjIdentifier(), + pObj->GetObjInventor(), + pObj, + const_cast<SvxDrawPage*>(this))); + return xShape; +} + +SdrObject *SvxDrawPage::CreateSdrObject( const Reference< drawing::XShape > & xShape, bool bBeginning ) noexcept +{ + SdrObject* pObj = CreateSdrObject_( xShape ); + if( pObj) + { + if ( !pObj->IsInserted() && !pObj->IsDoNotInsertIntoPageAutomatically() ) + { + if(bBeginning) + mpPage->InsertObject( pObj, 0 ); + else + mpPage->InsertObject( pObj ); + } + } + + return pObj; +} + +// css::lang::XServiceInfo +OUString SAL_CALL SvxDrawPage::getImplementationName() +{ + return "SvxDrawPage"; +} + +sal_Bool SAL_CALL SvxDrawPage::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +uno::Sequence< OUString > SAL_CALL SvxDrawPage::getSupportedServiceNames() +{ + uno::Sequence<OUString> aSeq { "com.sun.star.drawing.ShapeCollection" }; + return aSeq; +} + +rtl::Reference<SvxShape> CreateSvxShapeByTypeAndInventor(SdrObjKind nType, SdrInventor nInventor, OUString const & referer) +{ + return SvxDrawPage::CreateShapeByTypeAndInventor( nType, nInventor, nullptr, nullptr, referer ); +} + +/** returns a StarOffice API wrapper for the given SdrPage */ +uno::Reference< drawing::XDrawPage > GetXDrawPageForSdrPage( SdrPage* pPage ) noexcept +{ + if(pPage) + { + uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); + + return xDrawPage; + } + + return uno::Reference< drawing::XDrawPage >(); +} + +/** returns the SdrObject from the given StarOffice API wrapper */ +SdrPage* GetSdrPageFromXDrawPage( const uno::Reference< drawing::XDrawPage >& xDrawPage ) noexcept +{ + if(xDrawPage.is()) + { + SvxDrawPage* pDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( xDrawPage ); + + if(pDrawPage) + { + return pDrawPage->GetSdrPage(); + } + } + + return nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unopool.cxx b/svx/source/unodraw/unopool.cxx new file mode 100644 index 000000000..59c19c702 --- /dev/null +++ b/svx/source/unodraw/unopool.cxx @@ -0,0 +1,375 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/PropertyState.hpp> + +#include <comphelper/propertysetinfo.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <vcl/svapp.hxx> +#include <svx/unopool.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpool.hxx> +#include <svx/unoprov.hxx> +#include <svx/unoshprp.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/svdetc.hxx> +#include <editeng/editeng.hxx> +#include <tools/debug.hxx> + +#include <memory> + +using namespace ::com::sun::star; +using namespace ::cppu; + +SvxUnoDrawPool::SvxUnoDrawPool(SdrModel* pModel, sal_Int32 nServiceId) +: PropertySetHelper( SvxPropertySetInfoPool::getOrCreate( nServiceId ) ), mpModel( pModel ) +{ + init(); +} + +/* deprecated */ +SvxUnoDrawPool::SvxUnoDrawPool(SdrModel* pModel) +: PropertySetHelper( SvxPropertySetInfoPool::getOrCreate( SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS ) ), mpModel( pModel ) +{ + init(); +} + +SvxUnoDrawPool::~SvxUnoDrawPool() noexcept +{ +} + +void SvxUnoDrawPool::init() +{ + mpDefaultsPool = new SdrItemPool(); + rtl::Reference<SfxItemPool> pOutlPool = EditEngine::CreatePool(); + mpDefaultsPool->SetSecondaryPool(pOutlPool.get()); + + SdrModel::SetTextDefaults( mpDefaultsPool.get(), SdrEngineDefaults::GetFontHeight() ); + mpDefaultsPool->SetDefaultMetric(SdrEngineDefaults::GetMapUnit()); + mpDefaultsPool->FreezeIdRanges(); +} + +SfxItemPool* SvxUnoDrawPool::getModelPool( bool bReadOnly ) noexcept +{ + if( mpModel ) + { + return &mpModel->GetItemPool(); + } + else + { + if( bReadOnly ) + return mpDefaultsPool.get(); + else + return nullptr; + } +} + +void SvxUnoDrawPool::getAny( SfxItemPool const * pPool, const comphelper::PropertyMapEntry* pEntry, uno::Any& rValue ) +{ + switch( pEntry->mnHandle ) + { + case OWN_ATTR_FILLBMP_MODE: + { + if (pPool->GetDefaultItem(XATTR_FILLBMP_TILE).GetValue()) + { + rValue <<= drawing::BitmapMode_REPEAT; + } + else if (pPool->GetDefaultItem(XATTR_FILLBMP_STRETCH).GetValue()) + { + rValue <<= drawing::BitmapMode_STRETCH; + } + else + { + rValue <<= drawing::BitmapMode_NO_REPEAT; + } + break; + } + default: + { + const MapUnit eMapUnit = pPool->GetMetric(static_cast<sal_uInt16>(pEntry->mnHandle)); + + sal_uInt8 nMemberId = pEntry->mnMemberId; + if( eMapUnit == MapUnit::Map100thMM ) + nMemberId &= (~CONVERT_TWIPS); + + // Assure, that ID is a Which-ID (it could be a Slot-ID.) + // Thus, convert handle to Which-ID. + pPool->GetDefaultItem( pPool->GetWhich( static_cast<sal_uInt16>(pEntry->mnHandle) ) ).QueryValue( rValue, nMemberId ); + } + } + + + // check for needed metric translation + const MapUnit eMapUnit = pPool->GetMetric(static_cast<sal_uInt16>(pEntry->mnHandle)); + if(pEntry->mnMoreFlags & PropertyMoreFlags::METRIC_ITEM && eMapUnit != MapUnit::Map100thMM) + { + SvxUnoConvertToMM( eMapUnit, rValue ); + } + // convert int32 to correct enum type if needed + else if ( pEntry->maType.getTypeClass() == uno::TypeClass_ENUM && rValue.getValueType() == ::cppu::UnoType<sal_Int32>::get() ) + { + sal_Int32 nEnum; + rValue >>= nEnum; + + rValue.setValue( &nEnum, pEntry->maType ); + } +} + +void SvxUnoDrawPool::putAny( SfxItemPool* pPool, const comphelper::PropertyMapEntry* pEntry, const uno::Any& rValue ) +{ + uno::Any aValue( rValue ); + + const MapUnit eMapUnit = pPool->GetMetric(static_cast<sal_uInt16>(pEntry->mnHandle)); + if(pEntry->mnMoreFlags & PropertyMoreFlags::METRIC_ITEM && eMapUnit != MapUnit::Map100thMM) + { + SvxUnoConvertFromMM( eMapUnit, aValue ); + } + + // Assure, that ID is a Which-ID (it could be a Slot-ID.) + // Thus, convert handle to Which-ID. + const sal_uInt16 nWhich = pPool->GetWhich( static_cast<sal_uInt16>(pEntry->mnHandle) ); + switch( nWhich ) + { + case OWN_ATTR_FILLBMP_MODE: + do + { + drawing::BitmapMode eMode; + if(!(aValue >>= eMode) ) + { + sal_Int32 nMode = 0; + if(!(aValue >>= nMode)) + throw lang::IllegalArgumentException(); + + eMode = static_cast<drawing::BitmapMode>(nMode); + } + + pPool->SetPoolDefaultItem( XFillBmpStretchItem( eMode == drawing::BitmapMode_STRETCH ) ); + pPool->SetPoolDefaultItem( XFillBmpTileItem( eMode == drawing::BitmapMode_REPEAT ) ); + return; + } + while(false); + + default: + { + std::unique_ptr<SfxPoolItem> pNewItem( pPool->GetDefaultItem( nWhich ).Clone() ); + sal_uInt8 nMemberId = pEntry->mnMemberId; + if( pPool->GetMetric(nWhich) == MapUnit::Map100thMM ) + nMemberId &= (~CONVERT_TWIPS); + + if( !pNewItem->PutValue( aValue, nMemberId ) ) + throw lang::IllegalArgumentException(); + + pPool->SetPoolDefaultItem( *pNewItem ); + } + } +} + +void SvxUnoDrawPool::_setPropertyValues( const comphelper::PropertyMapEntry** ppEntries, const uno::Any* pValues ) +{ + SolarMutexGuard aGuard; + + SfxItemPool* pPool = getModelPool( false ); + + DBG_ASSERT( pPool, "I need a SfxItemPool!" ); + if( nullptr == pPool ) + throw beans::UnknownPropertyException( "no pool, no properties..", static_cast<cppu::OWeakObject*>(this)); + + while( *ppEntries ) + putAny( pPool, *ppEntries++, *pValues++ ); +} + +void SvxUnoDrawPool::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, uno::Any* pValue ) +{ + SolarMutexGuard aGuard; + + SfxItemPool* pPool = getModelPool( true ); + + DBG_ASSERT( pPool, "I need a SfxItemPool!" ); + if( nullptr == pPool ) + throw beans::UnknownPropertyException( "no pool, no properties..", static_cast<cppu::OWeakObject*>(this)); + + while( *ppEntries ) + getAny( pPool, *ppEntries++, *pValue++ ); +} + +void SvxUnoDrawPool::_getPropertyStates( const comphelper::PropertyMapEntry** ppEntries, beans::PropertyState* pStates ) +{ + SolarMutexGuard aGuard; + + SfxItemPool* pPool = getModelPool( true ); + + if( pPool && pPool != mpDefaultsPool.get() ) + { + while( *ppEntries ) + { + //Assure, that ID is a Which-ID (it could be a Slot-ID.) + // Thus, convert handle to Which-ID. + const sal_uInt16 nWhich = pPool->GetWhich( static_cast<sal_uInt16>((*ppEntries)->mnHandle) ); + + switch( nWhich ) + { + case OWN_ATTR_FILLBMP_MODE: + { + // use method <IsStaticDefaultItem(..)> instead of using + // probably incompatible item pool <mpDefaultPool>. + if ( IsStaticDefaultItem( &(pPool->GetDefaultItem( XATTR_FILLBMP_STRETCH )) ) || + IsStaticDefaultItem( &(pPool->GetDefaultItem( XATTR_FILLBMP_TILE )) ) ) + { + *pStates = beans::PropertyState_DEFAULT_VALUE; + } + else + { + *pStates = beans::PropertyState_DIRECT_VALUE; + } + } + break; + case OWN_ATTR_TEXTCOLUMNS: + if (IsStaticDefaultItem(&pPool->GetDefaultItem(sal_uInt16(SDRATTR_TEXTCOLUMNS_NUMBER))) + && IsStaticDefaultItem(&pPool->GetDefaultItem(sal_uInt16(SDRATTR_TEXTCOLUMNS_SPACING)))) + *pStates = beans::PropertyState_DEFAULT_VALUE; + else + *pStates = beans::PropertyState_DIRECT_VALUE; + break; + default: + //#i18732# - correction: + // use method <IsStaticDefaultItem(..)> instead of using probably + // incompatible item pool <mpDefaultPool>. + const SfxPoolItem& r1 = pPool->GetDefaultItem( nWhich ); + //const SfxPoolItem& r2 = mpDefaultPool->GetDefaultItem( nWhich ); + + if ( IsStaticDefaultItem( &r1 ) ) + { + *pStates = beans::PropertyState_DEFAULT_VALUE; + } + else + { + *pStates = beans::PropertyState_DIRECT_VALUE; + } + } + + pStates++; + ppEntries++; + } + } + else + { + // as long as we have no model, all properties are default + while( *ppEntries++ ) + *pStates++ = beans::PropertyState_DEFAULT_VALUE; + return; + } +} + +void SvxUnoDrawPool::_setPropertyToDefault( const comphelper::PropertyMapEntry* pEntry ) +{ + SolarMutexGuard aGuard; + + SfxItemPool* pPool = getModelPool( true ); + + // Assure, that ID is a Which-ID (it could be a Slot-ID.) + // Thus, convert handle to Which-ID. + const sal_uInt16 nWhich = pPool->GetWhich( static_cast<sal_uInt16>(pEntry->mnHandle) ); + if ( pPool && pPool != mpDefaultsPool.get() ) + { + // use method <ResetPoolDefaultItem(..)> instead of using probably incompatible item pool <mpDefaultsPool>. + pPool->ResetPoolDefaultItem( nWhich ); + } +} + +uno::Any SvxUnoDrawPool::_getPropertyDefault( const comphelper::PropertyMapEntry* pEntry ) +{ + SolarMutexGuard aGuard; + //#i18732# - use method <GetPoolDefaultItem(..)> instead of + // using probably incompatible item pool <mpDefaultsPool> + uno::Any aAny; + SfxItemPool* pPool = getModelPool( true ); + const sal_uInt16 nWhich = pPool->GetWhich( static_cast<sal_uInt16>(pEntry->mnHandle) ); + const SfxPoolItem *pItem = pPool->GetPoolDefaultItem ( nWhich ); + if (pItem) + { + pItem->QueryValue( aAny, pEntry->mnMemberId ); + } + + return aAny; +} + +// XInterface + +uno::Any SAL_CALL SvxUnoDrawPool::queryInterface( const uno::Type & rType ) +{ + return OWeakAggObject::queryInterface( rType ); +} + +uno::Any SAL_CALL SvxUnoDrawPool::queryAggregation( const uno::Type & rType ) +{ + uno::Any aAny; + + if( rType == cppu::UnoType<lang::XServiceInfo>::get()) + aAny <<= uno::Reference< lang::XServiceInfo >(this); + else if( rType == cppu::UnoType<lang::XTypeProvider>::get()) + aAny <<= uno::Reference< lang::XTypeProvider >(this); + else if( rType == cppu::UnoType<beans::XPropertySet>::get()) + aAny <<= uno::Reference< beans::XPropertySet >(this); + else if( rType == cppu::UnoType<beans::XPropertyState>::get()) + aAny <<= uno::Reference< beans::XPropertyState >(this); + else if( rType == cppu::UnoType<beans::XMultiPropertySet>::get()) + aAny <<= uno::Reference< beans::XMultiPropertySet >(this); + else + aAny = OWeakAggObject::queryAggregation( rType ); + + return aAny; +} + +uno::Sequence< uno::Type > SAL_CALL SvxUnoDrawPool::getTypes() +{ + static const uno::Sequence aTypes { + cppu::UnoType<uno::XAggregation>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get() }; + return aTypes; +} + +uno::Sequence< sal_Int8 > SAL_CALL SvxUnoDrawPool::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XServiceInfo +sal_Bool SAL_CALL SvxUnoDrawPool::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +OUString SAL_CALL SvxUnoDrawPool::getImplementationName() +{ + return "SvxUnoDrawPool"; +} + +uno::Sequence< OUString > SAL_CALL SvxUnoDrawPool::getSupportedServiceNames( ) +{ + uno::Sequence<OUString> aSNS { "com.sun.star.drawing.Defaults" }; + return aSNS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoprov.cxx b/svx/source/unodraw/unoprov.cxx new file mode 100644 index 000000000..9936a4df9 --- /dev/null +++ b/svx/source/unodraw/unoprov.cxx @@ -0,0 +1,2107 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cassert> + +#include <sal/macros.h> +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/media/ZoomLevel.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <tools/fldunit.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/sequence.hxx> +#include <svx/dialmgr.hxx> +#include <svx/unoapi.hxx> +#include <svx/unoshprp.hxx> +#include <svx/svxids.hrc> +#include <svx/svdobjkind.hxx> +#include <svx/strings.hrc> +#include <o3tl/string_view.hxx> +#include <strings.hxx> + +#include "shapeimpl.hxx" +#include <unordered_map> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans::PropertyAttribute; +using ::com::sun::star::drawing::TextVerticalAdjust; + +static SfxItemPropertyMapEntry const * ImplGetSvxShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aShapePropertyMap_Impl[] = + { + EDGERADIUS_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aShapePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxTextShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aTextShapePropertyMap_Impl[] = + { + EDGERADIUS_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES_NO_SHEAR + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aTextShapePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxConnectorPropertyMap() +{ + static SfxItemPropertyMapEntry const aConnectorPropertyMap_Impl[] = + { + SPECIAL_CONNECTOR_PROPERTIES + EDGERADIUS_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aConnectorPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxDimensioningPropertyMap() +{ + static SfxItemPropertyMapEntry const aDimensioningPropertyMap_Impl[] = + { + SPECIAL_DIMENSIONING_PROPERTIES + EDGERADIUS_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aDimensioningPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxCirclePropertyMap() +{ + static SfxItemPropertyMapEntry const aCirclePropertyMap_Impl[] = + { + SPECIAL_CIRCLE_PROPERTIES + EDGERADIUS_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aCirclePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxPolyPolygonPropertyMap() +{ + static SfxItemPropertyMapEntry const aPolyPolygonPropertyMap_Impl[] = + { + { u"Geometry", OWN_ATTR_BASE_GEOMETRY, cppu::UnoType<css::drawing::PointSequenceSequence>::get(), 0, 0 }, + SPECIAL_POLYGON_PROPERTIES + SPECIAL_POLYPOLYGON_PROPERTIES + SPECIAL_POLYPOLYGONBEZIER_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aPolyPolygonPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxGraphicObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const aGraphicObjectPropertyMap_Impl[] = + { + SPECIAL_GRAPHOBJ_PROPERTIES + + // #i25616# + FILL_PROPERTIES + + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + + // #i118485# Full properties now, shear included + MISC_OBJ_PROPERTIES + + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"IsMirrored", OWN_ATTR_MIRRORED, cppu::UnoType<bool>::get(), 0, 0}, + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"GraphicStream", OWN_ATTR_GRAPHIC_STREAM, cppu::UnoType<css::io::XInputStream>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aGraphicObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvx3DSceneObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const a3DSceneObjectPropertyMap_Impl[] = + { + SPECIAL_3DSCENEOBJECT_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return a3DSceneObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvx3DCubeObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const a3DCubeObjectPropertyMap_Impl[] = + { + SPECIAL_3DCUBEOBJECT_PROPERTIES + MISC_3D_OBJ_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return a3DCubeObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvx3DSphereObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const a3DSphereObjectPropertyMap_Impl[] = + { + SPECIAL_3DSPHEREOBJECT_PROPERTIES + MISC_3D_OBJ_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + return a3DSphereObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvx3DLatheObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const a3DLatheObjectPropertyMap_Impl[] = + { + SPECIAL_3DLATHEOBJECT_PROPERTIES + + // #107245# New 3D properties which are possible for lathe and extrude 3d objects + SPECIAL_3DLATHEANDEXTRUDEOBJ_PROPERTIES + + SPECIAL_3DBACKSCALE_PROPERTIES + MISC_3D_OBJ_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return a3DLatheObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvx3DExtrudeObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const a3DExtrudeObjectPropertyMap_Impl[] = + { + SPECIAL_3DEXTRUDEOBJECT_PROPERTIES + + // #107245# New 3D properties which are possible for lathe and extrude 3d objects + SPECIAL_3DLATHEANDEXTRUDEOBJ_PROPERTIES + + SPECIAL_3DBACKSCALE_PROPERTIES + MISC_3D_OBJ_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return a3DExtrudeObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvx3DPolygonObjectPropertyMap() +{ + static SfxItemPropertyMapEntry const a3DPolygonObjectPropertyMap_Impl[] = + { + SPECIAL_3DPOLYGONOBJECT_PROPERTIES + MISC_3D_OBJ_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return a3DPolygonObjectPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxAllPropertyMap() +{ + static SfxItemPropertyMapEntry const aAllPropertyMap_Impl[] = + { + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + FILL_PROPERTIES + EDGERADIUS_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SPECIAL_CONNECTOR_PROPERTIES + SPECIAL_DIMENSIONING_PROPERTIES + SPECIAL_CIRCLE_PROPERTIES + SPECIAL_POLYGON_PROPERTIES + SPECIAL_POLYPOLYGON_PROPERTIES + SPECIAL_POLYPOLYGONBEZIER_PROPERTIES + SPECIAL_GRAPHOBJ_PROPERTIES + SPECIAL_3DSCENEOBJECT_PROPERTIES + MISC_3D_OBJ_PROPERTIES + SPECIAL_3DCUBEOBJECT_PROPERTIES + SPECIAL_3DSPHEREOBJECT_PROPERTIES + SPECIAL_3DLATHEOBJECT_PROPERTIES + SPECIAL_3DEXTRUDEOBJECT_PROPERTIES + + // #107245# New 3D properties which are possible for lathe and extrude 3d objects + SPECIAL_3DLATHEANDEXTRUDEOBJ_PROPERTIES + + SPECIAL_3DBACKSCALE_PROPERTIES + SPECIAL_3DPOLYGONOBJECT_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aAllPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxGroupPropertyMap() +{ + static SfxItemPropertyMapEntry const aGroupPropertyMap_Impl[] = + { + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aGroupPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxOle2PropertyMap() +{ + static SfxItemPropertyMapEntry const aOle2PropertyMap_Impl[] = + { + // #i118485# Adding properties for line, fill, text, shadow, fontwork, rotate, shear + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + FONTWORK_PROPERTIES + + { u"ThumbnailGraphic", OWN_ATTR_THUMBNAIL , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0 }, + { u"Model", OWN_ATTR_OLEMODEL , cppu::UnoType<css::frame::XModel>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"EmbeddedObject", OWN_ATTR_OLE_EMBEDDED_OBJECT, cppu::UnoType<css::embed::XEmbeddedObject>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"EmbeddedObjectNoNewClient",OWN_ATTR_OLE_EMBEDDED_OBJECT_NONEWCLIENT, cppu::UnoType<css::embed::XEmbeddedObject>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"OriginalSize", OWN_ATTR_OLESIZE , cppu::UnoType<css::awt::Size>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"CLSID", OWN_ATTR_CLSID , cppu::UnoType<OUString>::get(), 0, 0 }, + { u"IsInternal", OWN_ATTR_INTERNAL_OLE , cppu::UnoType<bool>::get() , css::beans::PropertyAttribute::READONLY, 0}, + { u"VisibleArea", OWN_ATTR_OLE_VISAREA , cppu::UnoType<css::awt::Rectangle>::get(), 0, 0}, + { u"Aspect", OWN_ATTR_OLE_ASPECT , cppu::UnoType<sal_Int64>::get(), 0, 0}, + { UNO_NAME_OLE2_PERSISTNAME, OWN_ATTR_PERSISTNAME , cppu::UnoType<OUString>::get(), 0, 0 }, + { u"LinkURL", OWN_ATTR_OLE_LINKURL , cppu::UnoType<OUString>::get(), 0, 0 }, + { UNO_NAME_GRAPHOBJ_GRAPHIC, OWN_ATTR_VALUE_GRAPHIC , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aOle2PropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxPluginPropertyMap() +{ + static SfxItemPropertyMapEntry const aPluginPropertyMap_Impl[] = + { + { u"PluginMimeType", OWN_ATTR_PLUGIN_MIMETYPE , cppu::UnoType<OUString>::get(), 0, 0}, + { u"PluginURL", OWN_ATTR_PLUGIN_URL , cppu::UnoType<OUString>::get(), 0, 0}, + { u"PluginCommands", OWN_ATTR_PLUGIN_COMMANDS , cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get(), 0, 0}, + { u"Transformation", OWN_ATTR_TRANSFORMATION , cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID , cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME,SDRATTR_LAYERNAME , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP , cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_OLE2_METAFILE, OWN_ATTR_METAFILE , cppu::UnoType<css::uno::Sequence<sal_Int8>>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"ThumbnailGraphic", OWN_ATTR_THUMBNAIL , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_OLE2_PERSISTNAME, OWN_ATTR_PERSISTNAME , cppu::UnoType<OUString>::get(), 0, 0 }, + { u"LinkURL", OWN_ATTR_OLE_LINKURL , cppu::UnoType<OUString>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"VisibleArea", OWN_ATTR_OLE_VISAREA , cppu::UnoType<css::awt::Rectangle>::get(), 0, 0}, + { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + // #i68101# + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aPluginPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxFramePropertyMap() +{ + //TODO/LATER: new properties for ScrollingMode and DefaultBorder + static SfxItemPropertyMapEntry const aFramePropertyMap_Impl[] = + { + { u"FrameURL", OWN_ATTR_FRAME_URL , cppu::UnoType<OUString>::get(), 0, 0}, + { u"FrameName", OWN_ATTR_FRAME_NAME , cppu::UnoType<OUString>::get(), 0, 0}, + { u"FrameIsAutoScroll", OWN_ATTR_FRAME_ISAUTOSCROLL , cppu::UnoType<bool>::get() , css::beans::PropertyAttribute::MAYBEVOID, 0}, + { u"FrameIsBorder", OWN_ATTR_FRAME_ISBORDER , cppu::UnoType<bool>::get() , 0, 0}, + { u"FrameMarginWidth", OWN_ATTR_FRAME_MARGIN_WIDTH , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { u"FrameMarginHeight", OWN_ATTR_FRAME_MARGIN_HEIGHT, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { u"Transformation", OWN_ATTR_TRANSFORMATION , cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID , cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME,SDRATTR_LAYERNAME , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP , cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_OLE2_METAFILE, OWN_ATTR_METAFILE , cppu::UnoType<css::uno::Sequence<sal_Int8>>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"ThumbnailGraphic", OWN_ATTR_THUMBNAIL , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_OLE2_PERSISTNAME, OWN_ATTR_PERSISTNAME , cppu::UnoType<OUString>::get(), 0, 0 }, + { u"LinkURL", OWN_ATTR_OLE_LINKURL , cppu::UnoType<OUString>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"VisibleArea", OWN_ATTR_OLE_VISAREA , cppu::UnoType<css::awt::Rectangle>::get(), 0, 0}, + { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + // #i68101# + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aFramePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxAppletPropertyMap() +{ + static SfxItemPropertyMapEntry const aAppletPropertyMap_Impl[] = + { + { u"AppletCodeBase", OWN_ATTR_APPLET_CODEBASE , cppu::UnoType<OUString>::get(), 0, 0}, + { u"AppletName", OWN_ATTR_APPLET_NAME , cppu::UnoType<OUString>::get(), 0, 0}, + { u"AppletCode", OWN_ATTR_APPLET_CODE , cppu::UnoType<OUString>::get(), 0, 0}, + { u"AppletCommands", OWN_ATTR_APPLET_COMMANDS , cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get(), 0, 0}, + { u"AppletDocBase", OWN_ATTR_APPLET_DOCBASE , cppu::UnoType<OUString>::get(), 0, 0}, + { u"AppletIsScript", OWN_ATTR_APPLET_ISSCRIPT , cppu::UnoType<bool>::get(), 0, 0 }, + { u"Transformation", OWN_ATTR_TRANSFORMATION , cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID , cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME,SDRATTR_LAYERNAME , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP , cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_OLE2_METAFILE, OWN_ATTR_METAFILE , cppu::UnoType<css::uno::Sequence<sal_Int8>>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"ThumbnailGraphic", OWN_ATTR_THUMBNAIL , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_OLE2_PERSISTNAME, OWN_ATTR_PERSISTNAME , cppu::UnoType<OUString>::get(), 0, 0 }, + { u"LinkURL", OWN_ATTR_OLE_LINKURL , cppu::UnoType<OUString>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"VisibleArea", OWN_ATTR_OLE_VISAREA , cppu::UnoType<css::awt::Rectangle>::get(), 0, 0}, + { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + // #i68101# + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aAppletPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxControlShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aControlPropertyMap_Impl[] = + { + // the following properties are mapped to the XControl Model of this shape + { UNO_NAME_EDIT_CHAR_FONTNAME, 0, cppu::UnoType<OUString>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_FONTSTYLENAME, 0, cppu::UnoType<OUString>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_FONTFAMILY, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_FONTCHARSET, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_HEIGHT, 0, cppu::UnoType<float>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_FONTPITCH, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_POSTURE, 0, cppu::UnoType<css::awt::FontSlant>::get(),0, 0 }, + { UNO_NAME_EDIT_CHAR_WEIGHT, 0, cppu::UnoType<float>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_UNDERLINE, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_STRIKEOUT, 0, cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_EDIT_CHAR_CASEMAP, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_EDIT_CHAR_COLOR, 0, cppu::UnoType<sal_Int32>::get(), 0, MID_COLOR_RGB }, + { UNO_NAME_EDIT_CHAR_COLOR_THEME, 0, cppu::UnoType<sal_Int16>::get(), 0, MID_COLOR_THEME_INDEX }, + { UNO_NAME_EDIT_CHAR_COLOR_TINT_OR_SHADE, 0, cppu::UnoType<sal_Int16>::get(), 0, MID_COLOR_TINT_OR_SHADE }, + { u"CharBackColor", 0, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"CharBackTransparent", 0, cppu::UnoType<bool>::get(), 0, 0 }, + { u"CharRelief", 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"CharUnderlineColor", 0, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"CharKerning", 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"CharWordMode", 0, cppu::UnoType<bool>::get(), 0, 0 }, + { UNO_NAME_EDIT_PARA_ADJUST, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"TextVerticalAdjust", 0, cppu::UnoType<TextVerticalAdjust>::get(), MAYBEVOID, 0 }, + { u"ControlBackground", 0, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"ControlBorder", 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"ControlBorderColor", 0, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"ControlSymbolColor", 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"ImageScaleMode", 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { u"ControlTextEmphasis", 0, cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { u"ControlWritingMode", 0, cppu::UnoType< sal_Int16 >::get(), 0, 0}, + // the following properties are handled by SvxShape + { u"Transformation", OWN_ATTR_TRANSFORMATION , cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID , cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME,SDRATTR_LAYERNAME , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP , cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + {u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + // #i68101# + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + // #i112587# + { UNO_NAME_MISC_OBJ_PRINTABLE, SDRATTR_OBJPRINTABLE , cppu::UnoType<bool>::get(), 0, 0}, + { u"Visible", SDRATTR_OBJVISIBLE , cppu::UnoType<bool>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_INTEROPGRABBAG, OWN_ATTR_INTEROPGRABBAG, cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aControlPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxPageShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aPageShapePropertyMap_Impl[] = + { + { u"PageNumber", OWN_ATTR_PAGE_NUMBER , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { u"Transformation", OWN_ATTR_TRANSFORMATION , cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER , cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID , cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME,SDRATTR_LAYERNAME , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP , cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + // #i68101# + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aPageShapePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxCaptionPropertyMap() +{ + static SfxItemPropertyMapEntry const aCaptionPropertyMap_Impl[] = + { + { u"CaptionPoint", OWN_ATTR_CAPTION_POINT, cppu::UnoType<css::awt::Point>::get(), 0, 0 }, + { u"CaptionType", SDRATTR_CAPTIONTYPE, cppu::UnoType<sal_Int16>::get(), 0, 0}, + { u"CaptionIsFixedAngle", SDRATTR_CAPTIONFIXEDANGLE, cppu::UnoType<bool>::get(), 0, 0}, + { u"CaptionAngle", SDRATTR_CAPTIONANGLE, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { u"CaptionGap", SDRATTR_CAPTIONGAP, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM}, + { u"CaptionEscapeDirection", SDRATTR_CAPTIONESCDIR, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { u"CaptionIsEscapeRelative", SDRATTR_CAPTIONESCISREL, cppu::UnoType<bool>::get(), 0, 0}, + { u"CaptionEscapeRelative", SDRATTR_CAPTIONESCREL, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { u"CaptionEscapeAbsolute", SDRATTR_CAPTIONESCABS, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM}, + { u"CaptionLineLength", SDRATTR_CAPTIONLINELEN, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM}, + { u"CaptionIsFitLineLength", SDRATTR_CAPTIONFITLINELEN, cppu::UnoType<bool>::get(), 0, 0}, + EDGERADIUS_PROPERTIES + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + // #FontWork# + FONTWORK_PROPERTIES + { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + {u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aCaptionPropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxCustomShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aCustomShapePropertyMap_Impl[] = + { + { u"CustomShapeEngine", SDRATTR_CUSTOMSHAPE_ENGINE, cppu::UnoType<OUString>::get(), 0, 0 }, + { u"CustomShapeData", SDRATTR_CUSTOMSHAPE_DATA, cppu::UnoType<OUString>::get(), 0, 0 }, + { u"CustomShapeGeometry", SDRATTR_CUSTOMSHAPE_GEOMETRY, + cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get(), 0, 0 }, + FILL_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + SHAPE_DESCRIPTOR_PROPERTIES + MISC_OBJ_PROPERTIES + LINKTARGET_PROPERTIES + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + TEXT_PROPERTIES + {u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + {u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + return aCustomShapePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxMediaShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aMediaShapePropertyMap_Impl[] = + { + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID, cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME, SDRATTR_LAYERNAME, cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP, cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"Transformation", OWN_ATTR_TRANSFORMATION, cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { u"MediaURL", OWN_ATTR_MEDIA_URL, cppu::UnoType<OUString>::get(), 0, 0}, + { u"PreferredSize", OWN_ATTR_MEDIA_PREFERREDSIZE, cppu::UnoType<css::awt::Size>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"Loop", OWN_ATTR_MEDIA_LOOP, cppu::UnoType<sal_Bool>::get(), 0, 0}, + { u"Mute", OWN_ATTR_MEDIA_MUTE, cppu::UnoType<sal_Bool>::get(), 0, 0}, + { u"VolumeDB", OWN_ATTR_MEDIA_VOLUMEDB, cppu::UnoType<sal_Int16>::get(), 0, 0}, + { u"Zoom", OWN_ATTR_MEDIA_ZOOM, cppu::UnoType<css::media::ZoomLevel>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + // #i68101# + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + {u"PrivateStream", OWN_ATTR_MEDIA_STREAM, cppu::UnoType<css::io::XInputStream>::get(), 0, 0}, + {u"PrivateTempFileURL", OWN_ATTR_MEDIA_TEMPFILEURL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"MediaMimeType", OWN_ATTR_MEDIA_MIMETYPE, cppu::UnoType<OUString>::get(), 0, 0}, + { u"FallbackGraphic", OWN_ATTR_FALLBACK_GRAPHIC, cppu::UnoType<css::graphic::XGraphic>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_GRAPHOBJ_GRAPHIC, OWN_ATTR_VALUE_GRAPHIC , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0}, + { UNO_NAME_GRAPHIC_GRAPHICCROP, SDRATTR_GRAFCROP , cppu::UnoType<css::text::GraphicCrop>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aMediaShapePropertyMap_Impl; +} + +static SfxItemPropertyMapEntry const * ImplGetSvxTableShapePropertyMap() +{ + static SfxItemPropertyMapEntry const aTableShapePropertyMap_Impl[] = + { + SHADOW_PROPERTIES + { UNO_NAME_MISC_OBJ_ZORDER, OWN_ATTR_ZORDER, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERID, SDRATTR_LAYERID, cppu::UnoType<sal_Int16>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_LAYERNAME, SDRATTR_LAYERNAME, cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_LINKDISPLAYBITMAP, OWN_ATTR_LDBITMAP, cppu::UnoType<css::awt::XBitmap>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_LINKDISPLAYNAME, OWN_ATTR_LDNAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"Transformation", OWN_ATTR_TRANSFORMATION, cppu::UnoType<css::drawing::HomogenMatrix3>::get(), 0, 0 }, + { UNO_NAME_MISC_OBJ_MOVEPROTECT, SDRATTR_OBJMOVEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT, cppu::UnoType<bool>::get(),0, 0}, + { UNO_NAME_MISC_OBJ_BOUNDRECT, OWN_ATTR_BOUNDRECT, cppu::UnoType<css::awt::Rectangle>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_MISC_OBJ_NAME, SDRATTR_OBJECTNAME, cppu::UnoType<OUString>::get(), 0, 0}, + { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, + { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, + { u"Model", OWN_ATTR_OLEMODEL , cppu::UnoType<css::table::XTable>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"TableTemplate", OWN_ATTR_TABLETEMPLATE , cppu::UnoType<css::container::XIndexAccess>::get(), 0, 0}, + { u"UseFirstRowStyle", OWN_ATTR_TABLETEMPLATE_FIRSTROW, cppu::UnoType<bool>::get(),0, 0}, + { u"UseLastRowStyle", OWN_ATTR_TABLETEMPLATE_LASTROW, cppu::UnoType<bool>::get(),0, 0}, + { u"UseFirstColumnStyle", OWN_ATTR_TABLETEMPLATE_FIRSTCOLUMN, cppu::UnoType<bool>::get(),0, 0}, + { u"UseLastColumnStyle", OWN_ATTR_TABLETEMPLATE_LASTCOLUMN, cppu::UnoType<bool>::get(),0, 0}, + { u"UseBandingRowStyle", OWN_ATTR_TABLETEMPLATE_BANDINGROWS, cppu::UnoType<bool>::get(),0, 0}, + { u"UseBandingColumnStyle", OWN_ATTR_TABLETEMPLATE_BANDINGCOLUMNS, cppu::UnoType<bool>::get(),0, 0}, + { u"ReplacementGraphic", OWN_ATTR_REPLACEMENT_GRAPHIC, cppu::UnoType<css::graphic::XGraphic>::get(), css::beans::PropertyAttribute::READONLY, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aTableShapePropertyMap_Impl; +} + +static o3tl::span<comphelper::PropertyMapEntry const> ImplGetSvxDrawingDefaultsPropertyMap() +{ + static comphelper::PropertyMapEntry const aSvxDrawingDefaultsPropertyMap_Impl[] = + { + GLOW_PROPERTIES + SOFTEDGE_PROPERTIES + SHADOW_PROPERTIES + LINE_PROPERTIES_DEFAULTS + FILL_PROPERTIES_BMP + FILL_PROPERTIES_DEFAULTS + EDGERADIUS_PROPERTIES + TEXT_PROPERTIES_DEFAULTS + CONNECTOR_PROPERTIES + SPECIAL_DIMENSIONING_PROPERTIES_DEFAULTS + MISC_3D_OBJ_PROPERTIES + SPECIAL_3DBACKSCALE_PROPERTIES + }; + + return aSvxDrawingDefaultsPropertyMap_Impl; +} + +static o3tl::span<comphelper::PropertyMapEntry const> ImplGetAdditionalWriterDrawingDefaultsPropertyMap() +{ + static comphelper::PropertyMapEntry const aSvxAdditionalDefaultsPropertyMap_Impl[] = + { + { "IsFollowingTextFlow", SID_SW_FOLLOW_TEXT_FLOW, cppu::UnoType<bool>::get(), 0, 0}, + }; + + return aSvxAdditionalDefaultsPropertyMap_Impl; +} + +typedef std::unordered_map< OUString, SdrObjKind > UHashMapImpl; + +namespace { + +const UHashMapImpl& GetUHashImpl() +{ + static UHashMapImpl const aImpl + { + { "com.sun.star.drawing.RectangleShape", SdrObjKind::Rectangle }, + { "com.sun.star.drawing.EllipseShape", SdrObjKind::CircleOrEllipse }, + { "com.sun.star.drawing.ControlShape", SdrObjKind::UNO }, + { "com.sun.star.drawing.ConnectorShape", SdrObjKind::Edge }, + { "com.sun.star.drawing.MeasureShape", SdrObjKind::Measure }, + { "com.sun.star.drawing.LineShape", SdrObjKind::Line }, + { "com.sun.star.drawing.PolyPolygonShape", SdrObjKind::Polygon }, + { "com.sun.star.drawing.PolyLineShape", SdrObjKind::PolyLine }, + { "com.sun.star.drawing.OpenBezierShape", SdrObjKind::PathLine }, + { "com.sun.star.drawing.ClosedBezierShape", SdrObjKind::PathFill }, + { "com.sun.star.drawing.OpenFreeHandShape", SdrObjKind::FreehandLine }, + { "com.sun.star.drawing.ClosedFreeHandShape", SdrObjKind::FreehandFill }, + { "com.sun.star.drawing.PolyPolygonPathShape", SdrObjKind::PathPoly }, + { "com.sun.star.drawing.PolyLinePathShape", SdrObjKind::PathPolyLine }, + { "com.sun.star.drawing.GraphicObjectShape", SdrObjKind::Graphic }, + { "com.sun.star.drawing.GroupShape", SdrObjKind::Group }, + { "com.sun.star.drawing.TextShape", SdrObjKind::Text }, + { "com.sun.star.drawing.OLE2Shape", SdrObjKind::OLE2 }, + { "com.sun.star.drawing.PageShape", SdrObjKind::Page }, + { "com.sun.star.drawing.CaptionShape", SdrObjKind::Caption }, + { "com.sun.star.drawing.FrameShape", SdrObjKind::OLEPluginFrame }, + { "com.sun.star.drawing.PluginShape", SdrObjKind::OLE2Plugin }, + { "com.sun.star.drawing.AppletShape", SdrObjKind::OLE2Applet }, + { "com.sun.star.drawing.CustomShape", SdrObjKind::CustomShape }, + { "com.sun.star.drawing.MediaShape", SdrObjKind::Media }, + + { "com.sun.star.drawing.Shape3DSceneObject", SdrObjKind::E3D_Scene }, + { "com.sun.star.drawing.Shape3DCubeObject", SdrObjKind::E3D_Cube }, + { "com.sun.star.drawing.Shape3DSphereObject", SdrObjKind::E3D_Sphere }, + { "com.sun.star.drawing.Shape3DLatheObject", SdrObjKind::E3D_Lathe }, + { "com.sun.star.drawing.Shape3DExtrudeObject", SdrObjKind::E3D_Extrusion }, + { "com.sun.star.drawing.Shape3DPolygonObject", SdrObjKind::E3D_Polygon }, + }; + + return aImpl; +} + +} + + +OUString UHashMap::getNameFromId(SdrObjKind nId) +{ + const UHashMapImpl &rMap = GetUHashImpl(); + + auto it = std::find_if(rMap.begin(), rMap.end(), + [nId](const UHashMapImpl::value_type& rEntry) { return rEntry.second == nId; }); + if (it != rMap.end()) + return it->first; + OSL_FAIL("[CL] unknown SdrObject identifier"); + return OUString(); +} + +uno::Sequence< OUString > UHashMap::getServiceNames() +{ + return comphelper::mapKeysToSequence( GetUHashImpl() ); +} + +std::optional<SdrObjKind> UHashMap::getId( const OUString& rCompareString ) +{ + const UHashMapImpl &rMap = GetUHashImpl(); + UHashMapImpl::const_iterator it = rMap.find( rCompareString ); + if( it == rMap.end() ) + return {}; + else + return it->second; +} + +SvxUnoPropertyMapProvider& getSvxMapProvider() +{ + static SvxUnoPropertyMapProvider theSvxMapProvider; + return theSvxMapProvider; +} + + +SvxUnoPropertyMapProvider::SvxUnoPropertyMapProvider() +{ + for(sal_uInt16 i=0;i<SVXMAP_END; i++) + { + aSetArr[i] = nullptr; + aMapArr[i] = nullptr; + } +} + +SvxUnoPropertyMapProvider::~SvxUnoPropertyMapProvider() +{ +} + + +const SfxItemPropertyMapEntry* SvxUnoPropertyMapProvider::GetMap(sal_uInt16 nPropertyId) +{ + assert(nPropertyId < SVXMAP_END); + if(!aMapArr[nPropertyId]) { + switch(nPropertyId) { + case SVXMAP_SHAPE: aMapArr[SVXMAP_SHAPE]=ImplGetSvxShapePropertyMap(); break; + case SVXMAP_CONNECTOR: aMapArr[SVXMAP_CONNECTOR]=ImplGetSvxConnectorPropertyMap(); break; + case SVXMAP_DIMENSIONING: aMapArr[SVXMAP_DIMENSIONING]=ImplGetSvxDimensioningPropertyMap(); break; + case SVXMAP_CIRCLE: aMapArr[SVXMAP_CIRCLE]=ImplGetSvxCirclePropertyMap(); break; + case SVXMAP_POLYPOLYGON: aMapArr[SVXMAP_POLYPOLYGON]=ImplGetSvxPolyPolygonPropertyMap(); break; + case SVXMAP_GRAPHICOBJECT: aMapArr[SVXMAP_GRAPHICOBJECT]=ImplGetSvxGraphicObjectPropertyMap(); break; + case SVXMAP_3DSCENEOBJECT: aMapArr[SVXMAP_3DSCENEOBJECT]=ImplGetSvx3DSceneObjectPropertyMap(); break; + case SVXMAP_3DCUBEOBJECT: aMapArr[SVXMAP_3DCUBEOBJECT]=ImplGetSvx3DCubeObjectPropertyMap(); break; + case SVXMAP_3DSPHEREOBJECT: aMapArr[SVXMAP_3DSPHEREOBJECT]=ImplGetSvx3DSphereObjectPropertyMap(); break; + case SVXMAP_3DLATHEOBJECT: aMapArr[SVXMAP_3DLATHEOBJECT]=ImplGetSvx3DLatheObjectPropertyMap(); break; + case SVXMAP_3DEXTRUDEOBJECT: aMapArr[SVXMAP_3DEXTRUDEOBJECT]=ImplGetSvx3DExtrudeObjectPropertyMap(); break; + case SVXMAP_3DPOLYGONOBJECT: aMapArr[SVXMAP_3DPOLYGONOBJECT]=ImplGetSvx3DPolygonObjectPropertyMap(); break; + case SVXMAP_ALL: aMapArr[SVXMAP_ALL]=ImplGetSvxAllPropertyMap(); break; + case SVXMAP_GROUP: aMapArr[SVXMAP_GROUP]=ImplGetSvxGroupPropertyMap(); break; + case SVXMAP_CAPTION: aMapArr[SVXMAP_CAPTION]=ImplGetSvxCaptionPropertyMap(); break; + case SVXMAP_OLE2: aMapArr[SVXMAP_OLE2]=ImplGetSvxOle2PropertyMap(); break; + case SVXMAP_PLUGIN: aMapArr[SVXMAP_PLUGIN]=ImplGetSvxPluginPropertyMap(); break; + case SVXMAP_FRAME: aMapArr[SVXMAP_FRAME]=ImplGetSvxFramePropertyMap(); break; + case SVXMAP_APPLET: aMapArr[SVXMAP_APPLET]=ImplGetSvxAppletPropertyMap(); break; + case SVXMAP_CONTROL: aMapArr[SVXMAP_CONTROL]=ImplGetSvxControlShapePropertyMap(); break; + case SVXMAP_TEXT: aMapArr[SVXMAP_TEXT]=ImplGetSvxTextShapePropertyMap(); break; + case SVXMAP_CUSTOMSHAPE: aMapArr[SVXMAP_CUSTOMSHAPE]=ImplGetSvxCustomShapePropertyMap(); break; + case SVXMAP_MEDIA: aMapArr[SVXMAP_MEDIA]=ImplGetSvxMediaShapePropertyMap(); break; + case SVXMAP_TABLE: aMapArr[SVXMAP_TABLE]=ImplGetSvxTableShapePropertyMap(); break; + case SVXMAP_PAGE: aMapArr[SVXMAP_PAGE] = ImplGetSvxPageShapePropertyMap(); break; + + default: + OSL_FAIL( "Unknown property map for SvxUnoPropertyMapProvider!" ); + } +// Sort(nPropertyId); + } + return aMapArr[nPropertyId]; +} +const SvxItemPropertySet* SvxUnoPropertyMapProvider::GetPropertySet(sal_uInt16 nPropertyId, SfxItemPool& rPool) +{ + if( !aSetArr[nPropertyId] ) + aSetArr[nPropertyId].reset(new SvxItemPropertySet( GetMap( nPropertyId ), rPool )); + return aSetArr[nPropertyId].get(); +} + +/** maps the vcl MapUnit enum to an API constant MeasureUnit. + Returns false if conversion is not supported. +*/ +bool SvxMapUnitToMeasureUnit( const MapUnit eVcl, short& eApi ) noexcept +{ + switch( eVcl ) + { + case MapUnit::Map100thMM: eApi = util::MeasureUnit::MM_100TH; break; + case MapUnit::Map10thMM: eApi = util::MeasureUnit::MM_10TH; break; + case MapUnit::MapMM: eApi = util::MeasureUnit::MM; break; + case MapUnit::MapCM: eApi = util::MeasureUnit::CM; break; + case MapUnit::Map1000thInch: eApi = util::MeasureUnit::INCH_1000TH; break; + case MapUnit::Map100thInch: eApi = util::MeasureUnit::INCH_100TH; break; + case MapUnit::Map10thInch: eApi = util::MeasureUnit::INCH_10TH; break; + case MapUnit::MapInch: eApi = util::MeasureUnit::INCH; break; + case MapUnit::MapPoint: eApi = util::MeasureUnit::POINT; break; + case MapUnit::MapTwip: eApi = util::MeasureUnit::TWIP; break; + case MapUnit::MapRelative: eApi = util::MeasureUnit::PERCENT; break; + default: + return false; + } + + return true; +} + +/** maps the API constant MeasureUnit to a vcl MapUnit enum. + Returns false if conversion is not supported. +*/ + +bool SvxMeasureUnitToFieldUnit( const short eApi, FieldUnit& eVcl ) noexcept +{ + switch( eApi ) + { + case util::MeasureUnit::MM: eVcl = FieldUnit::MM; break; + case util::MeasureUnit::CM: eVcl = FieldUnit::CM; break; + case util::MeasureUnit::M: eVcl = FieldUnit::M; break; + case util::MeasureUnit::KM: eVcl = FieldUnit::KM; break; + case util::MeasureUnit::TWIP: eVcl = FieldUnit::TWIP; break; + case util::MeasureUnit::POINT: eVcl = FieldUnit::POINT; break; + case util::MeasureUnit::PICA: eVcl = FieldUnit::PICA; break; + case util::MeasureUnit::INCH: eVcl = FieldUnit::INCH; break; + case util::MeasureUnit::FOOT: eVcl = FieldUnit::FOOT; break; + case util::MeasureUnit::MILE: eVcl = FieldUnit::MILE; break; + case util::MeasureUnit::PERCENT: eVcl = FieldUnit::PERCENT; break; + case util::MeasureUnit::MM_100TH: eVcl = FieldUnit::MM_100TH; break; + default: + return false; + } + + return true; +} + +/** maps the vcl MapUnit enum to an API constant MeasureUnit. + Returns false if conversion is not supported. +*/ +bool SvxFieldUnitToMeasureUnit( const FieldUnit eVcl, short& eApi ) noexcept +{ + switch( eVcl ) + { + case FieldUnit::MM: eApi = util::MeasureUnit::MM; break; + case FieldUnit::CM: eApi = util::MeasureUnit::CM; break; + case FieldUnit::M: eApi = util::MeasureUnit::M; break; + case FieldUnit::KM: eApi = util::MeasureUnit::KM; break; + case FieldUnit::TWIP: eApi = util::MeasureUnit::TWIP; break; + case FieldUnit::POINT: eApi = util::MeasureUnit::POINT; break; + case FieldUnit::PICA: eApi = util::MeasureUnit::PICA; break; + case FieldUnit::INCH: eApi = util::MeasureUnit::INCH; break; + case FieldUnit::FOOT: eApi = util::MeasureUnit::FOOT; break; + case FieldUnit::MILE: eApi = util::MeasureUnit::MILE; break; + case FieldUnit::PERCENT: eApi = util::MeasureUnit::PERCENT; break; + case FieldUnit::MM_100TH: eApi = util::MeasureUnit::MM_100TH; break; + default: + return false; + } + + return true; +} + +constexpr rtl::OUStringConstExpr RID_SVXSTR_BMP_DEF[] = +{ + RID_SVXSTR_BMP0_DEF, + RID_SVXSTR_BMP1_DEF, + RID_SVXSTR_BMP2_DEF, + RID_SVXSTR_BMP3_DEF, + RID_SVXSTR_BMP4_DEF, + RID_SVXSTR_BMP5_DEF, + RID_SVXSTR_BMP6_DEF, + RID_SVXSTR_BMP7_DEF, + RID_SVXSTR_BMP8_DEF, + RID_SVXSTR_BMP9_DEF, + RID_SVXSTR_BMP10_DEF, + RID_SVXSTR_BMP11_DEF, + RID_SVXSTR_BMP12_DEF, + RID_SVXSTR_BMP13_DEF, + RID_SVXSTR_BMP14_DEF, + RID_SVXSTR_BMP15_DEF, + RID_SVXSTR_BMP16_DEF, + RID_SVXSTR_BMP17_DEF, + RID_SVXSTR_BMP18_DEF, + RID_SVXSTR_BMP19_DEF, + RID_SVXSTR_BMP20_DEF, + RID_SVXSTR_BMP21_DEF, + RID_SVXSTR_BMP22_DEF, + RID_SVXSTR_BMP23_DEF, + RID_SVXSTR_BMP24_DEF, + RID_SVXSTR_BMP25_DEF, + RID_SVXSTR_BMP26_DEF, + RID_SVXSTR_BMP27_DEF, + RID_SVXSTR_BMP28_DEF, + RID_SVXSTR_BMP29_DEF, + RID_SVXSTR_BMP30_DEF, + RID_SVXSTR_BMP31_DEF, + RID_SVXSTR_BMP32_DEF, + RID_SVXSTR_BMP33_DEF, + RID_SVXSTR_BMP34_DEF, + RID_SVXSTR_BMP35_DEF, + RID_SVXSTR_BMP36_DEF, + RID_SVXSTR_BMP37_DEF, + RID_SVXSTR_BMP38_DEF, + RID_SVXSTR_BMP39_DEF, + RID_SVXSTR_BMP40_DEF, + RID_SVXSTR_BMP41_DEF, + RID_SVXSTR_BMP42_DEF, + RID_SVXSTR_BMP43_DEF, + RID_SVXSTR_BMP44_DEF, + RID_SVXSTR_BMP45_DEF, + RID_SVXSTR_BMP46_DEF, + RID_SVXSTR_BMP47_DEF, + RID_SVXSTR_BMP48_DEF, + RID_SVXSTR_BMP49_DEF, + RID_SVXSTR_BMP50_DEF, + RID_SVXSTR_BMP51_DEF, + RID_SVXSTR_BMP52_DEF, + RID_SVXSTR_BMP53_DEF, + RID_SVXSTR_BMP54_DEF, + RID_SVXSTR_BMP55_DEF, + RID_SVXSTR_BMP56_DEF, + RID_SVXSTR_BMP57_DEF, + RID_SVXSTR_BMP58_DEF, + RID_SVXSTR_BMP59_DEF, + RID_SVXSTR_BMP60_DEF, + RID_SVXSTR_BMP61_DEF, + RID_SVXSTR_BMP62_DEF, + RID_SVXSTR_BMP63_DEF, + RID_SVXSTR_BMP64_DEF, + RID_SVXSTR_BMP65_DEF, + RID_SVXSTR_BMP66_DEF, + RID_SVXSTR_BMP67_DEF, + RID_SVXSTR_BMP68_DEF, + RID_SVXSTR_BMP69_DEF, + RID_SVXSTR_BMP70_DEF, + RID_SVXSTR_BMP71_DEF, + RID_SVXSTR_BMP72_DEF, + RID_SVXSTR_BMP73_DEF, + RID_SVXSTR_BMP74_DEF, + RID_SVXSTR_BMP75_DEF, + RID_SVXSTR_BMP76_DEF, + RID_SVXSTR_BMP77_DEF, + RID_SVXSTR_BMP78_DEF, + RID_SVXSTR_BMP79_DEF, + RID_SVXSTR_BMP80_DEF, + RID_SVXSTR_BMP81_DEF, + RID_SVXSTR_BMP82_DEF, + RID_SVXSTR_BMP83_DEF, + RID_SVXSTR_BMP84_DEF, + RID_SVXSTR_BMP85_DEF, + RID_SVXSTR_BMP86_DEF, + RID_SVXSTR_BMP87_DEF, + RID_SVXSTR_BMP88_DEF, + RID_SVXSTR_BMP89_DEF, + RID_SVXSTR_BMP90_DEF, + RID_SVXSTR_BMP91_DEF, + RID_SVXSTR_BMP92_DEF +}; + +const TranslateId RID_SVXSTR_BMP[] = +{ + RID_SVXSTR_BMP0, + RID_SVXSTR_BMP1, + RID_SVXSTR_BMP2, + RID_SVXSTR_BMP3, + RID_SVXSTR_BMP4, + RID_SVXSTR_BMP5, + RID_SVXSTR_BMP6, + RID_SVXSTR_BMP7, + RID_SVXSTR_BMP8, + RID_SVXSTR_BMP9, + RID_SVXSTR_BMP10, + RID_SVXSTR_BMP11, + RID_SVXSTR_BMP12, + RID_SVXSTR_BMP13, + RID_SVXSTR_BMP14, + RID_SVXSTR_BMP15, + RID_SVXSTR_BMP16, + RID_SVXSTR_BMP17, + RID_SVXSTR_BMP18, + RID_SVXSTR_BMP19, + RID_SVXSTR_BMP20, + RID_SVXSTR_BMP21, + RID_SVXSTR_BMP22, + RID_SVXSTR_BMP23, + RID_SVXSTR_BMP24, + RID_SVXSTR_BMP25, + RID_SVXSTR_BMP26, + RID_SVXSTR_BMP27, + RID_SVXSTR_BMP28, + RID_SVXSTR_BMP29, + RID_SVXSTR_BMP30, + RID_SVXSTR_BMP31, + RID_SVXSTR_BMP32, + RID_SVXSTR_BMP33, + RID_SVXSTR_BMP34, + RID_SVXSTR_BMP35, + RID_SVXSTR_BMP36, + RID_SVXSTR_BMP37, + RID_SVXSTR_BMP38, + RID_SVXSTR_BMP39, + RID_SVXSTR_BMP40, + RID_SVXSTR_BMP41, + RID_SVXSTR_BMP42, + RID_SVXSTR_BMP43, + RID_SVXSTR_BMP44, + RID_SVXSTR_BMP45, + RID_SVXSTR_BMP46, + RID_SVXSTR_BMP47, + RID_SVXSTR_BMP48, + RID_SVXSTR_BMP49, + RID_SVXSTR_BMP50, + RID_SVXSTR_BMP51, + RID_SVXSTR_BMP52, + RID_SVXSTR_BMP53, + RID_SVXSTR_BMP54, + RID_SVXSTR_BMP55, + RID_SVXSTR_BMP56, + RID_SVXSTR_BMP57, + RID_SVXSTR_BMP58, + RID_SVXSTR_BMP59, + RID_SVXSTR_BMP60, + RID_SVXSTR_BMP61, + RID_SVXSTR_BMP62, + RID_SVXSTR_BMP63, + RID_SVXSTR_BMP64, + RID_SVXSTR_BMP65, + RID_SVXSTR_BMP66, + RID_SVXSTR_BMP67, + RID_SVXSTR_BMP68, + RID_SVXSTR_BMP69, + RID_SVXSTR_BMP70, + RID_SVXSTR_BMP71, + RID_SVXSTR_BMP72, + RID_SVXSTR_BMP73, + RID_SVXSTR_BMP74, + RID_SVXSTR_BMP75, + RID_SVXSTR_BMP76, + RID_SVXSTR_BMP77, + RID_SVXSTR_BMP78, + RID_SVXSTR_BMP79, + RID_SVXSTR_BMP80, + RID_SVXSTR_BMP81, + RID_SVXSTR_BMP82, + RID_SVXSTR_BMP83, + RID_SVXSTR_BMP84, + RID_SVXSTR_BMP85, + RID_SVXSTR_BMP86, + RID_SVXSTR_BMP87, + RID_SVXSTR_BMP88, + RID_SVXSTR_BMP89, + RID_SVXSTR_BMP90, + RID_SVXSTR_BMP91, + RID_SVXSTR_BMP92 +}; + +constexpr rtl::OUStringConstExpr RID_SVXSTR_DASH_DEF[] = +{ + RID_SVXSTR_DASH0_DEF, + RID_SVXSTR_DASH1_DEF, + RID_SVXSTR_DASH2_DEF, + RID_SVXSTR_DASH3_DEF, + RID_SVXSTR_DASH4_DEF, + RID_SVXSTR_DASH5_DEF, + RID_SVXSTR_DASH6_DEF, + RID_SVXSTR_DASH7_DEF, + RID_SVXSTR_DASH8_DEF, + RID_SVXSTR_DASH9_DEF, + RID_SVXSTR_DASH10_DEF, + RID_SVXSTR_DASH11_DEF, + RID_SVXSTR_DASH12_DEF, + RID_SVXSTR_DASH13_DEF, + RID_SVXSTR_DASH14_DEF, + RID_SVXSTR_DASH15_DEF, + RID_SVXSTR_DASH16_DEF, + RID_SVXSTR_DASH17_DEF, + RID_SVXSTR_DASH18_DEF, + RID_SVXSTR_DASH19_DEF, + RID_SVXSTR_DASH20_DEF, + RID_SVXSTR_DASH21_DEF, + RID_SVXSTR_DASH22_DEF, + RID_SVXSTR_DASH23_DEF, + RID_SVXSTR_DASH24_DEF, + RID_SVXSTR_DASH25_DEF, + RID_SVXSTR_DASH26_DEF, + RID_SVXSTR_DASH27_DEF, + RID_SVXSTR_DASH28_DEF, + RID_SVXSTR_DASH29_DEF, + RID_SVXSTR_DASH30_DEF + +}; + +const TranslateId RID_SVXSTR_DASH[] = +{ + RID_SVXSTR_DASH0, + RID_SVXSTR_DASH1, + RID_SVXSTR_DASH2, + RID_SVXSTR_DASH3, + RID_SVXSTR_DASH4, + RID_SVXSTR_DASH5, + RID_SVXSTR_DASH6, + RID_SVXSTR_DASH7, + RID_SVXSTR_DASH8, + RID_SVXSTR_DASH9, + RID_SVXSTR_DASH10, + RID_SVXSTR_DASH11, + RID_SVXSTR_DASH12, + RID_SVXSTR_DASH13, + RID_SVXSTR_DASH14, + RID_SVXSTR_DASH15, + RID_SVXSTR_DASH16, + RID_SVXSTR_DASH17, + RID_SVXSTR_DASH18, + RID_SVXSTR_DASH19, + RID_SVXSTR_DASH20, + RID_SVXSTR_DASH21, + RID_SVXSTR_DASH22, + RID_SVXSTR_DASH23, + RID_SVXSTR_DASH24, + RID_SVXSTR_DASH25, + RID_SVXSTR_DASH26, + RID_SVXSTR_DASH27, + RID_SVXSTR_DASH28, + RID_SVXSTR_DASH29, + RID_SVXSTR_DASH30 +}; + +constexpr rtl::OUStringConstExpr RID_SVXSTR_LEND_DEF[] = +{ + RID_SVXSTR_LEND0_DEF, + RID_SVXSTR_LEND1_DEF, + RID_SVXSTR_LEND2_DEF, + RID_SVXSTR_LEND3_DEF, + RID_SVXSTR_LEND4_DEF, + RID_SVXSTR_LEND5_DEF, + RID_SVXSTR_LEND6_DEF, + RID_SVXSTR_LEND7_DEF, + RID_SVXSTR_LEND8_DEF, + RID_SVXSTR_LEND9_DEF, + RID_SVXSTR_LEND10_DEF, + RID_SVXSTR_LEND11_DEF, + RID_SVXSTR_LEND12_DEF, + RID_SVXSTR_LEND13_DEF, + RID_SVXSTR_LEND14_DEF, + RID_SVXSTR_LEND15_DEF, + RID_SVXSTR_LEND16_DEF, + RID_SVXSTR_LEND17_DEF, + RID_SVXSTR_LEND18_DEF, + RID_SVXSTR_LEND19_DEF, + RID_SVXSTR_LEND20_DEF, + RID_SVXSTR_LEND21_DEF, + RID_SVXSTR_LEND22_DEF, + RID_SVXSTR_LEND23_DEF, + RID_SVXSTR_LEND24_DEF, + RID_SVXSTR_LEND25_DEF, + RID_SVXSTR_LEND26_DEF, + RID_SVXSTR_LEND27_DEF, + RID_SVXSTR_LEND28_DEF, + RID_SVXSTR_LEND29_DEF, + RID_SVXSTR_LEND30_DEF, + RID_SVXSTR_LEND31_DEF +}; + +const TranslateId RID_SVXSTR_LEND[] = +{ + RID_SVXSTR_LEND0, + RID_SVXSTR_LEND1, + RID_SVXSTR_LEND2, + RID_SVXSTR_LEND3, + RID_SVXSTR_LEND4, + RID_SVXSTR_LEND5, + RID_SVXSTR_LEND6, + RID_SVXSTR_LEND7, + RID_SVXSTR_LEND8, + RID_SVXSTR_LEND9, + RID_SVXSTR_LEND10, + RID_SVXSTR_LEND11, + RID_SVXSTR_LEND12, + RID_SVXSTR_LEND13, + RID_SVXSTR_LEND14, + RID_SVXSTR_LEND15, + RID_SVXSTR_LEND16, + RID_SVXSTR_LEND17, + RID_SVXSTR_LEND18, + RID_SVXSTR_LEND19, + RID_SVXSTR_LEND20, + RID_SVXSTR_LEND21, + RID_SVXSTR_LEND22, + RID_SVXSTR_LEND23, + RID_SVXSTR_LEND24, + RID_SVXSTR_LEND25, + RID_SVXSTR_LEND26, + RID_SVXSTR_LEND27, + RID_SVXSTR_LEND28, + RID_SVXSTR_LEND29, + RID_SVXSTR_LEND30, + RID_SVXSTR_LEND31 +}; + +constexpr rtl::OUStringConstExpr RID_SVXSTR_GRDT_DEF[] = +{ + RID_SVXSTR_GRDT0_DEF, + RID_SVXSTR_GRDT1_DEF, + RID_SVXSTR_GRDT2_DEF, + RID_SVXSTR_GRDT3_DEF, + RID_SVXSTR_GRDT4_DEF, + RID_SVXSTR_GRDT5_DEF, + RID_SVXSTR_GRDT6_DEF, + RID_SVXSTR_GRDT7_DEF, + RID_SVXSTR_GRDT8_DEF, + RID_SVXSTR_GRDT9_DEF, + RID_SVXSTR_GRDT10_DEF, + RID_SVXSTR_GRDT11_DEF, + RID_SVXSTR_GRDT12_DEF, + RID_SVXSTR_GRDT13_DEF, + RID_SVXSTR_GRDT14_DEF, + RID_SVXSTR_GRDT15_DEF, + RID_SVXSTR_GRDT16_DEF, + RID_SVXSTR_GRDT17_DEF, + RID_SVXSTR_GRDT18_DEF, + RID_SVXSTR_GRDT19_DEF, + RID_SVXSTR_GRDT20_DEF, + RID_SVXSTR_GRDT21_DEF, + RID_SVXSTR_GRDT22_DEF, + RID_SVXSTR_GRDT23_DEF, + RID_SVXSTR_GRDT24_DEF, + RID_SVXSTR_GRDT25_DEF, + RID_SVXSTR_GRDT26_DEF, + RID_SVXSTR_GRDT27_DEF, + RID_SVXSTR_GRDT28_DEF, + RID_SVXSTR_GRDT29_DEF, + RID_SVXSTR_GRDT30_DEF, + RID_SVXSTR_GRDT31_DEF, + RID_SVXSTR_GRDT32_DEF, + RID_SVXSTR_GRDT33_DEF, + RID_SVXSTR_GRDT34_DEF, + RID_SVXSTR_GRDT35_DEF, + RID_SVXSTR_GRDT36_DEF, + RID_SVXSTR_GRDT37_DEF, + RID_SVXSTR_GRDT38_DEF, + RID_SVXSTR_GRDT39_DEF, + RID_SVXSTR_GRDT40_DEF, + RID_SVXSTR_GRDT41_DEF, + RID_SVXSTR_GRDT42_DEF, + RID_SVXSTR_GRDT43_DEF, + RID_SVXSTR_GRDT44_DEF, + RID_SVXSTR_GRDT45_DEF, + RID_SVXSTR_GRDT46_DEF, + RID_SVXSTR_GRDT47_DEF, + RID_SVXSTR_GRDT48_DEF, + RID_SVXSTR_GRDT49_DEF, + RID_SVXSTR_GRDT50_DEF, + RID_SVXSTR_GRDT51_DEF, + RID_SVXSTR_GRDT52_DEF, + RID_SVXSTR_GRDT53_DEF, + RID_SVXSTR_GRDT54_DEF, + RID_SVXSTR_GRDT55_DEF, + RID_SVXSTR_GRDT56_DEF, + RID_SVXSTR_GRDT57_DEF, + RID_SVXSTR_GRDT58_DEF, + RID_SVXSTR_GRDT59_DEF, + RID_SVXSTR_GRDT60_DEF, + RID_SVXSTR_GRDT61_DEF, + RID_SVXSTR_GRDT62_DEF, + RID_SVXSTR_GRDT63_DEF, + RID_SVXSTR_GRDT64_DEF, + RID_SVXSTR_GRDT65_DEF, + RID_SVXSTR_GRDT66_DEF, + RID_SVXSTR_GRDT67_DEF, + RID_SVXSTR_GRDT68_DEF, + RID_SVXSTR_GRDT69_DEF, + RID_SVXSTR_GRDT70_DEF, + RID_SVXSTR_GRDT71_DEF, + RID_SVXSTR_GRDT72_DEF, + RID_SVXSTR_GRDT73_DEF, + RID_SVXSTR_GRDT74_DEF, + RID_SVXSTR_GRDT75_DEF, + RID_SVXSTR_GRDT76_DEF, + RID_SVXSTR_GRDT77_DEF, + RID_SVXSTR_GRDT78_DEF, + RID_SVXSTR_GRDT79_DEF, + RID_SVXSTR_GRDT80_DEF, + RID_SVXSTR_GRDT81_DEF, + RID_SVXSTR_GRDT82_DEF, + RID_SVXSTR_GRDT83_DEF, + RID_SVXSTR_GRDT84_DEF +}; + +const TranslateId RID_SVXSTR_GRDT[] = +{ + RID_SVXSTR_GRDT0, + RID_SVXSTR_GRDT1, + RID_SVXSTR_GRDT2, + RID_SVXSTR_GRDT3, + RID_SVXSTR_GRDT4, + RID_SVXSTR_GRDT5, + RID_SVXSTR_GRDT6, + RID_SVXSTR_GRDT7, + RID_SVXSTR_GRDT8, + RID_SVXSTR_GRDT9, + RID_SVXSTR_GRDT10, + RID_SVXSTR_GRDT11, + RID_SVXSTR_GRDT12, + RID_SVXSTR_GRDT13, + RID_SVXSTR_GRDT14, + RID_SVXSTR_GRDT15, + RID_SVXSTR_GRDT16, + RID_SVXSTR_GRDT17, + RID_SVXSTR_GRDT18, + RID_SVXSTR_GRDT19, + RID_SVXSTR_GRDT20, + RID_SVXSTR_GRDT21, + RID_SVXSTR_GRDT22, + RID_SVXSTR_GRDT23, + RID_SVXSTR_GRDT24, + RID_SVXSTR_GRDT25, + RID_SVXSTR_GRDT26, + RID_SVXSTR_GRDT27, + RID_SVXSTR_GRDT28, + RID_SVXSTR_GRDT29, + RID_SVXSTR_GRDT30, + RID_SVXSTR_GRDT31, + RID_SVXSTR_GRDT32, + RID_SVXSTR_GRDT33, + RID_SVXSTR_GRDT34, + RID_SVXSTR_GRDT35, + RID_SVXSTR_GRDT36, + RID_SVXSTR_GRDT37, + RID_SVXSTR_GRDT38, + RID_SVXSTR_GRDT39, + RID_SVXSTR_GRDT40, + RID_SVXSTR_GRDT41, + RID_SVXSTR_GRDT42, + RID_SVXSTR_GRDT43, + RID_SVXSTR_GRDT44, + RID_SVXSTR_GRDT45, + RID_SVXSTR_GRDT46, + RID_SVXSTR_GRDT47, + RID_SVXSTR_GRDT48, + RID_SVXSTR_GRDT49, + RID_SVXSTR_GRDT50, + RID_SVXSTR_GRDT51, + RID_SVXSTR_GRDT52, + RID_SVXSTR_GRDT53, + RID_SVXSTR_GRDT54, + RID_SVXSTR_GRDT55, + RID_SVXSTR_GRDT56, + RID_SVXSTR_GRDT57, + RID_SVXSTR_GRDT58, + RID_SVXSTR_GRDT59, + RID_SVXSTR_GRDT60, + RID_SVXSTR_GRDT61, + RID_SVXSTR_GRDT62, + RID_SVXSTR_GRDT63, + RID_SVXSTR_GRDT64, + RID_SVXSTR_GRDT65, + RID_SVXSTR_GRDT66, + RID_SVXSTR_GRDT67, + RID_SVXSTR_GRDT68, + RID_SVXSTR_GRDT69, + RID_SVXSTR_GRDT70, + RID_SVXSTR_GRDT71, + RID_SVXSTR_GRDT72, + RID_SVXSTR_GRDT73, + RID_SVXSTR_GRDT74, + RID_SVXSTR_GRDT75, + RID_SVXSTR_GRDT76, + RID_SVXSTR_GRDT77, + RID_SVXSTR_GRDT78, + RID_SVXSTR_GRDT79, + RID_SVXSTR_GRDT80, + RID_SVXSTR_GRDT81, + RID_SVXSTR_GRDT82, + RID_SVXSTR_GRDT83, + RID_SVXSTR_GRDT84 +}; + +constexpr rtl::OUStringConstExpr RID_SVXSTR_HATCHS_DEF[] = +{ + RID_SVXSTR_HATCH0_DEF, + RID_SVXSTR_HATCH1_DEF, + RID_SVXSTR_HATCH2_DEF, + RID_SVXSTR_HATCH3_DEF, + RID_SVXSTR_HATCH4_DEF, + RID_SVXSTR_HATCH5_DEF, + RID_SVXSTR_HATCH6_DEF, + RID_SVXSTR_HATCH7_DEF, + RID_SVXSTR_HATCH8_DEF, + RID_SVXSTR_HATCH9_DEF, + RID_SVXSTR_HATCH10_DEF, + RID_SVXSTR_HATCH11_DEF, + RID_SVXSTR_HATCH12_DEF, + RID_SVXSTR_HATCH13_DEF, + RID_SVXSTR_HATCH14_DEF, + RID_SVXSTR_HATCH15_DEF +}; + +const TranslateId RID_SVXSTR_HATCHS[] = +{ + RID_SVXSTR_HATCH0, + RID_SVXSTR_HATCH1, + RID_SVXSTR_HATCH2, + RID_SVXSTR_HATCH3, + RID_SVXSTR_HATCH4, + RID_SVXSTR_HATCH5, + RID_SVXSTR_HATCH6, + RID_SVXSTR_HATCH7, + RID_SVXSTR_HATCH8, + RID_SVXSTR_HATCH9, + RID_SVXSTR_HATCH10, + RID_SVXSTR_HATCH11, + RID_SVXSTR_HATCH12, + RID_SVXSTR_HATCH13, + RID_SVXSTR_HATCH14, + RID_SVXSTR_HATCH15 +}; + +constexpr rtl::OUStringConstExpr RID_SVXSTR_TRASNGR_DEF[] = +{ + RID_SVXSTR_TRASNGR0_DEF +}; + +const TranslateId RID_SVXSTR_TRASNGR[] = +{ + RID_SVXSTR_TRASNGR0 +}; + +static bool SvxUnoGetResourceRanges( const sal_uInt16 nWhich, const rtl::OUStringConstExpr*& pApiResIds, const TranslateId*& pIntResIds, int& nCount ) noexcept +{ + switch( nWhich ) + { + case XATTR_FILLBITMAP: + pApiResIds = RID_SVXSTR_BMP_DEF; + pIntResIds = RID_SVXSTR_BMP; + nCount = SAL_N_ELEMENTS(RID_SVXSTR_BMP_DEF); + break; + case XATTR_LINEDASH: + pApiResIds = RID_SVXSTR_DASH_DEF; + pIntResIds = RID_SVXSTR_DASH; + nCount = SAL_N_ELEMENTS(RID_SVXSTR_DASH_DEF); + break; + + case XATTR_LINESTART: + case XATTR_LINEEND: + pApiResIds = RID_SVXSTR_LEND_DEF; + pIntResIds = RID_SVXSTR_LEND; + nCount = SAL_N_ELEMENTS(RID_SVXSTR_LEND_DEF); + break; + + case XATTR_FILLGRADIENT: + pApiResIds = RID_SVXSTR_GRDT_DEF; + pIntResIds = RID_SVXSTR_GRDT; + nCount = SAL_N_ELEMENTS(RID_SVXSTR_GRDT_DEF); + break; + + case XATTR_FILLHATCH: + pApiResIds = RID_SVXSTR_HATCHS_DEF; + pIntResIds = RID_SVXSTR_HATCHS; + nCount = SAL_N_ELEMENTS(RID_SVXSTR_HATCHS_DEF); + break; + + case XATTR_FILLFLOATTRANSPARENCE: + pApiResIds = RID_SVXSTR_TRASNGR_DEF; + pIntResIds = RID_SVXSTR_TRASNGR; + nCount = SAL_N_ELEMENTS(RID_SVXSTR_TRASNGR_DEF); + break; + + default: + return false; + } + return true; +} + +/// @throws std::exception +static bool SvxUnoConvertResourceStringToApi(const TranslateId* pSourceResIds, const rtl::OUStringConstExpr* pDestResIds, int nCount, OUString& rString) +{ + // first, calculate the search string length without an optional number after the name + sal_Int32 nLength = rString.getLength(); + while( nLength > 0 ) + { + const sal_Unicode nChar = rString[ nLength - 1 ]; + if( (nChar < '0') || (nChar > '9') ) + break; + + nLength--; + } + + // if we cut off a number, also cut of some spaces + if( nLength != rString.getLength() ) + { + while( nLength > 0 ) + { + const sal_Unicode nChar = rString[ nLength - 1 ]; + if( nChar != ' ' ) + break; + + nLength--; + } + } + + const std::u16string_view aShortString( rString.subView( 0, nLength ) ); + + for (int i = 0; i < nCount; ++i) + { + const OUString & aCompare = SvxResId(pSourceResIds[i]); + if( aShortString == aCompare ) + { + rString = rString.replaceAt( 0, aShortString.size(), OUString(pDestResIds[i]) ); + return true; + } + else if( rString == aCompare ) + { + rString = pDestResIds[i]; + return true; + } + } + + return false; +} + +static bool SvxUnoConvertResourceStringFromApi(const rtl::OUStringConstExpr* pSourceResIds, const TranslateId* pDestResIds, int nCount, OUString& rString) +{ + // first, calculate the search string length without an optional number after the name + sal_Int32 nLength = rString.getLength(); + while( nLength > 0 ) + { + const sal_Unicode nChar = rString[ nLength - 1 ]; + if( (nChar < '0') || (nChar > '9') ) + break; + + nLength--; + } + + // if we cut off a number, also cut of some spaces + if( nLength != rString.getLength() ) + { + while( nLength > 0 ) + { + const sal_Unicode nChar = rString[ nLength - 1 ]; + if( nChar != ' ' ) + break; + + nLength--; + } + } + + const std::u16string_view aShortString( rString.subView( 0, nLength ) ); + + for (int i = 0; i < nCount; ++i) + { + auto pCompare = pSourceResIds[i]; + if( aShortString == pCompare.asView() ) + { + rString = rString.replaceAt( 0, aShortString.size(), SvxResId(pDestResIds[i]) ); + return true; + } + else if( rString == pCompare ) + { + rString = SvxResId(pDestResIds[i]); + return true; + } + } + + return false; +} + +// #i122649# Some comments on the below arrays: +// - They need to have the same order and count of items +// - They are used to translate between translated and non-translated color names +// - To make longer names be found which start with the same basic string, +// these have to be in front of others + +// It would be nice to: +// - evtl. organize these in a single array with 2-dimensional inner to eliminate +// the possibility to define it wrong +// - change the compare to also work when a shorter name is in front of a longer one + +constexpr rtl::OUStringConstExpr SvxUnoColorNameDefResId[] = +{ + RID_SVXSTR_COLOR_BLUEGREY_DEF, + RID_SVXSTR_COLOR_BLACK_DEF, + RID_SVXSTR_COLOR_BLUE_CLASSIC_DEF, + RID_SVXSTR_COLOR_BLUE_DEF, + RID_SVXSTR_COLOR_GREEN_DEF, + RID_SVXSTR_COLOR_RED_DEF, + RID_SVXSTR_COLOR_MAGENTA_DEF, + RID_SVXSTR_COLOR_GREY_DEF, + RID_SVXSTR_COLOR_YELLOWGREEN_DEF, + RID_SVXSTR_COLOR_YELLOW_DEF, + RID_SVXSTR_COLOR_WHITE_DEF, + RID_SVXSTR_COLOR_ORANGE_DEF, + RID_SVXSTR_COLOR_BORDEAUX_DEF, + RID_SVXSTR_COLOR_PALE_YELLOW_DEF, + RID_SVXSTR_COLOR_PALE_GREEN_DEF, + RID_SVXSTR_COLOR_DARKVIOLET_DEF, + RID_SVXSTR_COLOR_SALMON_DEF, + RID_SVXSTR_COLOR_SEABLUE_DEF, + RID_SVXSTR_COLOR_CHART_DEF, + RID_SVXSTR_COLOR_PURPLE_DEF, + RID_SVXSTR_COLOR_SKYBLUE_DEF, + RID_SVXSTR_COLOR_PINK_DEF, + RID_SVXSTR_COLOR_TURQUOISE_DEF, + RID_SVXSTR_COLOR_GOLD_DEF, + RID_SVXSTR_COLOR_BRICK_DEF, + RID_SVXSTR_COLOR_INDIGO_DEF, + RID_SVXSTR_COLOR_TEAL_DEF, + RID_SVXSTR_COLOR_LIME_DEF, + RID_SVXSTR_COLOR_LIGHTGRAY_DEF, + RID_SVXSTR_COLOR_LIGHTYELLOW_DEF, + RID_SVXSTR_COLOR_LIGHTGOLD_DEF, + RID_SVXSTR_COLOR_LIGHTORANGE_DEF, + RID_SVXSTR_COLOR_LIGHTBRICK_DEF, + RID_SVXSTR_COLOR_LIGHTRED_DEF, + RID_SVXSTR_COLOR_LIGHTMAGENTA_DEF, + RID_SVXSTR_COLOR_LIGHTPURPLE_DEF, + RID_SVXSTR_COLOR_LIGHTINDIGO_DEF, + RID_SVXSTR_COLOR_LIGHTBLUE_DEF, + RID_SVXSTR_COLOR_LIGHTTEAL_DEF, + RID_SVXSTR_COLOR_LIGHTGREEN_DEF, + RID_SVXSTR_COLOR_LIGHTLIME_DEF, + RID_SVXSTR_COLOR_DARKGRAY_DEF, + RID_SVXSTR_COLOR_DARKYELLOW_DEF, + RID_SVXSTR_COLOR_DARKGOLD_DEF, + RID_SVXSTR_COLOR_DARKORANGE_DEF, + RID_SVXSTR_COLOR_DARKBRICK_DEF, + RID_SVXSTR_COLOR_DARKRED_DEF, + RID_SVXSTR_COLOR_DARKMAGENTA_DEF, + RID_SVXSTR_COLOR_DARKPURPLE_DEF, + RID_SVXSTR_COLOR_DARKINDIGO_DEF, + RID_SVXSTR_COLOR_DARKBLUE_DEF, + RID_SVXSTR_COLOR_DARKTEAL_DEF, + RID_SVXSTR_COLOR_DARKGREEN_DEF, + RID_SVXSTR_COLOR_DARKLIME_DEF, + RID_SVXSTR_COLOR_VIOLET_DEF, + RID_SVXSTR_COLOR_VIOLET_OUG_DEF, + RID_SVXSTR_COLOR_BLUE_OUG_DEF, + RID_SVXSTR_COLOR_AZURE_OUG_DEF, + RID_SVXSTR_COLOR_SPRINGGREEN_OUG_DEF, + RID_SVXSTR_COLOR_GREEN_OUG_DEF, + RID_SVXSTR_COLOR_CHARTREUSEGREEN_OUG_DEF, + RID_SVXSTR_COLOR_ORANGE_OUG_DEF, + RID_SVXSTR_COLOR_RED_OUG_DEF, + RID_SVXSTR_COLOR_ROSE_OUG_DEF, + RID_SVXSTR_COLOR_AZURE_DEF, + RID_SVXSTR_COLOR_CYAN_DEF, + RID_SVXSTR_COLOR_SPRINGGREEN_DEF, + RID_SVXSTR_COLOR_CHARTREUSEGREEN_DEF, + RID_SVXSTR_COLOR_ROSE_DEF, + RID_SVXSTR_COLOR_MATERIAL_GRAY_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_YELLOW_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_AMBER_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_AMBER_DEF, + RID_SVXSTR_COLOR_MATERIAL_ORANGE_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_DEEP_ORANGE_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_DEEP_ORANGE_DEF, + RID_SVXSTR_COLOR_MATERIAL_RED_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_PINK_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_PURPLE_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_DEEP_PURPLE_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_DEEP_PURPLE_DEF, + RID_SVXSTR_COLOR_MATERIAL_INDIGO_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_BLUE_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_LIGHT_BLUE_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_CYAN_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_TEAL_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_GREEN_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_LIGHT_GREEN_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_LIME_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_BROWN_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_BROWN_DEF, + RID_SVXSTR_COLOR_MATERIAL_BLUE_GRAY_A_DEF, + RID_SVXSTR_COLOR_MATERIAL_BLUE_GRAY_DEF, + RID_SVXSTR_COLOR_LIBRE_GREEN_1_DEF, + RID_SVXSTR_COLOR_LIBRE_GREEN_ACCENT_DEF, + RID_SVXSTR_COLOR_LIBRE_BLUE_ACCENT_DEF, + RID_SVXSTR_COLOR_LIBRE_ORANGE_ACCENT_DEF, + RID_SVXSTR_COLOR_LIBRE_PURPLE_DEF, + RID_SVXSTR_COLOR_LIBRE_PURPLE_ACCENT_DEF, + RID_SVXSTR_COLOR_LIBRE_YELLOW_ACCENT_DEF +}; + +const TranslateId SvxUnoColorNameResId[] = +{ + RID_SVXSTR_COLOR_BLUEGREY, + RID_SVXSTR_COLOR_BLACK, + RID_SVXSTR_COLOR_BLUE_CLASSIC, + RID_SVXSTR_COLOR_BLUE, + RID_SVXSTR_COLOR_GREEN, + RID_SVXSTR_COLOR_RED, + RID_SVXSTR_COLOR_MAGENTA, + RID_SVXSTR_COLOR_GREY, + RID_SVXSTR_COLOR_YELLOWGREEN, + RID_SVXSTR_COLOR_YELLOW, + RID_SVXSTR_COLOR_WHITE, + RID_SVXSTR_COLOR_ORANGE, + RID_SVXSTR_COLOR_BORDEAUX, + RID_SVXSTR_COLOR_PALE_YELLOW, + RID_SVXSTR_COLOR_PALE_GREEN, + RID_SVXSTR_COLOR_DARKVIOLET, + RID_SVXSTR_COLOR_SALMON, + RID_SVXSTR_COLOR_SEABLUE, + RID_SVXSTR_COLOR_CHART, + RID_SVXSTR_COLOR_PURPLE, + RID_SVXSTR_COLOR_SKYBLUE, + RID_SVXSTR_COLOR_PINK, + RID_SVXSTR_COLOR_TURQUOISE, + RID_SVXSTR_COLOR_GOLD, + RID_SVXSTR_COLOR_BRICK, + RID_SVXSTR_COLOR_INDIGO, + RID_SVXSTR_COLOR_TEAL, + RID_SVXSTR_COLOR_LIME, + RID_SVXSTR_COLOR_LIGHTGRAY, + RID_SVXSTR_COLOR_LIGHTYELLOW, + RID_SVXSTR_COLOR_LIGHTGOLD, + RID_SVXSTR_COLOR_LIGHTORANGE, + RID_SVXSTR_COLOR_LIGHTBRICK, + RID_SVXSTR_COLOR_LIGHTRED, + RID_SVXSTR_COLOR_LIGHTMAGENTA, + RID_SVXSTR_COLOR_LIGHTPURPLE, + RID_SVXSTR_COLOR_LIGHTINDIGO, + RID_SVXSTR_COLOR_LIGHTBLUE, + RID_SVXSTR_COLOR_LIGHTTEAL, + RID_SVXSTR_COLOR_LIGHTGREEN, + RID_SVXSTR_COLOR_LIGHTLIME, + RID_SVXSTR_COLOR_DARKGRAY, + RID_SVXSTR_COLOR_DARKYELLOW, + RID_SVXSTR_COLOR_DARKGOLD, + RID_SVXSTR_COLOR_DARKORANGE, + RID_SVXSTR_COLOR_DARKBRICK, + RID_SVXSTR_COLOR_DARKRED, + RID_SVXSTR_COLOR_DARKMAGENTA, + RID_SVXSTR_COLOR_DARKPURPLE, + RID_SVXSTR_COLOR_DARKINDIGO, + RID_SVXSTR_COLOR_DARKBLUE, + RID_SVXSTR_COLOR_DARKTEAL, + RID_SVXSTR_COLOR_DARKGREEN, + RID_SVXSTR_COLOR_DARKLIME, + RID_SVXSTR_COLOR_VIOLET, + RID_SVXSTR_COLOR_VIOLET_OUG, + RID_SVXSTR_COLOR_BLUE_OUG, + RID_SVXSTR_COLOR_AZURE_OUG, + RID_SVXSTR_COLOR_SPRINGGREEN_OUG, + RID_SVXSTR_COLOR_GREEN_OUG, + RID_SVXSTR_COLOR_CHARTREUSEGREEN_OUG, + RID_SVXSTR_COLOR_ORANGE_OUG, + RID_SVXSTR_COLOR_RED_OUG, + RID_SVXSTR_COLOR_ROSE_OUG, + RID_SVXSTR_COLOR_AZURE, + RID_SVXSTR_COLOR_CYAN, + RID_SVXSTR_COLOR_SPRINGGREEN, + RID_SVXSTR_COLOR_CHARTREUSEGREEN, + RID_SVXSTR_COLOR_ROSE, + RID_SVXSTR_COLOR_MATERIAL_GRAY_A, + RID_SVXSTR_COLOR_MATERIAL_YELLOW_A, + RID_SVXSTR_COLOR_MATERIAL_AMBER_A, + RID_SVXSTR_COLOR_MATERIAL_AMBER, + RID_SVXSTR_COLOR_MATERIAL_ORANGE_A, + RID_SVXSTR_COLOR_MATERIAL_DEEP_ORANGE_A, + RID_SVXSTR_COLOR_MATERIAL_DEEP_ORANGE, + RID_SVXSTR_COLOR_MATERIAL_RED_A, + RID_SVXSTR_COLOR_MATERIAL_PINK_A, + RID_SVXSTR_COLOR_MATERIAL_PURPLE_A, + RID_SVXSTR_COLOR_MATERIAL_DEEP_PURPLE_A, + RID_SVXSTR_COLOR_MATERIAL_DEEP_PURPLE, + RID_SVXSTR_COLOR_MATERIAL_INDIGO_A, + RID_SVXSTR_COLOR_MATERIAL_BLUE_A, + RID_SVXSTR_COLOR_MATERIAL_LIGHT_BLUE_A, + RID_SVXSTR_COLOR_MATERIAL_CYAN_A, + RID_SVXSTR_COLOR_MATERIAL_TEAL_A, + RID_SVXSTR_COLOR_MATERIAL_GREEN_A, + RID_SVXSTR_COLOR_MATERIAL_LIGHT_GREEN_A, + RID_SVXSTR_COLOR_MATERIAL_LIME_A, + RID_SVXSTR_COLOR_MATERIAL_BROWN_A, + RID_SVXSTR_COLOR_MATERIAL_BROWN, + RID_SVXSTR_COLOR_MATERIAL_BLUE_GRAY_A, + RID_SVXSTR_COLOR_MATERIAL_BLUE_GRAY, + RID_SVXSTR_COLOR_LIBRE_GREEN_1, + RID_SVXSTR_COLOR_LIBRE_GREEN_ACCENT, + RID_SVXSTR_COLOR_LIBRE_BLUE_ACCENT, + RID_SVXSTR_COLOR_LIBRE_ORANGE_ACCENT, + RID_SVXSTR_COLOR_LIBRE_PURPLE, + RID_SVXSTR_COLOR_LIBRE_PURPLE_ACCENT, + RID_SVXSTR_COLOR_LIBRE_YELLOW_ACCENT +}; + +/// @throws std::exception +static bool SvxUnoConvertResourceStringBuiltInToApi(const TranslateId* pSourceResIds, rtl::OUStringConstExpr const *pDestResIds, int nCount, OUString& rString) +{ + //We replace e.g. "Gray 10%" with the translation of Gray, but we shouldn't + //replace "Red Hat 1" with the translation of Red :-) + sal_Int32 nLength = rString.getLength(); + while( nLength > 0 ) + { + const sal_Unicode nChar = rString[nLength-1]; + if (nChar != '%' && (nChar < '0' || nChar > '9')) + break; + nLength--; + } + std::u16string_view sStr = o3tl::trim(rString.subView(0, nLength)); + + for(int i = 0; i < nCount; ++i ) + { + OUString aStrDefName = SvxResId(pSourceResIds[i]); + if( sStr == aStrDefName ) + { + OUString aReplace = pDestResIds[i]; + rString = rString.replaceAt( 0, aStrDefName.getLength(), aReplace ); + return true; + } + } + + return false; +} + +static bool SvxUnoConvertResourceStringBuiltInFromApi(rtl::OUStringConstExpr const *pSourceResIds, const TranslateId* pDestResIds, int nCount, OUString& rString) +{ + //We replace e.g. "Gray 10%" with the translation of Gray, but we shouldn't + //replace "Red Hat 1" with the translation of Red :-) + sal_Int32 nLength = rString.getLength(); + while( nLength > 0 ) + { + const sal_Unicode nChar = rString[nLength-1]; + if (nChar != '%' && (nChar < '0' || nChar > '9')) + break; + nLength--; + } + std::u16string_view sStr = o3tl::trim(rString.subView(0, nLength)); + + for(int i = 0; i < nCount; ++i ) + { + if( sStr == pSourceResIds[i].asView() ) + { + OUString aReplace = SvxResId(pDestResIds[i]); + rString = aReplace + rString.subView( pSourceResIds[i].asView().size() ); + return true; + } + } + + return false; +} + +/** if the given name is a predefined name for the current language it is replaced by + the corresponding api name. +*/ +OUString SvxUnogetApiNameForItem(const sal_uInt16 nWhich, const OUString& rInternalName) +{ + OUString aNew = rInternalName; + + if( nWhich == sal_uInt16(XATTR_LINECOLOR) ) + { + if (SvxUnoConvertResourceStringBuiltInToApi(SvxUnoColorNameResId, SvxUnoColorNameDefResId, SAL_N_ELEMENTS(SvxUnoColorNameResId), aNew)) + { + return aNew; + } + } + else + { + const rtl::OUStringConstExpr* pApiResIds; + const TranslateId* pIntResIds; + int nCount; + + if( SvxUnoGetResourceRanges(nWhich, pApiResIds, pIntResIds, nCount)) + { + if (SvxUnoConvertResourceStringToApi(pIntResIds, pApiResIds, nCount, aNew)) + { + return aNew; + } + } + } + + // just use previous name, if nothing else was found. + return rInternalName; +} + +/** if the given name is a predefined api name it is replaced by the predefined name + for the current language. +*/ +OUString SvxUnogetInternalNameForItem(const sal_uInt16 nWhich, const OUString& rApiName) +{ + OUString aNew = rApiName; + + if( nWhich == sal_uInt16(XATTR_LINECOLOR) ) + { + if (SvxUnoConvertResourceStringBuiltInFromApi(SvxUnoColorNameDefResId, SvxUnoColorNameResId, SAL_N_ELEMENTS(SvxUnoColorNameResId), aNew)) + { + return aNew; + } + } + else + { + const rtl::OUStringConstExpr* pApiResIds; + const TranslateId* pIntResIds; + int nCount; + + if (SvxUnoGetResourceRanges(nWhich, pApiResIds, pIntResIds, nCount)) + { + if (SvxUnoConvertResourceStringFromApi(pApiResIds, pIntResIds, nCount, aNew)) + { + return aNew; + } + } + } + + // just use previous name, if nothing else was found. + return rApiName; +} + + +rtl::Reference<comphelper::PropertySetInfo> const & SvxPropertySetInfoPool::getOrCreate( sal_Int32 nServiceId ) noexcept +{ + SolarMutexGuard aGuard; + + assert( nServiceId <= SVXUNO_SERVICEID_LASTID ); + + if( !mxInfos[ nServiceId ].is() ) + { + mxInfos[nServiceId] = new comphelper::PropertySetInfo(); + + switch( nServiceId ) + { + case SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS: + mxInfos[SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS]->add( ImplGetSvxDrawingDefaultsPropertyMap() ); + break; + case SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS_WRITER: + mxInfos[SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS_WRITER]->add( ImplGetSvxDrawingDefaultsPropertyMap() ); + mxInfos[SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS_WRITER]->remove( UNO_NAME_EDIT_PARA_IS_HANGING_PUNCTUATION ); + // OD 13.10.2003 #i18732# - add property map for writer item 'IsFollowingTextFlow' + mxInfos[SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS_WRITER]->add( ImplGetAdditionalWriterDrawingDefaultsPropertyMap() ); + break; + + default: + OSL_FAIL( "unknown service id!" ); + } + } + + return mxInfos[ nServiceId ]; +} + +rtl::Reference<comphelper::PropertySetInfo> SvxPropertySetInfoPool::mxInfos[SVXUNO_SERVICEID_LASTID+1] = { nullptr }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoshap2.cxx b/svx/source/unodraw/unoshap2.cxx new file mode 100644 index 000000000..6972819c3 --- /dev/null +++ b/svx/source/unodraw/unoshap2.cxx @@ -0,0 +1,1798 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/PointSequence.hpp> +#include <com/sun/star/drawing/PolygonKind.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/drawing/BarCode.hpp> +#include <o3tl/any.hxx> +#include <o3tl/safeint.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wmf.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/GraphicLoader.hxx> + +#include <svx/svdpool.hxx> + +#include <editeng/unoprnms.hxx> +#include <svx/unoshape.hxx> +#include <svx/unopage.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdouno.hxx> +#include "shapeimpl.hxx" +#include <svx/unoshprp.hxx> +#include <svx/svdoashp.hxx> +#include <svx/svdviter.hxx> +#include <svx/svdview.hxx> +#include <svx/svdopath.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <com/sun/star/awt/XBitmap.hpp> +#include <svx/svdograf.hxx> +#include <sal/log.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <tools/stream.hxx> + + +#include <memory> + +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; + +#define QUERYINT( xint ) \ + if( rType == cppu::UnoType<xint>::get() ) \ + aAny <<= Reference< xint >(this) + +SvxShapeGroup::SvxShapeGroup(SdrObject* pObj, SvxDrawPage* pDrawPage) + : SvxShapeGroupAnyD(pObj, getSvxMapProvider().GetMap(SVXMAP_GROUP), getSvxMapProvider().GetPropertySet(SVXMAP_GROUP, SdrObject::GetGlobalDrawObjectItemPool())) + , mxPage(pDrawPage) +{ +} + +SvxShapeGroup::~SvxShapeGroup() noexcept +{ +} + +void SvxShapeGroup::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) +{ + SvxShape::Create( pNewObj, pNewPage ); + mxPage = pNewPage; +} + + +uno::Any SAL_CALL SvxShapeGroup::queryInterface( const uno::Type & rType ) +{ + return SvxShape::queryInterface( rType ); +} + +uno::Any SAL_CALL SvxShapeGroup::queryAggregation( const uno::Type & rType ) +{ + uno::Any aAny; + + QUERYINT( drawing::XShapeGroup ); + else QUERYINT( drawing::XShapes ); + else QUERYINT( drawing::XShapes2 ); + else QUERYINT( container::XIndexAccess ); + else QUERYINT( container::XElementAccess ); + else + return SvxShape::queryAggregation( rType ); + + return aAny; +} + +uno::Sequence< sal_Int8 > SAL_CALL SvxShapeGroup::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// css::drawing::XShape + + +OUString SAL_CALL SvxShapeGroup::getShapeType() +{ + return SvxShape::getShapeType(); +} + +awt::Point SAL_CALL SvxShapeGroup::getPosition() +{ + return SvxShape::getPosition(); +} + + +void SAL_CALL SvxShapeGroup::setPosition( const awt::Point& Position ) +{ + SvxShape::setPosition(Position); +} + + +awt::Size SAL_CALL SvxShapeGroup::getSize() +{ + return SvxShape::getSize(); +} + + +void SAL_CALL SvxShapeGroup::setSize( const awt::Size& rSize ) +{ + SvxShape::setSize( rSize ); +} + +// drawing::XShapeGroup + + +void SAL_CALL SvxShapeGroup::enterGroup( ) +{ + // Todo +// pDrView->EnterMarkedGroup(); +} + + +void SAL_CALL SvxShapeGroup::leaveGroup( ) +{ + // Todo +// pDrView->LeaveOneGroup(); +} + +void SvxShapeGroup::addUnoShape( const uno::Reference< drawing::XShape >& xShape, size_t nPos ) +{ + SvxShape* pShape = comphelper::getFromUnoTunnel<SvxShape>( xShape ); + if (!pShape) + { + OSL_FAIL("could not add XShape to group shape!"); + return; + } + addShape(*pShape, nPos); +} + +void SvxShapeGroup::addShape( SvxShape& rShape ) +{ + addShape(rShape, SAL_MAX_SIZE); +} + +void SvxShapeGroup::addShape( SvxShape& rShape, size_t nPos ) +{ + if (!HasSdrObject() || !mxPage.is()) + { + OSL_FAIL("could not add XShape to group shape!"); + return; + } + + SdrObject* pSdrShape = rShape.GetSdrObject(); + if( pSdrShape == nullptr ) + pSdrShape = mxPage->CreateSdrObject_( &rShape ); + + if( pSdrShape->IsInserted() ) + pSdrShape->getParentSdrObjListFromSdrObject()->RemoveObject( pSdrShape->GetOrdNum() ); + + GetSdrObject()->GetSubList()->InsertObject(pSdrShape, nPos); + // TTTT Was created using mpModel in CreateSdrObject_ above + // TTTT may be good to add an assertion here for the future + // pSdrShape->SetModel(GetSdrObject()->GetModel()); + + // #85922# It makes no sense to set the layer asked + // from the group object since this is an iteration + // over the contained objects. In consequence, this + // statement erases all layer information from the draw + // objects. Layers need to be set at draw objects directly + // and have nothing to do with grouping at all. + // pSdrShape->SetLayer(pObject->GetLayer()); + + // Establish connection between new SdrObject and its wrapper before + // inserting the new shape into the group. There a new wrapper + // would be created when this connection would not already exist. + rShape.Create( pSdrShape, mxPage.get() ); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +// XShapes +void SAL_CALL SvxShapeGroup::add( const uno::Reference< drawing::XShape >& xShape ) +{ + ::SolarMutexGuard aGuard; + + // Add to the top of the stack (i.e. bottom of the list) by default. + addUnoShape(xShape, SAL_MAX_SIZE); +} + + +void SAL_CALL SvxShapeGroup::remove( const uno::Reference< drawing::XShape >& xShape ) +{ + ::SolarMutexGuard aGuard; + + SdrObject* pSdrShape = SdrObject::getSdrObjectFromXShape( xShape ); + + if( !HasSdrObject() || pSdrShape == nullptr || pSdrShape->getParentSdrObjectFromSdrObject() != GetSdrObject() ) + throw uno::RuntimeException(); + + SdrObjList& rList = *pSdrShape->getParentSdrObjListFromSdrObject(); + + const size_t nObjCount = rList.GetObjCount(); + size_t nObjNum = 0; + while( nObjNum < nObjCount ) + { + if(rList.GetObj( nObjNum ) == pSdrShape ) + break; + nObjNum++; + } + + if( nObjNum < nObjCount ) + { + // #i29181# + // If the SdrObject which is about to be deleted is in any selection, + // deselect it first. + SdrViewIter aIter( pSdrShape ); + + for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() ) + { + if(SAL_MAX_SIZE != pView->TryToFindMarkedObject(pSdrShape)) + { + pView->MarkObj(pSdrShape, pView->GetSdrPageView(), true); + } + } + + SdrObject* pObject = rList.NbcRemoveObject( nObjNum ); + SdrObject::Free( pObject ); + } + else + { + SAL_WARN( "svx", "Fatality! SdrObject is not belonging to its SdrObjList! [CL]" ); + } + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +void SAL_CALL SvxShapeGroup::addTop( const uno::Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + // Add to the top of the stack (i.e. bottom of the list). + addUnoShape(xShape, SAL_MAX_SIZE); +} + +void SAL_CALL SvxShapeGroup::addBottom( const uno::Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + // Add to the bottom of the stack (i.e. top of the list). + addUnoShape(xShape, 0); +} + +// XIndexAccess + + +sal_Int32 SAL_CALL SvxShapeGroup::getCount() +{ + ::SolarMutexGuard aGuard; + + if(!HasSdrObject() || !GetSdrObject()->GetSubList()) + throw uno::RuntimeException(); + + sal_Int32 nRetval = GetSdrObject()->GetSubList()->GetObjCount(); + return nRetval; +} + + +uno::Any SAL_CALL SvxShapeGroup::getByIndex( sal_Int32 Index ) +{ + ::SolarMutexGuard aGuard; + + if( !HasSdrObject() || GetSdrObject()->GetSubList() == nullptr ) + throw uno::RuntimeException(); + + if( Index<0 || GetSdrObject()->GetSubList()->GetObjCount() <= o3tl::make_unsigned(Index) ) + throw lang::IndexOutOfBoundsException(); + + SdrObject* pDestObj = GetSdrObject()->GetSubList()->GetObj( Index ); + + if(pDestObj == nullptr) + throw lang::IndexOutOfBoundsException(); + + Reference< drawing::XShape > xShape( pDestObj->getUnoShape(), uno::UNO_QUERY ); + return uno::Any( xShape ); +} + +// css::container::XElementAccess + + +uno::Type SAL_CALL SvxShapeGroup::getElementType() +{ + return cppu::UnoType<drawing::XShape>::get(); +} + + +sal_Bool SAL_CALL SvxShapeGroup::hasElements() +{ + ::SolarMutexGuard aGuard; + + return HasSdrObject() && GetSdrObject()->GetSubList() && (GetSdrObject()->GetSubList()->GetObjCount() > 0); +} + +SvxShapeConnector::SvxShapeConnector(SdrObject* pObj) + : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CONNECTOR), getSvxMapProvider().GetPropertySet(SVXMAP_CONNECTOR, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + + +SvxShapeConnector::~SvxShapeConnector() noexcept +{ +} + + +uno::Any SAL_CALL SvxShapeConnector::queryInterface( const uno::Type & rType ) +{ + return SvxShapeText::queryInterface( rType ); +} + +uno::Any SAL_CALL SvxShapeConnector::queryAggregation( const uno::Type & rType ) +{ + uno::Any aAny; + + QUERYINT( drawing::XConnectorShape ); + else + return SvxShapeText::queryAggregation( rType ); + + return aAny; +} + +// XTypeProvider + +uno::Sequence< uno::Type > SAL_CALL SvxShapeConnector::getTypes() +{ + return SvxShape::getTypes(); +} + +uno::Sequence< sal_Int8 > SAL_CALL SvxShapeConnector::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// css::drawing::XShape + + +OUString SAL_CALL SvxShapeConnector::getShapeType() +{ + return SvxShapeText::getShapeType(); +} + +awt::Point SAL_CALL SvxShapeConnector::getPosition() +{ + return SvxShapeText::getPosition(); +} + + +void SAL_CALL SvxShapeConnector::setPosition( const awt::Point& Position ) +{ + SvxShapeText::setPosition(Position); +} + + +awt::Size SAL_CALL SvxShapeConnector::getSize() +{ + return SvxShapeText::getSize(); +} + + +void SAL_CALL SvxShapeConnector::setSize( const awt::Size& rSize ) +{ + SvxShapeText::setSize( rSize ); +} + + +// XConnectorShape + +void SAL_CALL SvxShapeConnector::connectStart( const uno::Reference< drawing::XConnectableShape >& xShape, drawing::ConnectionType ) +{ + ::SolarMutexGuard aGuard; + + Reference< drawing::XShape > xRef( xShape, UNO_QUERY ); + SdrObject* pSdrObject = SdrObject::getSdrObjectFromXShape( xRef ); + + if( pSdrObject ) + GetSdrObject()->ConnectToNode( true, pSdrObject ); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + + +void SAL_CALL SvxShapeConnector::connectEnd( const uno::Reference< drawing::XConnectableShape >& xShape, drawing::ConnectionType ) +{ + ::SolarMutexGuard aGuard; + + Reference< drawing::XShape > xRef( xShape, UNO_QUERY ); + SdrObject* pSdrObject = SdrObject::getSdrObjectFromXShape( xRef ); + + if( HasSdrObject() && pSdrObject ) + GetSdrObject()->ConnectToNode( false, pSdrObject ); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + + +void SAL_CALL SvxShapeConnector::disconnectBegin( const uno::Reference< drawing::XConnectableShape >& ) +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + GetSdrObject()->DisconnectFromNode( true ); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + + +void SAL_CALL SvxShapeConnector::disconnectEnd( const uno::Reference< drawing::XConnectableShape >& ) +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + GetSdrObject()->DisconnectFromNode( false ); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +SvxShapeControl::SvxShapeControl(SdrObject* pObj) + : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CONTROL), getSvxMapProvider().GetPropertySet(SVXMAP_CONTROL, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ + setShapeKind( SdrObjKind::UNO ); +} + + +SvxShapeControl::~SvxShapeControl() noexcept +{ +} + + +uno::Any SAL_CALL SvxShapeControl::queryInterface( const uno::Type & rType ) +{ + return SvxShapeText::queryInterface( rType ); +} + +uno::Any SAL_CALL SvxShapeControl::queryAggregation( const uno::Type & rType ) +{ + uno::Any aAny; + + QUERYINT( drawing::XControlShape ); + else + return SvxShapeText::queryAggregation( rType ); + + return aAny; +} + +// XTypeProvider + +uno::Sequence< uno::Type > SAL_CALL SvxShapeControl::getTypes() +{ + return SvxShape::getTypes(); +} + +uno::Sequence< sal_Int8 > SAL_CALL SvxShapeControl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// css::drawing::XShape + + +OUString SAL_CALL SvxShapeControl::getShapeType() +{ + return SvxShapeText::getShapeType(); +} + +awt::Point SAL_CALL SvxShapeControl::getPosition() +{ + return SvxShapeText::getPosition(); +} + + +void SAL_CALL SvxShapeControl::setPosition( const awt::Point& Position ) +{ + SvxShapeText::setPosition(Position); +} + + +awt::Size SAL_CALL SvxShapeControl::getSize() +{ + return SvxShapeText::getSize(); +} + + +void SAL_CALL SvxShapeControl::setSize( const awt::Size& rSize ) +{ + SvxShapeText::setSize( rSize ); +} + + +// XControlShape + +Reference< awt::XControlModel > SAL_CALL SvxShapeControl::getControl() +{ + ::SolarMutexGuard aGuard; + + Reference< awt::XControlModel > xModel; + + SdrUnoObj* pUnoObj = dynamic_cast< SdrUnoObj * >(GetSdrObject()); + if( pUnoObj ) + xModel = pUnoObj->GetUnoControlModel(); + + return xModel; +} + + +void SAL_CALL SvxShapeControl::setControl( const Reference< awt::XControlModel >& xControl ) +{ + ::SolarMutexGuard aGuard; + + SdrUnoObj* pUnoObj = dynamic_cast< SdrUnoObj * >(GetSdrObject()); + if( pUnoObj ) + pUnoObj->SetUnoControlModel( xControl ); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +struct +{ + OUString msAPIName; + OUString msFormName; +} +const SvxShapeControlPropertyMapping[] = +{ + // Warning: The first entry must be FontSlant because the any needs to be converted + { UNO_NAME_EDIT_CHAR_POSTURE, "FontSlant" }, // const sal_Int16 => css::awt::FontSlant + { UNO_NAME_EDIT_CHAR_FONTNAME, "FontName" }, + { UNO_NAME_EDIT_CHAR_FONTSTYLENAME, "FontStyleName" }, + { UNO_NAME_EDIT_CHAR_FONTFAMILY, "FontFamily" }, + { UNO_NAME_EDIT_CHAR_FONTCHARSET, "FontCharset" }, + { UNO_NAME_EDIT_CHAR_HEIGHT, "FontHeight" }, + { UNO_NAME_EDIT_CHAR_FONTPITCH, "FontPitch" }, + { UNO_NAME_EDIT_CHAR_WEIGHT, "FontWeight" }, + { UNO_NAME_EDIT_CHAR_UNDERLINE, "FontUnderline" }, + { UNO_NAME_EDIT_CHAR_STRIKEOUT, "FontStrikeout" }, + { "CharKerning", "FontKerning" }, + { "CharWordMode", "FontWordLineMode" }, + { UNO_NAME_EDIT_CHAR_COLOR, "TextColor" }, + { "CharBackColor", "CharBackColor" }, + { "CharBackTransparent", "CharBackTransparent" }, + { UNO_NAME_TEXT_CHAINNEXTNAME, UNO_NAME_TEXT_CHAINNEXTNAME }, + { "CharRelief", "FontRelief" }, + { "CharUnderlineColor", "TextLineColor" }, + { UNO_NAME_EDIT_PARA_ADJUST, "Align" }, + { "TextVerticalAdjust", "VerticalAlign" }, + { "ControlBackground", "BackgroundColor" }, + { "ControlSymbolColor", "SymbolColor" }, + { "ControlBorder", "Border" }, + { "ControlBorderColor", "BorderColor" }, + { "ControlTextEmphasis", "FontEmphasisMark" }, + { "ImageScaleMode", "ScaleMode" }, + { "ControlWritingMode", "WritingMode" }, + //added for exporting OCX control + { "ControlTypeinMSO", "ControlTypeinMSO" }, + { "ObjIDinMSO", "ObjIDinMSO" }, + { "CharCaseMap", "CharCaseMap" }, + { "CharColorTheme", "CharColorTheme" }, + { "CharColorTintOrShade", "CharColorTintOrShade" }, +}; + +namespace +{ + bool lcl_convertPropertyName( const OUString& rApiName, OUString& rInternalName ) + { + for( const auto & rEntry : SvxShapeControlPropertyMapping ) + { + if( rApiName.reverseCompareTo( rEntry.msAPIName ) == 0 ) + { + rInternalName = rEntry.msFormName; + } + } + return !rInternalName.isEmpty(); + } + + struct EnumConversionMap + { + style::ParagraphAdjust nAPIValue; + sal_Int16 nFormValue; + }; + + EnumConversionMap const aMapAdjustToAlign[] = + { + // note that order matters: + // lcl_convertTextAlignmentToParaAdjustment and lcl_convertParaAdjustmentToTextAlignment search this map from the _beginning_ + // and use the first matching entry + {style::ParagraphAdjust_LEFT, sal_Int16(awt::TextAlign::LEFT)}, + {style::ParagraphAdjust_CENTER, sal_Int16(awt::TextAlign::CENTER)}, + {style::ParagraphAdjust_RIGHT, sal_Int16(awt::TextAlign::RIGHT)}, + {style::ParagraphAdjust_BLOCK, sal_Int16(awt::TextAlign::RIGHT)}, + {style::ParagraphAdjust_STRETCH, sal_Int16(awt::TextAlign::LEFT)}, + {style::ParagraphAdjust(-1),-1} + }; + + void lcl_convertTextAlignmentToParaAdjustment( Any& _rValue ) + { + sal_Int16 nValue = sal_Int16(); + OSL_VERIFY( _rValue >>= nValue ); + + for ( auto const & rEntry : aMapAdjustToAlign ) + if ( nValue == rEntry.nFormValue ) + { + _rValue <<= static_cast<sal_uInt16>(rEntry.nAPIValue); + return; + } + } + + void lcl_convertParaAdjustmentToTextAlignment( Any& _rValue ) + { + sal_Int32 nValue = 0; + OSL_VERIFY( _rValue >>= nValue ); + + for ( auto const & rEntry : aMapAdjustToAlign ) + if ( static_cast<style::ParagraphAdjust>(nValue) == rEntry.nAPIValue ) + { + _rValue <<= rEntry.nFormValue; + return; + } + } + + void convertVerticalAdjustToVerticalAlign( Any& _rValue ) + { + if ( !_rValue.hasValue() ) + return; + + drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP; + style::VerticalAlignment eAlign = style::VerticalAlignment_TOP; + if ( !( _rValue >>= eAdjust ) ) + throw lang::IllegalArgumentException(); + switch ( eAdjust ) + { + case drawing::TextVerticalAdjust_TOP: eAlign = style::VerticalAlignment_TOP; break; + case drawing::TextVerticalAdjust_BOTTOM: eAlign = style::VerticalAlignment_BOTTOM; break; + default: eAlign = style::VerticalAlignment_MIDDLE; break; + } + _rValue <<= eAlign; + } + + void convertVerticalAlignToVerticalAdjust( Any& _rValue ) + { + if ( !_rValue.hasValue() ) + return; + style::VerticalAlignment eAlign = style::VerticalAlignment_TOP; + drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP; + OSL_VERIFY( _rValue >>= eAlign ); + switch ( eAlign ) + { + case style::VerticalAlignment_TOP: eAdjust = drawing::TextVerticalAdjust_TOP; break; + case style::VerticalAlignment_BOTTOM: eAdjust = drawing::TextVerticalAdjust_BOTTOM; break; + default: eAdjust = drawing::TextVerticalAdjust_CENTER; break; + } + _rValue <<= eAdjust; + } +} + +void SAL_CALL SvxShapeControl::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue ) +{ + OUString aFormsName; + if ( lcl_convertPropertyName( aPropertyName, aFormsName ) ) + { + uno::Reference< beans::XPropertySet > xControl( getControl(), uno::UNO_QUERY ); + if( xControl.is() ) + { + uno::Reference< beans::XPropertySetInfo > xInfo( xControl->getPropertySetInfo() ); + if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) ) + { + uno::Any aConvertedValue( aValue ); + if ( aFormsName == "FontSlant" ) + { + awt::FontSlant nSlant; + if( !(aValue >>= nSlant ) ) + throw lang::IllegalArgumentException(); + aConvertedValue <<= static_cast<sal_Int16>(nSlant); + } + else if ( aFormsName == "Align" ) + { + lcl_convertParaAdjustmentToTextAlignment( aConvertedValue ); + } + else if ( aFormsName == "VerticalAlign" ) + { + convertVerticalAdjustToVerticalAlign( aConvertedValue ); + } + + xControl->setPropertyValue( aFormsName, aConvertedValue ); + } + } + } + else + { + SvxShape::setPropertyValue( aPropertyName, aValue ); + } +} + +uno::Any SAL_CALL SvxShapeControl::getPropertyValue( const OUString& aPropertyName ) +{ + OUString aFormsName; + if ( lcl_convertPropertyName( aPropertyName, aFormsName ) ) + { + uno::Reference< beans::XPropertySet > xControl( getControl(), uno::UNO_QUERY ); + + uno::Any aValue; + if( xControl.is() ) + { + uno::Reference< beans::XPropertySetInfo > xInfo( xControl->getPropertySetInfo() ); + if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) ) + { + aValue = xControl->getPropertyValue( aFormsName ); + if ( aFormsName == "FontSlant" ) + { + awt::FontSlant eSlant = awt::FontSlant_NONE; + sal_Int16 nSlant = sal_Int16(); + if ( aValue >>= nSlant ) + { + eSlant = static_cast<awt::FontSlant>(nSlant); + } + else + { + OSL_VERIFY( aValue >>= eSlant ); + } + aValue <<= eSlant; + } + else if ( aFormsName == "Align" ) + { + lcl_convertTextAlignmentToParaAdjustment( aValue ); + } + else if ( aFormsName == "VerticalAlign" ) + { + convertVerticalAlignToVerticalAdjust( aValue ); + } + } + } + + return aValue; + } + else + { + return SvxShape::getPropertyValue( aPropertyName ); + } + +} + +// XPropertyState +beans::PropertyState SAL_CALL SvxShapeControl::getPropertyState( const OUString& PropertyName ) +{ + OUString aFormsName; + if ( lcl_convertPropertyName( PropertyName, aFormsName ) ) + { + uno::Reference< beans::XPropertyState > xControl( getControl(), uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xPropSet( getControl(), uno::UNO_QUERY ); + + if( xControl.is() && xPropSet.is() ) + { + uno::Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() ); + if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) ) + { + return xControl->getPropertyState( aFormsName ); + } + } + + return beans::PropertyState_DEFAULT_VALUE; + } + else + { + return SvxShape::getPropertyState( PropertyName ); + } +} + +void SAL_CALL SvxShapeControl::setPropertyToDefault( const OUString& PropertyName ) +{ + OUString aFormsName; + if ( lcl_convertPropertyName( PropertyName, aFormsName ) ) + { + uno::Reference< beans::XPropertyState > xControl( getControl(), uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xPropSet( getControl(), uno::UNO_QUERY ); + + if( xControl.is() && xPropSet.is() ) + { + uno::Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() ); + if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) ) + { + xControl->setPropertyToDefault( aFormsName ); + } + } + } + else + { + SvxShape::setPropertyToDefault( PropertyName ); + } +} + +uno::Any SAL_CALL SvxShapeControl::getPropertyDefault( const OUString& aPropertyName ) +{ + OUString aFormsName; + if ( lcl_convertPropertyName( aPropertyName, aFormsName ) ) + { + uno::Reference< beans::XPropertyState > xControl( getControl(), uno::UNO_QUERY ); + + if( xControl.is() ) + { + Any aDefault( xControl->getPropertyDefault( aFormsName ) ); + if ( aFormsName == "FontSlant" ) + { + sal_Int16 nSlant( 0 ); + aDefault >>= nSlant; + aDefault <<= static_cast<awt::FontSlant>(nSlant); + } + else if ( aFormsName == "Align" ) + { + lcl_convertTextAlignmentToParaAdjustment( aDefault ); + } + else if ( aFormsName == "VerticalAlign" ) + { + convertVerticalAlignToVerticalAdjust( aDefault ); + } + return aDefault; + } + + throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this)); + } + else + { + return SvxShape::getPropertyDefault( aPropertyName ); + } +} + +SvxShapeDimensioning::SvxShapeDimensioning(SdrObject* pObj) + : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_DIMENSIONING), getSvxMapProvider().GetPropertySet(SVXMAP_DIMENSIONING, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +SvxShapeDimensioning::~SvxShapeDimensioning() noexcept +{ +} + +SvxShapeCircle::SvxShapeCircle(SdrObject* pObj) + : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CIRCLE), getSvxMapProvider().GetPropertySet(SVXMAP_CIRCLE, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +SvxShapeCircle::~SvxShapeCircle() noexcept +{ +} + +////////////////////////////////////////////////////////////////////////////// + +SvxShapePolyPolygon::SvxShapePolyPolygon( + SdrObject* pObj) +: SvxShapeText( + pObj, + getSvxMapProvider().GetMap(SVXMAP_POLYPOLYGON), + getSvxMapProvider().GetPropertySet(SVXMAP_POLYPOLYGON, SdrObject::GetGlobalDrawObjectItemPool())) +{ +} + +SvxShapePolyPolygon::~SvxShapePolyPolygon() noexcept +{ +} + +bool SvxShapePolyPolygon::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_VALUE_POLYPOLYGONBEZIER: + { + if( auto s = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(rValue) ) + { + basegfx::B2DPolyPolygon aNewPolyPolygon( + basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*s)); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricToItemPoolMetric(aNewPolyPolygon); + + SetPolygon(aNewPolyPolygon); + return true; + } + break; + } + case OWN_ATTR_VALUE_POLYPOLYGON: + { + if( auto s = o3tl::tryAccess<drawing::PointSequenceSequence>(rValue) ) + { + basegfx::B2DPolyPolygon aNewPolyPolygon( + basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(*s)); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricToItemPoolMetric(aNewPolyPolygon); + + SetPolygon(aNewPolyPolygon); + return true; + } + break; + } + case OWN_ATTR_BASE_GEOMETRY: + { + drawing::PointSequenceSequence aPointSequenceSequence; + drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords; + + if( rValue >>= aPointSequenceSequence) + { + if( HasSdrObject() ) + { + basegfx::B2DPolyPolygon aNewPolyPolygon; + basegfx::B2DHomMatrix aNewHomogenMatrix; + + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + aNewPolyPolygon = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(aPointSequenceSequence); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + // Need to adapt aNewPolyPolygon from 100thmm to app-specific + ForceMetricToItemPoolMetric(aNewPolyPolygon); + + GetSdrObject()->TRSetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + } + return true; + } + else if( rValue >>= aPolyPolygonBezierCoords) + { + if( HasSdrObject() ) + { + basegfx::B2DPolyPolygon aNewPolyPolygon; + basegfx::B2DHomMatrix aNewHomogenMatrix; + + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + aNewPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(aPolyPolygonBezierCoords); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricToItemPoolMetric(aNewPolyPolygon); + + GetSdrObject()->TRSetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + } + return true; + } + break; + } + case OWN_ATTR_VALUE_POLYGON: + { + if( auto pSequence = o3tl::tryAccess<drawing::PointSequence>(rValue) ) + { + // prepare new polygon + basegfx::B2DPolygon aNewPolygon; + + // get pointer to arrays + const awt::Point* pArray = pSequence->getConstArray(); + const awt::Point* pArrayEnd = pArray + pSequence->getLength(); + + for(;pArray != pArrayEnd;++pArray) + { + aNewPolygon.append(basegfx::B2DPoint(pArray->X, pArray->Y)); + } + + // check for closed state flag + basegfx::utils::checkClosed(aNewPolygon); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + basegfx::B2DPolyPolygon aNewPolyPolygon(aNewPolygon); + ForceMetricToItemPoolMetric(aNewPolyPolygon); + + // set polygon + SetPolygon(aNewPolyPolygon); + return true; + } + break; + } + default: + return SvxShapeText::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw lang::IllegalArgumentException(); +} + +bool SvxShapePolyPolygon::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, + css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_VALUE_POLYPOLYGONBEZIER: + { + // pack a tools::PolyPolygon in a struct tools::PolyPolygon + basegfx::B2DPolyPolygon aPolyPoly(GetPolygon()); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricTo100th_mm(aPolyPoly); + + drawing::PolyPolygonBezierCoords aRetval; + basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(aPolyPoly, aRetval); + + rValue <<= aRetval; + break; + } + case OWN_ATTR_VALUE_POLYPOLYGON: + { + // pack a tools::PolyPolygon in a struct tools::PolyPolygon + basegfx::B2DPolyPolygon aPolyPoly(GetPolygon()); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricTo100th_mm(aPolyPoly); + + drawing::PointSequenceSequence aRetval( aPolyPoly.count() ); + basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPoly, aRetval); + + rValue <<= aRetval; + break; + } + case OWN_ATTR_BASE_GEOMETRY: + { + // pack a tools::PolyPolygon in struct PolyPolygon + basegfx::B2DPolyPolygon aPolyPoly; + basegfx::B2DHomMatrix aNewHomogenMatrix; + + if(HasSdrObject()) + { + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aPolyPoly); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricTo100th_mm(aPolyPoly); + } + + if(aPolyPoly.areControlPointsUsed()) + { + drawing::PolyPolygonBezierCoords aRetval; + basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(aPolyPoly, aRetval); + rValue <<= aRetval; + } + else + { + drawing::PointSequenceSequence aRetval(aPolyPoly.count()); + basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPoly, aRetval); + rValue <<= aRetval; + } + break; + } + case OWN_ATTR_VALUE_POLYGON: + { + // pack a tools::PolyPolygon in a struct tools::PolyPolygon + basegfx::B2DPolyPolygon aPolyPoly(GetPolygon()); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + ForceMetricTo100th_mm(aPolyPoly); + + const sal_Int32 nCount(0 == aPolyPoly.count() ? 0 : aPolyPoly.getB2DPolygon(0).count()); + drawing::PointSequence aRetval( nCount ); + + if( nCount > 0 ) + { + // get single polygon + const basegfx::B2DPolygon& aPoly(aPolyPoly.getB2DPolygon(0)); + + // get pointer to arrays + awt::Point* pSequence = aRetval.getArray(); + + for(sal_Int32 b=0;b<nCount;b++) + { + const basegfx::B2DPoint aPoint(aPoly.getB2DPoint(b)); + *pSequence++ = awt::Point( basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()) ); + } + } + + rValue <<= aRetval; + break; + } + case OWN_ATTR_VALUE_POLYGONKIND: + { + rValue <<= GetPolygonKind(); + break; + } + default: + return SvxShapeText::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +drawing::PolygonKind SvxShapePolyPolygon::GetPolygonKind() const +{ + ::SolarMutexGuard aGuard; + drawing::PolygonKind aRetval(drawing::PolygonKind_LINE); + + if(HasSdrObject()) + { + switch(GetSdrObject()->GetObjIdentifier()) + { + case SdrObjKind::Polygon: aRetval = drawing::PolygonKind_POLY; break; + case SdrObjKind::PolyLine: aRetval = drawing::PolygonKind_PLIN; break; + case SdrObjKind::SplineLine: + case SdrObjKind::PathLine: aRetval = drawing::PolygonKind_PATHLINE; break; + case SdrObjKind::SplineFill: + case SdrObjKind::PathFill: aRetval = drawing::PolygonKind_PATHFILL; break; + case SdrObjKind::FreehandLine: aRetval = drawing::PolygonKind_FREELINE; break; + case SdrObjKind::FreehandFill: aRetval = drawing::PolygonKind_FREEFILL; break; + default: break; + } + } + + return aRetval; +} + +void SvxShapePolyPolygon::SetPolygon(const basegfx::B2DPolyPolygon& rNew) +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + static_cast<SdrPathObj*>(GetSdrObject())->SetPathPoly(rNew); +} + + +basegfx::B2DPolyPolygon SvxShapePolyPolygon::GetPolygon() const noexcept +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + { + return static_cast<SdrPathObj*>(GetSdrObject())->GetPathPoly(); + } + else + { + return basegfx::B2DPolyPolygon(); + } +} + +////////////////////////////////////////////////////////////////////////////// + +SvxGraphicObject::SvxGraphicObject(SdrObject* pObj) + : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_GRAPHICOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_GRAPHICOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +SvxGraphicObject::~SvxGraphicObject() noexcept +{ +} + +bool SvxGraphicObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + bool bOk = false; + switch( pProperty->nWID ) + { + case OWN_ATTR_VALUE_FILLBITMAP: + { + if( auto pSeq = o3tl::tryAccess<uno::Sequence<sal_Int8>>(rValue) ) + { + SvMemoryStream aMemStm; + Graphic aGraphic; + + aMemStm.SetBuffer( const_cast<css::uno::Sequence<sal_Int8> *>(pSeq)->getArray(), pSeq->getLength(), pSeq->getLength() ); + + if( GraphicConverter::Import( aMemStm, aGraphic ) == ERRCODE_NONE ) + { + static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic); + bOk = true; + } + } + else if (rValue.getValueType() == cppu::UnoType<graphic::XGraphic>::get()) + { + auto xGraphic = rValue.get<uno::Reference<graphic::XGraphic>>(); + if (xGraphic.is()) + { + static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(Graphic(xGraphic)); + bOk = true; + } + } + else if (rValue.getValueType() == cppu::UnoType<awt::XBitmap>::get()) + { + auto xBitmap = rValue.get<uno::Reference<awt::XBitmap>>(); + if (xBitmap.is()) + { + uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY); + Graphic aGraphic(xGraphic); + static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic); + bOk = true; + } + } + break; + } + + case OWN_ATTR_GRAFSTREAMURL: + { + OUString aStreamURL; + + if( rValue >>= aStreamURL ) + { + if( !aStreamURL.startsWith( UNO_NAME_GRAPHOBJ_URLPKGPREFIX ) ) + aStreamURL.clear(); + + if( HasSdrObject() ) + { + static_cast<SdrGrafObj*>(GetSdrObject())->SetGrafStreamURL( aStreamURL ); + } + bOk = true; + } + break; + } + + case OWN_ATTR_GRAPHIC_URL: + { + OUString aURL; + uno::Reference<awt::XBitmap> xBitmap; + if (rValue >>= aURL) + { + Graphic aGraphic = vcl::graphic::loadFromURL(aURL); + if (!aGraphic.IsNone()) + { + static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic); + bOk = true; + } + } + else if (rValue >>= xBitmap) + { + uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY); + if (xGraphic.is()) + { + Graphic aGraphic = xGraphic; + if (!aGraphic.IsNone()) + { + static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic); + bOk = true; + } + } + } + break; + } + + case OWN_ATTR_VALUE_GRAPHIC: + { + Reference< graphic::XGraphic > xGraphic( rValue, uno::UNO_QUERY ); + if( xGraphic.is() ) + { + static_cast< SdrGrafObj*>( GetSdrObject() )->SetGraphic( xGraphic ); + bOk = true; + } + break; + } + + case OWN_ATTR_IS_SIGNATURELINE: + { + bool bIsSignatureLine; + if (rValue >>= bIsSignatureLine) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setIsSignatureLine(bIsSignatureLine); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_ID: + { + OUString aSignatureLineId; + if (rValue >>= aSignatureLineId) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineId(aSignatureLineId); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_NAME: + { + OUString aSuggestedSignerName; + if (rValue >>= aSuggestedSignerName) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSuggestedSignerName(aSuggestedSignerName); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_TITLE: + { + OUString aSuggestedSignerTitle; + if (rValue >>= aSuggestedSignerTitle) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSuggestedSignerTitle(aSuggestedSignerTitle); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_EMAIL: + { + OUString aSuggestedSignerEmail; + if (rValue >>= aSuggestedSignerEmail) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSuggestedSignerEmail(aSuggestedSignerEmail); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_SIGNING_INSTRUCTIONS: + { + OUString aSigningInstructions; + if (rValue >>= aSigningInstructions) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSigningInstructions(aSigningInstructions); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_SHOW_SIGN_DATE: + { + bool bShowSignDate; + if (rValue >>= bShowSignDate) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineShowSignDate(bShowSignDate); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_CAN_ADD_COMMENT: + { + bool bCanAddComment; + if (rValue >>= bCanAddComment) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineCanAddComment(bCanAddComment); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE: + { + Reference<graphic::XGraphic> xGraphic(rValue, uno::UNO_QUERY); + if (xGraphic.is()) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineUnsignedGraphic(xGraphic); + bOk = true; + } + break; + } + + case OWN_ATTR_SIGNATURELINE_IS_SIGNED: + { + bool bIsSigned; + if (rValue >>= bIsSigned) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineIsSigned(bIsSigned); + bOk = true; + } + break; + } + + case OWN_ATTR_QRCODE: + { + css::drawing::BarCode aBarCode; + if (rValue >>= aBarCode) + { + static_cast<SdrGrafObj*>(GetSdrObject())->setQrCode(aBarCode); + bOk = true; + } + break; + } + + default: + return SvxShapeText::setPropertyValueImpl( rName, pProperty, rValue ); + } + + if( !bOk ) + throw lang::IllegalArgumentException(); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); + + return true; +} + +bool SvxGraphicObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_VALUE_FILLBITMAP: + { + const Graphic& rGraphic = static_cast<SdrGrafObj*>(GetSdrObject())->GetGraphic(); + + if (rGraphic.GetType() != GraphicType::GdiMetafile) + { + uno::Reference<awt::XBitmap> xBitmap(rGraphic.GetXGraphic(), uno::UNO_QUERY); + rValue <<= xBitmap; + } + else + { + SvMemoryStream aDestStrm( 65535, 65535 ); + + ConvertGDIMetaFileToWMF( rGraphic.GetGDIMetaFile(), aDestStrm, nullptr, false ); + const uno::Sequence<sal_Int8> aSeq( + static_cast< const sal_Int8* >(aDestStrm.GetData()), + aDestStrm.GetEndOfData()); + rValue <<= aSeq; + } + break; + } + + case OWN_ATTR_REPLACEMENT_GRAPHIC: + { + const GraphicObject* pGrafObj = static_cast< SdrGrafObj* >(GetSdrObject())->GetReplacementGraphicObject(); + + if (pGrafObj) + { + rValue <<= pGrafObj->GetGraphic().GetXGraphic(); + } + + break; + } + + case OWN_ATTR_GRAFSTREAMURL: + { + const OUString aStreamURL( static_cast<SdrGrafObj*>( GetSdrObject() )->GetGrafStreamURL() ); + if( !aStreamURL.isEmpty() ) + rValue <<= aStreamURL; + break; + } + + case OWN_ATTR_GRAPHIC_URL: + case OWN_ATTR_VALUE_GRAPHIC: + { + if (pProperty->nWID == OWN_ATTR_GRAPHIC_URL) + { + SAL_WARN("svx", "Getting Graphic by URL is not supported, getting it by value"); + } + + Reference<graphic::XGraphic> xGraphic; + auto pSdrGraphicObject = static_cast<SdrGrafObj*>(GetSdrObject()); + if (pSdrGraphicObject + && pSdrGraphicObject->GetGraphicObject().GetType() != GraphicType::NONE) + xGraphic = pSdrGraphicObject->GetGraphic().GetXGraphic(); + rValue <<= xGraphic; + break; + } + + case OWN_ATTR_GRAPHIC_STREAM: + { + rValue <<= static_cast< SdrGrafObj* >( GetSdrObject() )->getInputStream(); + break; + } + + case OWN_ATTR_IS_SIGNATURELINE: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLine(); + break; + } + + case OWN_ATTR_SIGNATURELINE_ID: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineId(); + break; + } + + case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_NAME: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSuggestedSignerName(); + break; + } + + case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_TITLE: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSuggestedSignerTitle(); + break; + } + + case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_EMAIL: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSuggestedSignerEmail(); + break; + } + + case OWN_ATTR_SIGNATURELINE_SIGNING_INSTRUCTIONS: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSigningInstructions(); + break; + } + + case OWN_ATTR_SIGNATURELINE_SHOW_SIGN_DATE: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLineShowSignDate(); + break; + } + + case OWN_ATTR_SIGNATURELINE_CAN_ADD_COMMENT: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLineCanAddComment(); + break; + } + + case OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE: + { + Reference<graphic::XGraphic> xGraphic( + static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineUnsignedGraphic()); + rValue <<= xGraphic; + break; + } + + case OWN_ATTR_SIGNATURELINE_IS_SIGNED: + { + rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLineSigned(); + break; + } + + case OWN_ATTR_QRCODE: + { + css::drawing::BarCode* ptr = static_cast<SdrGrafObj*>(GetSdrObject())->getQrCode(); + if(ptr) + { + rValue <<= *ptr; + } + break; + } + + default: + return SvxShapeText::getPropertyValueImpl(rName, pProperty,rValue); + } + + return true; +} + + +SvxShapeCaption::SvxShapeCaption(SdrObject* pObj) +: SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CAPTION), getSvxMapProvider().GetPropertySet(SVXMAP_CAPTION, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +SvxShapeCaption::~SvxShapeCaption() noexcept +{ +} + +SvxCustomShape::SvxCustomShape(SdrObject* pObj) + : SvxShapeText( pObj, getSvxMapProvider().GetMap( SVXMAP_CUSTOMSHAPE ), getSvxMapProvider().GetPropertySet(SVXMAP_CUSTOMSHAPE, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +SvxCustomShape::~SvxCustomShape() noexcept +{ +} + +uno::Any SAL_CALL SvxCustomShape::queryInterface( const uno::Type & rType ) +{ + return SvxShapeText::queryInterface( rType ); +} + +uno::Any SAL_CALL SvxCustomShape::queryAggregation( const uno::Type & rType ) +{ + css::uno::Any aReturn = SvxShapeText::queryAggregation( rType ); + if ( !aReturn.hasValue() ) + aReturn = ::cppu::queryInterface(rType, static_cast<drawing::XEnhancedCustomShapeDefaulter*>(this) ); + return aReturn; +} + +uno::Sequence< sal_Int8 > SAL_CALL SvxCustomShape::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// css::drawing::XShape + + +awt::Point SAL_CALL SvxCustomShape::getPosition() +{ + ::SolarMutexGuard aGuard; + if ( HasSdrObject() ) + { + SdrAShapeObjGeoData aCustomShapeGeoData; + static_cast<SdrObjCustomShape*>(GetSdrObject())->SaveGeoData( aCustomShapeGeoData ); + + bool bMirroredX = false; + bool bMirroredY = false; + + if ( HasSdrObject() ) + { + bMirroredX = static_cast<SdrObjCustomShape*>(GetSdrObject())->IsMirroredX(); + bMirroredY = static_cast<SdrObjCustomShape*>(GetSdrObject())->IsMirroredY(); + } + // get aRect, this is the unrotated snaprect + tools::Rectangle aRect(static_cast<SdrObjCustomShape*>(GetSdrObject())->GetLogicRect()); + tools::Rectangle aRectangle( aRect ); + + if ( bMirroredX || bMirroredY ) + { // we have to retrieve the unmirrored rect + + GeoStat aNewGeo(aCustomShapeGeoData.maGeo); + if ( bMirroredX ) + { + tools::Polygon aPol( Rect2Poly( aRect, aNewGeo ) ); + tools::Rectangle aBoundRect( aPol.GetBoundRect() ); + + Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() ); + Point aRef2( aRef1.X(), aRef1.Y() + 1000 ); + sal_uInt16 i; + sal_uInt16 nPointCount=aPol.GetSize(); + for (i=0; i<nPointCount; i++) + { + MirrorPoint(aPol[i],aRef1,aRef2); + } + // turn and move polygon + tools::Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect(aPol,aRectangle,aNewGeo); + } + if ( bMirroredY ) + { + tools::Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) ); + tools::Rectangle aBoundRect( aPol.GetBoundRect() ); + + Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 ); + Point aRef2( aRef1.X() + 1000, aRef1.Y() ); + sal_uInt16 i; + sal_uInt16 nPointCount=aPol.GetSize(); + for (i=0; i<nPointCount; i++) + { + MirrorPoint(aPol[i],aRef1,aRef2); + } + // turn and move polygon + tools::Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect( aPol, aRectangle, aNewGeo ); + } + } + Point aPt( aRectangle.TopLeft() ); + + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aPt -= GetSdrObject()->GetAnchorPos(); + + ForceMetricTo100th_mm(aPt); + return css::awt::Point( aPt.X(), aPt.Y() ); + } + else + return SvxShape::getPosition(); +} + + +void SAL_CALL SvxCustomShape::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue ) +{ + ::SolarMutexGuard aGuard; + + SdrObject* pObject = GetSdrObject(); + + // 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 + if("FlushCustomShapeUnoApiObjects" == 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 replaceable and can be reset here. This + // will free the involved EditEngine and VirtualDevice. + pTarget->mxCustomShapeEngine.set(nullptr); + } + // since this case is only for the application cores + // we should return from this function now + return; + } + + bool bCustomShapeGeometry = pObject && aPropertyName == "CustomShapeGeometry"; + + bool bMirroredX = false; + bool bMirroredY = false; + + if ( bCustomShapeGeometry ) + { + bMirroredX = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredX(); + bMirroredY = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredY(); + } + + SvxShape::setPropertyValue( aPropertyName, aValue ); + + if ( !bCustomShapeGeometry ) + return; + + static_cast<SdrObjCustomShape*>(pObject)->MergeDefaultAttributes(); + tools::Rectangle aRect( pObject->GetSnapRect() ); + + // #i38892# + bool bNeedsMirrorX = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredX() != bMirroredX; + bool bNeedsMirrorY = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredY() != bMirroredY; + + std::unique_ptr< SdrGluePointList > pListCopy; + if( bNeedsMirrorX || bNeedsMirrorY ) + { + const SdrGluePointList* pList = pObject->GetGluePointList(); + if( pList ) + pListCopy.reset( new SdrGluePointList(*pList) ); + } + + if ( bNeedsMirrorX ) + { + Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() ); + Point aBottom( aTop.X(), aTop.Y() + 1000 ); + pObject->NbcMirror( aTop, aBottom ); + // NbcMirroring is flipping the current mirror state, + // so we have to set the correct state again + static_cast<SdrObjCustomShape*>(pObject)->SetMirroredX( !bMirroredX ); + } + if ( bNeedsMirrorY ) + { + Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 ); + Point aRight( aLeft.X() + 1000, aLeft.Y() ); + pObject->NbcMirror( aLeft, aRight ); + // NbcMirroring is flipping the current mirror state, + // so we have to set the correct state again + static_cast<SdrObjCustomShape*>(pObject)->SetMirroredY( !bMirroredY ); + } + + if( pListCopy ) + { + SdrGluePointList* pNewList = const_cast< SdrGluePointList* >( pObject->GetGluePointList() ); + if(pNewList) + *pNewList = *pListCopy; + } +} + +bool SvxCustomShape::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case SDRATTR_ROTATEANGLE: + { + double fAngle = static_cast<SdrObjCustomShape*>(GetSdrObject())->GetObjectRotation(); + fAngle *= 100; + rValue <<= static_cast<sal_Int32>(fAngle); + return true; + } + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } +} + +void SvxCustomShape::createCustomShapeDefaults( const OUString& rValueType ) +{ + if (!HasSdrObject()) + { + OSL_FAIL("could not create Custom Shape Defaults!"); + return; + } + + static_cast<SdrObjCustomShape*>(GetSdrObject())->MergeDefaultAttributes( &rValueType ); +} + +SvxShapeGroupAnyD::SvxShapeGroupAnyD( SdrObject* pObject, const SfxItemPropertyMapEntry* pEntries, const SvxItemPropertySet* pPropertySet ) + : SvxShape(pObject, pEntries, pPropertySet) +{} + +SvxShapeGroupAnyD::~SvxShapeGroupAnyD() noexcept +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoshap3.cxx b/svx/source/unodraw/unoshap3.cxx new file mode 100644 index 000000000..0704a4e5c --- /dev/null +++ b/svx/source/unodraw/unoshap3.cxx @@ -0,0 +1,1052 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <initializer_list> +#include <string_view> + +#include <com/sun/star/drawing/HomogenMatrix.hpp> +#include <com/sun/star/drawing/Position3D.hpp> +#include <com/sun/star/drawing/Direction3D.hpp> +#include <com/sun/star/drawing/DoubleSequence.hpp> +#include <com/sun/star/drawing/CameraGeometry.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <o3tl/safeint.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/sequence.hxx> +#include <sal/log.hxx> + +#include <svx/svdpool.hxx> +#include <svx/svditer.hxx> +#include <svx/unoshape.hxx> +#include <svx/unopage.hxx> +#include <svx/cube3d.hxx> +#include <svx/sphere3d.hxx> +#include <svx/lathe3d.hxx> +#include <extrud3d.hxx> +#include <polygn3d.hxx> +#include <svx/unoshprp.hxx> +#include <svx/svdmodel.hxx> +#include <svx/scene3d.hxx> +#include <basegfx/polygon/b3dpolygon.hxx> +#include <basegfx/polygon/b3dpolygontools.hxx> +#include <com/sun/star/drawing/PolyPolygonShape3D.hpp> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b3dhommatrixtools.hxx> +#include "shapeimpl.hxx" + +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; + +#define QUERYINT( xint ) \ + if( rType == cppu::UnoType<xint>::get() ) \ + aAny <<= Reference< xint >(this) + +Svx3DSceneObject::Svx3DSceneObject(SdrObject* pObj, SvxDrawPage* pDrawPage) +: SvxShapeGroupAnyD( pObj, getSvxMapProvider().GetMap(SVXMAP_3DSCENEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DSCENEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +, mxPage( pDrawPage ) +{ +} + + +Svx3DSceneObject::~Svx3DSceneObject() noexcept +{ +} + + +void Svx3DSceneObject::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) +{ + SvxShape::Create( pNewObj, pNewPage ); + mxPage = pNewPage; +} + + +uno::Any SAL_CALL Svx3DSceneObject::queryAggregation( const uno::Type & rType ) +{ + uno::Any aAny; + + QUERYINT( drawing::XShapes ); + else QUERYINT( container::XIndexAccess ); + else QUERYINT( container::XElementAccess ); + else + return SvxShape::queryAggregation( rType ); + + return aAny; +} + +uno::Any SAL_CALL Svx3DSceneObject::queryInterface( const uno::Type & rType ) +{ + return SvxShape::queryInterface( rType ); +} + +// XTypeProvider + +uno::Sequence< sal_Int8 > SAL_CALL Svx3DSceneObject::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + + +void SAL_CALL Svx3DSceneObject::add( const Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + SvxShape* pShape = comphelper::getFromUnoTunnel<SvxShape>( xShape ); + + if(!HasSdrObject() || !mxPage.is() || pShape == nullptr || nullptr != pShape->GetSdrObject() ) + throw uno::RuntimeException(); + + SdrObject* pSdrShape = mxPage->CreateSdrObject_( xShape ); + if( dynamic_cast<const E3dObject* >(pSdrShape) != nullptr ) + { + GetSdrObject()->GetSubList()->NbcInsertObject( pSdrShape ); + pShape->Create(pSdrShape, mxPage.get()); + } + else + { + SdrObject::Free( pSdrShape ); + throw uno::RuntimeException(); + } + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +void Svx3DSceneObject::addShape( SvxShape& rShape ) +{ + SolarMutexGuard aGuard; + + if(!HasSdrObject() || !mxPage.is() || nullptr != rShape.GetSdrObject() ) + throw uno::RuntimeException(); + + SdrObject* pSdrShape = mxPage->CreateSdrObject_( &rShape ); + if( dynamic_cast<const E3dObject* >(pSdrShape) != nullptr ) + { + GetSdrObject()->GetSubList()->NbcInsertObject( pSdrShape ); + rShape.Create(pSdrShape, mxPage.get()); + } + else + { + SdrObject::Free( pSdrShape ); + throw uno::RuntimeException(); + } + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +void SAL_CALL Svx3DSceneObject::remove( const Reference< drawing::XShape >& xShape ) +{ + SolarMutexGuard aGuard; + + SdrObject* pSdrShape = SdrObject::getSdrObjectFromXShape( xShape ); + + if(!HasSdrObject() || !pSdrShape || + pSdrShape->getParentSdrObjectFromSdrObject() != GetSdrObject()) + throw uno::RuntimeException(); + + SdrObjList& rList = *pSdrShape->getParentSdrObjListFromSdrObject(); + + const size_t nObjCount = rList.GetObjCount(); + size_t nObjNum = 0; + while( nObjNum < nObjCount ) + { + if(rList.GetObj( nObjNum ) == pSdrShape ) + break; + nObjNum++; + } + + if( nObjNum < nObjCount ) + { + SdrObject* pObject = rList.NbcRemoveObject( nObjNum ); + SdrObject::Free( pObject ); + } + else + { + SAL_WARN( "svx", "Fatality! SdrObject is not belonging to its SdrObjList! [CL]" ); + } +} + + +sal_Int32 SAL_CALL Svx3DSceneObject::getCount() +{ + SolarMutexGuard aGuard; + + sal_Int32 nRetval = 0; + + if(HasSdrObject() && dynamic_cast<const E3dScene* >(GetSdrObject()) != nullptr && GetSdrObject()->GetSubList()) + nRetval = GetSdrObject()->GetSubList()->GetObjCount(); + return nRetval; +} + + +uno::Any SAL_CALL Svx3DSceneObject::getByIndex( sal_Int32 Index ) +{ + SolarMutexGuard aGuard; + + if( !HasSdrObject() || GetSdrObject()->GetSubList() == nullptr ) + throw uno::RuntimeException(); + + if( Index<0 || GetSdrObject()->GetSubList()->GetObjCount() <= o3tl::make_unsigned(Index) ) + throw lang::IndexOutOfBoundsException(); + + SdrObject* pDestObj = GetSdrObject()->GetSubList()->GetObj( Index ); + if(pDestObj == nullptr) + throw lang::IndexOutOfBoundsException(); + + Reference< drawing::XShape > xShape( pDestObj->getUnoShape(), uno::UNO_QUERY ); + return uno::Any(xShape); +} + + +// css::container::XElementAccess + +uno::Type SAL_CALL Svx3DSceneObject::getElementType() +{ + return cppu::UnoType<drawing::XShape>::get(); +} + + +sal_Bool SAL_CALL Svx3DSceneObject::hasElements() +{ + SolarMutexGuard aGuard; + + return HasSdrObject() && GetSdrObject()->GetSubList() && (GetSdrObject()->GetSubList()->GetObjCount() > 0); +} + + +static bool ConvertHomogenMatrixToObject( E3dObject* pObject, const Any& rValue ) +{ + drawing::HomogenMatrix aMat; + if( rValue >>= aMat ) + { + pObject->SetTransform(basegfx::utils::UnoHomogenMatrixToB3DHomMatrix(aMat)); + return true; + } + return false; +} + +static void ConvertObjectToHomogenMatric( E3dObject const * pObject, Any& rValue ) +{ + drawing::HomogenMatrix aHomMat; + const basegfx::B3DHomMatrix& rMat = pObject->GetTransform(); + basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(rMat, aHomMat); + rValue <<= aHomMat; +} + +namespace { + +struct ImpRememberTransAndRect +{ + basegfx::B3DHomMatrix maMat; + tools::Rectangle maRect; +}; + +} + +bool Svx3DSceneObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // patch transformation matrix to the object + if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) ) + return true; + break; + } + case OWN_ATTR_3D_VALUE_CAMERA_GEOMETRY: + { + // set CameraGeometry at scene + E3dScene* pScene = static_cast< E3dScene* >( GetSdrObject() ); + drawing::CameraGeometry aCamGeo; + + if(rValue >>= aCamGeo) + { + basegfx::B3DPoint aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ); + basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ); + basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ); + + // rescue scene transformation + ImpRememberTransAndRect aSceneTAR; + aSceneTAR.maMat = pScene->GetTransform(); + aSceneTAR.maRect = pScene->GetSnapRect(); + + // rescue object transformations + SdrObjListIter aIter(pScene->GetSubList(), SdrIterMode::DeepWithGroups); + std::vector<basegfx::B3DHomMatrix*> aObjTrans; + while(aIter.IsMore()) + { + E3dObject* p3DObj = static_cast<E3dObject*>(aIter.Next()); + basegfx::B3DHomMatrix* pNew = new basegfx::B3DHomMatrix; + *pNew = p3DObj->GetTransform(); + aObjTrans.push_back(pNew); + } + + // reset object transformations + aIter.Reset(); + while(aIter.IsMore()) + { + E3dObject* p3DObj = static_cast<E3dObject*>(aIter.Next()); + p3DObj->NbcSetTransform(basegfx::B3DHomMatrix()); + } + + // reset scene transformation and make a complete recalc + pScene->NbcSetTransform(basegfx::B3DHomMatrix()); + + // fill old camera from new parameters + Camera3D aCam(pScene->GetCamera()); + const basegfx::B3DRange& rVolume = pScene->GetBoundVolume(); + double fW = rVolume.getWidth(); + double fH = rVolume.getHeight(); + + const SfxItemSet& rSceneSet = pScene->GetMergedItemSet(); + double fCamPosZ = + static_cast<double>(rSceneSet.Get(SDRATTR_3DSCENE_DISTANCE).GetValue()); + double fCamFocal = + static_cast<double>(rSceneSet.Get(SDRATTR_3DSCENE_FOCAL_LENGTH).GetValue()); + + aCam.SetAutoAdjustProjection(false); + aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH); + basegfx::B3DPoint aLookAt; + basegfx::B3DPoint aCamPos(0.0, 0.0, fCamPosZ); + aCam.SetPosAndLookAt(aCamPos, aLookAt); + aCam.SetFocalLength(fCamFocal / 100.0); + aCam.SetDeviceWindow(tools::Rectangle(0, 0, static_cast<tools::Long>(fW), static_cast<tools::Long>(fH))); + + // set at scene + pScene->SetCamera(aCam); + + // #91047# use imported VRP, VPN and VUP (if used) + bool bVRPUsed(!aVRP.equal(basegfx::B3DPoint(0.0, 0.0, 1.0))); + bool bVPNUsed(!aVPN.equal(basegfx::B3DVector(0.0, 0.0, 1.0))); + bool bVUPUsed(!aVUP.equal(basegfx::B3DVector(0.0, 1.0, 0.0))); + + if(bVRPUsed || bVPNUsed || bVUPUsed) + { + pScene->GetCameraSet().SetViewportValues(aVRP, aVPN, aVUP); + } + + // set object transformations again at objects + aIter.Reset(); + sal_uInt32 nIndex(0); + while(aIter.IsMore()) + { + E3dObject* p3DObj = static_cast<E3dObject*>(aIter.Next()); + basegfx::B3DHomMatrix* pMat = aObjTrans[nIndex++]; + p3DObj->NbcSetTransform(*pMat); + delete pMat; + } + + // set scene transformation again at scene + pScene->NbcSetTransform(aSceneTAR.maMat); + pScene->NbcSetSnapRect(aSceneTAR.maRect); + + return true; + } + break; + } + default: + return SvxShape::setPropertyValueImpl(rName, pProperty, rValue); + } + + throw IllegalArgumentException(); +} + + +bool Svx3DSceneObject::getPropertyValueImpl(const OUString& rName, const SfxItemPropertyMapEntry* pProperty, + css::uno::Any& rValue) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // patch object to a homogeneous 4x4 matrix + ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue ); + break; + } + case OWN_ATTR_3D_VALUE_CAMERA_GEOMETRY: + { + // get CameraGeometry from scene + E3dScene* pScene = static_cast< E3dScene* >( GetSdrObject() ); + drawing::CameraGeometry aCamGeo; + + // fill Vectors from scene camera + B3dCamera& aCameraSet = pScene->GetCameraSet(); + basegfx::B3DPoint aVRP(aCameraSet.GetVRP()); + basegfx::B3DVector aVPN(aCameraSet.GetVPN()); + basegfx::B3DVector aVUP(aCameraSet.GetVUV()); + + // transfer to structure + aCamGeo.vrp.PositionX = aVRP.getX(); + aCamGeo.vrp.PositionY = aVRP.getY(); + aCamGeo.vrp.PositionZ = aVRP.getZ(); + aCamGeo.vpn.DirectionX = aVPN.getX(); + aCamGeo.vpn.DirectionY = aVPN.getY(); + aCamGeo.vpn.DirectionZ = aVPN.getZ(); + aCamGeo.vup.DirectionX = aVUP.getX(); + aCamGeo.vup.DirectionY = aVUP.getY(); + aCamGeo.vup.DirectionZ = aVUP.getZ(); + + rValue <<= aCamGeo; + break; + } + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +// css::lang::XServiceInfo +uno::Sequence< OUString > SAL_CALL Svx3DSceneObject::getSupportedServiceNames() +{ + return comphelper::concatSequences( + SvxShape::getSupportedServiceNames(), + std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3DScene" }); +} + +Svx3DCubeObject::Svx3DCubeObject(SdrObject* pObj) +: SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DCUBEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DCUBEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +Svx3DCubeObject::~Svx3DCubeObject() noexcept +{ +} + +bool Svx3DCubeObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + SolarMutexGuard aGuard; + + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformationmatrix to the object + if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) ) + return true; + break; + } + case OWN_ATTR_3D_VALUE_POSITION: + { + // pack position to the object + drawing::Position3D aUnoPos; + if( rValue >>= aUnoPos ) + { + basegfx::B3DPoint aPos(aUnoPos.PositionX, aUnoPos.PositionY, aUnoPos.PositionZ); + static_cast< E3dCubeObj* >( GetSdrObject() )->SetCubePos(aPos); + return true; + } + break; + } + case OWN_ATTR_3D_VALUE_SIZE: + { + // pack size to the object + drawing::Direction3D aDirection; + if( rValue >>= aDirection ) + { + basegfx::B3DVector aSize(aDirection.DirectionX, aDirection.DirectionY, aDirection.DirectionZ); + static_cast< E3dCubeObj* >( GetSdrObject() )->SetCubeSize(aSize); + return true; + } + break; + } + case OWN_ATTR_3D_VALUE_POS_IS_CENTER: + { + bool bNew = false; + // pack sal_Bool bPosIsCenter to the object + if( rValue >>= bNew ) + { + static_cast< E3dCubeObj* >( GetSdrObject() )->SetPosIsCenter(bNew); + return true; + } + break; + } + default: + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + +bool Svx3DCubeObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation to a homogeneous matrix + ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue ); + break; + } + case OWN_ATTR_3D_VALUE_POSITION: + { + // pack position + const basegfx::B3DPoint& rPos = static_cast<E3dCubeObj*>(GetSdrObject())->GetCubePos(); + drawing::Position3D aPos; + + aPos.PositionX = rPos.getX(); + aPos.PositionY = rPos.getY(); + aPos.PositionZ = rPos.getZ(); + + rValue <<= aPos; + break; + } + case OWN_ATTR_3D_VALUE_SIZE: + { + // pack size + const basegfx::B3DVector& rSize = static_cast<E3dCubeObj*>(GetSdrObject())->GetCubeSize(); + drawing::Direction3D aDir; + + aDir.DirectionX = rSize.getX(); + aDir.DirectionY = rSize.getY(); + aDir.DirectionZ = rSize.getZ(); + + rValue <<= aDir; + break; + } + case OWN_ATTR_3D_VALUE_POS_IS_CENTER: + { + rValue <<= static_cast<E3dCubeObj*>(GetSdrObject())->GetPosIsCenter(); + break; + } + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +// css::lang::XServiceInfo +uno::Sequence< OUString > SAL_CALL Svx3DCubeObject::getSupportedServiceNames() +{ + return comphelper::concatSequences( + SvxShape::getSupportedServiceNames(), + std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D", + u"com.sun.star.drawing.Shape3DCube" }); +} + +Svx3DSphereObject::Svx3DSphereObject(SdrObject* pObj) + : SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DSPHEREOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DSPHEREOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +Svx3DSphereObject::~Svx3DSphereObject() noexcept +{ +} + +bool Svx3DSphereObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation matrix to the object + if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) ) + return true; + break; + } + + case OWN_ATTR_3D_VALUE_POSITION: + { + // pack position to the object + drawing::Position3D aUnoPos; + if( rValue >>= aUnoPos ) + { + basegfx::B3DPoint aPos(aUnoPos.PositionX, aUnoPos.PositionY, aUnoPos.PositionZ); + static_cast<E3dSphereObj*>(GetSdrObject())->SetCenter(aPos); + return true; + } + break; + } + + case OWN_ATTR_3D_VALUE_SIZE: + { + // pack size to the object + drawing::Direction3D aDir; + if( rValue >>= aDir ) + { + basegfx::B3DVector aPos(aDir.DirectionX, aDir.DirectionY, aDir.DirectionZ); + static_cast<E3dSphereObj*>(GetSdrObject())->SetSize(aPos); + return true; + } + break; + } + default: + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + +bool Svx3DSphereObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation to a homogeneous matrix + ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue ); + break; + } + case OWN_ATTR_3D_VALUE_POSITION: + { + // pack position + const basegfx::B3DPoint& rPos = static_cast<E3dSphereObj*>(GetSdrObject())->Center(); + drawing::Position3D aPos; + + aPos.PositionX = rPos.getX(); + aPos.PositionY = rPos.getY(); + aPos.PositionZ = rPos.getZ(); + + rValue <<= aPos; + break; + } + case OWN_ATTR_3D_VALUE_SIZE: + { + // pack size + const basegfx::B3DVector& rSize = static_cast<E3dSphereObj*>(GetSdrObject())->Size(); + drawing::Direction3D aDir; + + aDir.DirectionX = rSize.getX(); + aDir.DirectionY = rSize.getY(); + aDir.DirectionZ = rSize.getZ(); + + rValue <<= aDir; + break; + } + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +// css::lang::XServiceInfo +uno::Sequence< OUString > SAL_CALL Svx3DSphereObject::getSupportedServiceNames() +{ + return comphelper::concatSequences( + SvxShape::getSupportedServiceNames(), + std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D", + u"com.sun.star.drawing.Shape3DSphere" }); +} + +Svx3DLatheObject::Svx3DLatheObject(SdrObject* pObj) +: SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DLATHEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DLATHEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +Svx3DLatheObject::~Svx3DLatheObject() noexcept +{ +} + +static bool PolyPolygonShape3D_to_B3dPolyPolygon( + const Any& rValue, + basegfx::B3DPolyPolygon& rResultPolygon, + bool bCorrectPolygon) +{ + drawing::PolyPolygonShape3D aSourcePolyPolygon; + if( !(rValue >>= aSourcePolyPolygon) ) + return false; + + sal_Int32 nOuterSequenceCount = aSourcePolyPolygon.SequenceX.getLength(); + if(nOuterSequenceCount != aSourcePolyPolygon.SequenceY.getLength() || nOuterSequenceCount != aSourcePolyPolygon.SequenceZ.getLength()) + return false; + + const drawing::DoubleSequence* pInnerSequenceX = aSourcePolyPolygon.SequenceX.getConstArray(); + const drawing::DoubleSequence* pInnerSequenceY = aSourcePolyPolygon.SequenceY.getConstArray(); + const drawing::DoubleSequence* pInnerSequenceZ = aSourcePolyPolygon.SequenceZ.getConstArray(); + for(sal_Int32 a(0);a<nOuterSequenceCount;a++) + { + sal_Int32 nInnerSequenceCount = pInnerSequenceX->getLength(); + if(nInnerSequenceCount != pInnerSequenceY->getLength() || nInnerSequenceCount != pInnerSequenceZ->getLength()) + { + return false; + } + basegfx::B3DPolygon aNewPolygon; + const double* pArrayX = pInnerSequenceX->getConstArray(); + const double* pArrayY = pInnerSequenceY->getConstArray(); + const double* pArrayZ = pInnerSequenceZ->getConstArray(); + for(sal_Int32 b(0);b<nInnerSequenceCount;b++) + { + aNewPolygon.append(basegfx::B3DPoint(*pArrayX++,*pArrayY++,*pArrayZ++)); + } + pInnerSequenceX++; + pInnerSequenceY++; + pInnerSequenceZ++; + + // #i101520# correction is needed for imported polygons of old format, + // see callers + if(bCorrectPolygon) + { + basegfx::utils::checkClosed(aNewPolygon); + } + + rResultPolygon.append(aNewPolygon); + } + return true; +} + +static void B3dPolyPolygon_to_PolyPolygonShape3D( const basegfx::B3DPolyPolygon& rSourcePolyPolygon, Any& rValue ) +{ + drawing::PolyPolygonShape3D aRetval; + aRetval.SequenceX.realloc(rSourcePolyPolygon.count()); + aRetval.SequenceY.realloc(rSourcePolyPolygon.count()); + aRetval.SequenceZ.realloc(rSourcePolyPolygon.count()); + drawing::DoubleSequence* pOuterSequenceX = aRetval.SequenceX.getArray(); + drawing::DoubleSequence* pOuterSequenceY = aRetval.SequenceY.getArray(); + drawing::DoubleSequence* pOuterSequenceZ = aRetval.SequenceZ.getArray(); + for(sal_uInt32 a(0);a<rSourcePolyPolygon.count();a++) + { + const basegfx::B3DPolygon& aPoly(rSourcePolyPolygon.getB3DPolygon(a)); + sal_Int32 nPointCount(aPoly.count()); + if(aPoly.isClosed()) nPointCount++; + pOuterSequenceX->realloc(nPointCount); + pOuterSequenceY->realloc(nPointCount); + pOuterSequenceZ->realloc(nPointCount); + double* pInnerSequenceX = pOuterSequenceX->getArray(); + double* pInnerSequenceY = pOuterSequenceY->getArray(); + double* pInnerSequenceZ = pOuterSequenceZ->getArray(); + for(sal_uInt32 b(0);b<aPoly.count();b++) + { + const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(b)); + *pInnerSequenceX++ = aPoint.getX(); + *pInnerSequenceY++ = aPoint.getY(); + *pInnerSequenceZ++ = aPoint.getZ(); + } + if(aPoly.isClosed()) + { + const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(0)); + *pInnerSequenceX++ = aPoint.getX(); + *pInnerSequenceY++ = aPoint.getY(); + *pInnerSequenceZ++ = aPoint.getZ(); + } + pOuterSequenceX++; + pOuterSequenceY++; + pOuterSequenceZ++; + } + rValue <<= aRetval; +} + +bool Svx3DLatheObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation matrix to the object + if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) ) + return true; + break; + } + case OWN_ATTR_3D_VALUE_POLYPOLYGON3D: + { + // pack polygon definition to the object + basegfx::B3DPolyPolygon aNewB3DPolyPolygon; + + // #i101520# Probably imported + if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, true ) ) + { + // #105127# SetPolyPoly3D sets the Svx3DVerticalSegmentsItem to the number + // of points of the polygon. Thus, value gets lost. To avoid this, rescue + // item here and re-set after setting the polygon. + const sal_uInt32 nPrevVerticalSegs(static_cast<E3dLatheObj*>(GetSdrObject())->GetVerticalSegments()); + + // set polygon + const basegfx::B3DHomMatrix aIdentity; + const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aNewB3DPolyPolygon, aIdentity)); + static_cast<E3dLatheObj*>(GetSdrObject())->SetPolyPoly2D(aB2DPolyPolygon); + const sal_uInt32 nPostVerticalSegs(static_cast<E3dLatheObj*>(GetSdrObject())->GetVerticalSegments()); + + if(nPrevVerticalSegs != nPostVerticalSegs) + { + // restore the vertical segment count + static_cast<E3dLatheObj*>(GetSdrObject())->SetMergedItem(makeSvx3DVerticalSegmentsItem(nPrevVerticalSegs)); + } + return true; + } + break; + } + default: + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + +bool Svx3DLatheObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation to a homogeneous matrix + drawing::HomogenMatrix aHomMat; + basegfx::B3DHomMatrix aMat = static_cast<E3dObject*>(GetSdrObject())->GetTransform(); + basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aMat, aHomMat); + rValue <<= aHomMat; + break; + } + case OWN_ATTR_3D_VALUE_POLYPOLYGON3D: + { + const basegfx::B2DPolyPolygon& rPolyPoly = static_cast<E3dLatheObj*>(GetSdrObject())->GetPolyPoly2D(); + const basegfx::B3DPolyPolygon aB3DPolyPolygon(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(rPolyPoly)); + + B3dPolyPolygon_to_PolyPolygonShape3D(aB3DPolyPolygon, rValue); + break; + } + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +// css::lang::XServiceInfo +uno::Sequence< OUString > SAL_CALL Svx3DLatheObject::getSupportedServiceNames() +{ + return comphelper::concatSequences( + SvxShape::getSupportedServiceNames(), + std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D", + u"com.sun.star.drawing.Shape3DLathe" }); +} + +Svx3DExtrudeObject::Svx3DExtrudeObject(SdrObject* pObj) +: SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DEXTRUDEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DEXTRUDEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +Svx3DExtrudeObject::~Svx3DExtrudeObject() noexcept +{ +} + +bool Svx3DExtrudeObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation matrix to the object + if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) ) + return true; + break; + } + + case OWN_ATTR_3D_VALUE_POLYPOLYGON3D: + { + // pack polygon definition to the object + basegfx::B3DPolyPolygon aNewB3DPolyPolygon; + + // #i101520# Probably imported + if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, true ) ) + { + // set polygon + const basegfx::B3DHomMatrix aIdentity; + const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aNewB3DPolyPolygon, aIdentity)); + static_cast<E3dExtrudeObj*>(GetSdrObject())->SetExtrudePolygon(aB2DPolyPolygon); + return true; + } + break; + } + default: + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + +bool Svx3DExtrudeObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation to a homogeneous matrix + drawing::HomogenMatrix aHomMat; + basegfx::B3DHomMatrix aMat = static_cast<E3dObject*>(GetSdrObject())->GetTransform(); + basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aMat, aHomMat); + rValue <<= aHomMat; + break; + } + + case OWN_ATTR_3D_VALUE_POLYPOLYGON3D: + { + // pack polygon definition + const basegfx::B2DPolyPolygon& rPolyPoly = static_cast<E3dExtrudeObj*>(GetSdrObject())->GetExtrudePolygon(); + const basegfx::B3DPolyPolygon aB3DPolyPolygon(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(rPolyPoly)); + + B3dPolyPolygon_to_PolyPolygonShape3D(aB3DPolyPolygon, rValue); + break; + } + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +// css::lang::XServiceInfo +uno::Sequence< OUString > SAL_CALL Svx3DExtrudeObject::getSupportedServiceNames() +{ + return comphelper::concatSequences( + SvxShape::getSupportedServiceNames(), + std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D", + u"com.sun.star.drawing.Shape3DExtrude" }); +} + +Svx3DPolygonObject::Svx3DPolygonObject(SdrObject* pObj) +: SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DPOLYGONOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DPOLYGONOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +Svx3DPolygonObject::~Svx3DPolygonObject() noexcept +{ +} + +bool Svx3DPolygonObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + // pack transformation matrix to the object + if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) ) + return true; + break; + } + + case OWN_ATTR_3D_VALUE_POLYPOLYGON3D: + { + // pack polygon definition to the object + basegfx::B3DPolyPolygon aNewB3DPolyPolygon; + + // #i101520# Direct API data (e.g. from chart) + if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, false ) ) + { + // set polygon + static_cast<E3dPolygonObj*>(GetSdrObject())->SetPolyPolygon3D(aNewB3DPolyPolygon); + return true; + } + break; + } + case OWN_ATTR_3D_VALUE_NORMALSPOLYGON3D: + { + // pack perpendicular definition to the object + basegfx::B3DPolyPolygon aNewB3DPolyPolygon; + + // #i101520# Direct API data (e.g. from chart) + if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, false ) ) + { + // set polygon + static_cast<E3dPolygonObj*>(GetSdrObject())->SetPolyNormals3D(aNewB3DPolyPolygon); + return true; + } + break; + } + case OWN_ATTR_3D_VALUE_TEXTUREPOLYGON3D: + { + // pack texture definition to the object + basegfx::B3DPolyPolygon aNewB3DPolyPolygon; + + // #i101520# Direct API data (e.g. from chart) + if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, false ) ) + { + // set polygon + const basegfx::B3DHomMatrix aIdentity; + const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aNewB3DPolyPolygon, aIdentity)); + static_cast<E3dPolygonObj*>(GetSdrObject())->SetPolyTexture2D(aB2DPolyPolygon); + return true; + } + break; + } + case OWN_ATTR_3D_VALUE_LINEONLY: + { + bool bNew = false; + if( rValue >>= bNew ) + { + static_cast<E3dPolygonObj*>(GetSdrObject())->SetLineOnly(bNew); + return true; + } + break; + } + default: + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + +bool Svx3DPolygonObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX: + { + ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue ); + break; + } + + case OWN_ATTR_3D_VALUE_POLYPOLYGON3D: + { + B3dPolyPolygon_to_PolyPolygonShape3D(static_cast<E3dPolygonObj*>(GetSdrObject())->GetPolyPolygon3D(),rValue); + break; + } + + case OWN_ATTR_3D_VALUE_NORMALSPOLYGON3D: + { + B3dPolyPolygon_to_PolyPolygonShape3D(static_cast<E3dPolygonObj*>(GetSdrObject())->GetPolyNormals3D(),rValue); + break; + } + + case OWN_ATTR_3D_VALUE_TEXTUREPOLYGON3D: + { + // pack texture definition + const basegfx::B2DPolyPolygon& rPolyPoly = static_cast<E3dPolygonObj*>(GetSdrObject())->GetPolyTexture2D(); + const basegfx::B3DPolyPolygon aB3DPolyPolygon(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(rPolyPoly)); + + B3dPolyPolygon_to_PolyPolygonShape3D(aB3DPolyPolygon,rValue); + break; + } + + case OWN_ATTR_3D_VALUE_LINEONLY: + { + rValue <<= static_cast<E3dPolygonObj*>(GetSdrObject())->GetLineOnly(); + break; + } + + default: + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +// css::lang::XServiceInfo +uno::Sequence< OUString > SAL_CALL Svx3DPolygonObject::getSupportedServiceNames() +{ + return comphelper::concatSequences( + SvxShape::getSupportedServiceNames(), + std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D", + u"com.sun.star.drawing.Shape3DPolygon" }); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx new file mode 100644 index 000000000..18ce14f5e --- /dev/null +++ b/svx/source/unodraw/unoshap4.cxx @@ -0,0 +1,1115 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/embed/XLinkageSupport.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/ContentCreationException.hpp> + +#include <svx/svdoole2.hxx> +#include <svx/svdomedia.hxx> +#include <svx/svdpool.hxx> +#include <comphelper/classids.hxx> +#include <comphelper/embeddedobjectcontainer.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/propertyvalue.hxx> +#include <cppuhelper/exc_hlp.hxx> + +#include <toolkit/helper/vclunohelper.hxx> + +#include <sot/exchange.hxx> + +#include <svx/svdmodel.hxx> +#include "shapeimpl.hxx" + +#include <svx/unoshprp.hxx> + +#include <vcl/gdimtf.hxx> +#include <vcl/wmf.hxx> +#include <svtools/embedhlp.hxx> +#include <sal/log.hxx> +#include <tools/debug.hxx> +#include <tools/globname.hxx> +#include <tools/stream.hxx> + +#include <config_features.h> + + +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; + + +SvxOle2Shape::SvxOle2Shape(SdrObject* pObject) +: SvxShapeText( pObject, getSvxMapProvider().GetMap(SVXMAP_OLE2), + getSvxMapProvider().GetPropertySet(SVXMAP_OLE2,SdrObject::GetGlobalDrawObjectItemPool()) ) +{ +} + +SvxOle2Shape::SvxOle2Shape(SdrObject* pObject, const SfxItemPropertyMapEntry* pPropertyMap, const SvxItemPropertySet* pPropertySet) +: SvxShapeText( pObject, pPropertyMap, pPropertySet ) +{ +} + +SvxOle2Shape::~SvxOle2Shape() noexcept +{ +} + +//XPropertySet +bool SvxOle2Shape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_OLE_VISAREA: + { + // TODO/LATER: seems to make no sense for iconified object + + awt::Rectangle aVisArea; + if( !(rValue >>= aVisArea)) + break; + if( auto pOle2Obj = dynamic_cast<SdrOle2Obj* >(GetSdrObject()) ) + { + Size aTmp( aVisArea.X + aVisArea.Width, aVisArea.Y + aVisArea.Height ); + uno::Reference < embed::XEmbeddedObject > xObj = pOle2Obj->GetObjRef(); + if( xObj.is() ) + { + try + { + // the API handles with MapUnit::Map100thMM map mode + MapUnit aObjUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( embed::Aspects::MSOLE_CONTENT ) ); + aTmp = OutputDevice::LogicToLogic(aTmp, MapMode(MapUnit::Map100thMM), MapMode(aObjUnit)); + xObj->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, awt::Size( aTmp.Width(), aTmp.Height() ) ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "Couldn't set the visual area for the object!" ); + } + } + + return true; + } + break; + } + case OWN_ATTR_OLE_ASPECT: + { + sal_Int64 nAspect = 0; + if( rValue >>= nAspect ) + { + static_cast<SdrOle2Obj*>(GetSdrObject())->SetAspect( nAspect ); + return true; + } + break; + } + case OWN_ATTR_CLSID: + { + OUString aCLSID; + if( rValue >>= aCLSID ) + { + // init an OLE object with a global name + SvGlobalName aClassName; + if( aClassName.MakeId( aCLSID ) ) + { + if( createObject( aClassName ) ) + return true; + } + } + break; + } + case OWN_ATTR_THUMBNAIL: + { + uno::Reference< graphic::XGraphic > xGraphic( rValue, uno::UNO_QUERY ); + if( xGraphic.is() ) + { + const Graphic aGraphic(xGraphic); + static_cast<SdrOle2Obj*>(GetSdrObject())->SetGraphic(aGraphic); + return true; + } + break; + } + case OWN_ATTR_VALUE_GRAPHIC: + { + uno::Reference< graphic::XGraphic > xGraphic( rValue, uno::UNO_QUERY ); + if( xGraphic.is() ) + { + SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + if( pOle ) + { + GraphicObject aGrafObj( xGraphic ); + const Graphic& aGraphic( aGrafObj.GetGraphic() ); + pOle->SetGraphicToObj( aGraphic ); + } + return true; + } + break; + } + case OWN_ATTR_PERSISTNAME: + { + OUString aPersistName; + if( rValue >>= aPersistName ) + { + SdrOle2Obj *pOle; +#if OSL_DEBUG_LEVEL > 0 + pOle = dynamic_cast<SdrOle2Obj*>(GetSdrObject()); + assert(pOle); +#else + pOle = static_cast<SdrOle2Obj*>(GetSdrObject()); +#endif + pOle->SetPersistName( aPersistName, this ); + return true; + } + break; + } + case OWN_ATTR_OLE_LINKURL: + { + OUString aLinkURL; + if( rValue >>= aLinkURL ) + { + createLink( aLinkURL ); + return true; + } + break; + } + default: + return SvxShapeText::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + +bool SvxOle2Shape::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_CLSID: + { + OUString aCLSID; + GetClassName_Impl(aCLSID); + rValue <<= aCLSID; + break; + } + + case OWN_ATTR_INTERNAL_OLE: + { + OUString sCLSID; + rValue <<= SotExchange::IsInternal( GetClassName_Impl(sCLSID) ); + break; + } + + case OWN_ATTR_METAFILE: + { + SdrOle2Obj* pObj = dynamic_cast<SdrOle2Obj*>(GetSdrObject()); + if( pObj ) + { + const Graphic* pGraphic = pObj->GetGraphic(); + if( pGraphic ) + { + bool bIsWMF = false; + if ( pGraphic->IsGfxLink() ) + { + GfxLink aLnk = pGraphic->GetGfxLink(); + if ( aLnk.GetType() == GfxLinkType::NativeWmf ) + { + bIsWMF = true; + uno::Sequence<sal_Int8> aSeq(reinterpret_cast<sal_Int8 const *>(aLnk.GetData()), static_cast<sal_Int32>(aLnk.GetDataSize())); + rValue <<= aSeq; + } + } + if ( !bIsWMF ) + { + // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically + GDIMetaFile aMtf(pObj->GetGraphic()->GetGDIMetaFile()); + SvMemoryStream aDestStrm( 65535, 65535 ); + ConvertGDIMetaFileToWMF( aMtf, aDestStrm, nullptr, false ); + const uno::Sequence<sal_Int8> aSeq( + static_cast< const sal_Int8* >(aDestStrm.GetData()), + aDestStrm.GetEndOfData()); + rValue <<= aSeq; + } + } + } + else + { + rValue = GetBitmap( true ); + } + break; + } + + case OWN_ATTR_OLE_VISAREA: + { + awt::Rectangle aVisArea; + if( dynamic_cast<const SdrOle2Obj* >(GetSdrObject()) != nullptr) + { + MapMode aMapMode( MapUnit::Map100thMM ); // the API uses this map mode + Size aTmp = static_cast<SdrOle2Obj*>(GetSdrObject())->GetOrigObjSize( &aMapMode ); // get the size in the requested map mode + aVisArea = awt::Rectangle( 0, 0, aTmp.Width(), aTmp.Height() ); + } + + rValue <<= aVisArea; + break; + } + + case OWN_ATTR_OLESIZE: + { + Size aTmp( static_cast<SdrOle2Obj*>(GetSdrObject())->GetOrigObjSize() ); + rValue <<= awt::Size( aTmp.Width(), aTmp.Height() ); + break; + } + + case OWN_ATTR_OLE_ASPECT: + { + rValue <<= static_cast<SdrOle2Obj*>(GetSdrObject())->GetAspect(); + break; + } + + case OWN_ATTR_OLEMODEL: + case OWN_ATTR_OLE_EMBEDDED_OBJECT: + case OWN_ATTR_OLE_EMBEDDED_OBJECT_NONEWCLIENT: + { + SdrOle2Obj* pObj = dynamic_cast<SdrOle2Obj*>( GetSdrObject() ); + if( pObj ) + { + uno::Reference < embed::XEmbeddedObject > xObj( pObj->GetObjRef() ); + if ( xObj.is() + && ( pProperty->nWID == OWN_ATTR_OLE_EMBEDDED_OBJECT || pProperty->nWID == OWN_ATTR_OLE_EMBEDDED_OBJECT_NONEWCLIENT || svt::EmbeddedObjectRef::TryRunningState( xObj ) ) ) + { + // Discussed with CL fue to the before GetPaintingPageView + // usage. Removed it, former fallback is used now + if ( pProperty->nWID == OWN_ATTR_OLEMODEL || pProperty->nWID == OWN_ATTR_OLE_EMBEDDED_OBJECT ) + { + const bool bSuccess(pObj->AddOwnLightClient()); + SAL_WARN_IF(!bSuccess, "svx.svdraw", "An object without client is provided!"); + } + + if ( pProperty->nWID == OWN_ATTR_OLEMODEL ) + rValue <<= pObj->GetObjRef()->getComponent(); + else + rValue <<= xObj; + } + } + break; + } + + case OWN_ATTR_VALUE_GRAPHIC: + { + uno::Reference< graphic::XGraphic > xGraphic; + const Graphic* pGraphic = static_cast<SdrOle2Obj*>( GetSdrObject() )->GetGraphic(); + if( pGraphic ) + xGraphic = pGraphic->GetXGraphic(); + rValue <<= xGraphic; + break; + } + + case OWN_ATTR_THUMBNAIL: + { + uno::Reference< graphic::XGraphic > xGraphic; + const Graphic* pGraphic = static_cast<SdrOle2Obj*>( GetSdrObject() )->GetGraphic(); + if( pGraphic ) + xGraphic = pGraphic->GetXGraphic(); + rValue <<= xGraphic; + break; + } + case OWN_ATTR_PERSISTNAME: + { + OUString aPersistName; + SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + + if( pOle ) + { + aPersistName = pOle->GetPersistName(); + if( !aPersistName.isEmpty() ) + { + ::comphelper::IEmbeddedHelper* pPersist(GetSdrObject()->getSdrModelFromSdrObject().GetPersist()); + if( (nullptr == pPersist) || !pPersist->getEmbeddedObjectContainer().HasEmbeddedObject( pOle->GetPersistName() ) ) + aPersistName.clear(); + } + } + + rValue <<= aPersistName; + break; + } + case OWN_ATTR_OLE_LINKURL: + { + OUString aLinkURL; + SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + + if( pOle ) + { + uno::Reference< embed::XLinkageSupport > xLink( pOle->GetObjRef(), uno::UNO_QUERY ); + if ( xLink.is() && xLink->isLink() ) + aLinkURL = xLink->getLinkURL(); + } + + rValue <<= aLinkURL; + break; + } + default: + return SvxShapeText::getPropertyValueImpl( rName, pProperty, rValue ); + } + + return true; +} + +bool SvxOle2Shape::createObject( const SvGlobalName &aClassName ) +{ + DBG_TESTSOLARMUTEX(); + + SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + if ( !pOle2Obj || !pOle2Obj->IsEmpty() ) + return false; + + // create storage and inplace object + ::comphelper::IEmbeddedHelper* pPersist = GetSdrObject()->getSdrModelFromSdrObject().GetPersist(); + OUString aPersistName; + OUString aTmpStr; + if( SvxShape::getPropertyValue( UNO_NAME_OLE2_PERSISTNAME ) >>= aTmpStr ) + aPersistName = aTmpStr; + + uno::Sequence<beans::PropertyValue> objArgs( comphelper::InitPropertySequence({ + { "DefaultParentBaseURL", Any(pPersist->getDocumentBaseURL()) } + })); + //TODO/LATER: how to cope with creation failure?! + uno::Reference<embed::XEmbeddedObject> xObj( + pPersist->getEmbeddedObjectContainer().CreateEmbeddedObject( + aClassName.GetByteSequence(), objArgs, aPersistName)); + if( xObj.is() ) + { + tools::Rectangle aRect = pOle2Obj->GetLogicRect(); + if ( aRect.GetWidth() == 101 && aRect.GetHeight() == 101 ) + { + // TODO/LATER: is it possible that this method is used to create an iconified object? + // default size + try + { + awt::Size aSz = xObj->getVisualAreaSize( pOle2Obj->GetAspect() ); + aRect.SetSize( Size( aSz.Width, aSz.Height ) ); + } + catch( embed::NoVisualAreaSizeException& ) + {} + pOle2Obj->SetLogicRect( aRect ); + } + else + { + awt::Size aSz; + Size aSize = aRect.GetSize(); + aSz.Width = aSize.Width(); + aSz.Height = aSize.Height(); + if (aSz.Width != 0 || aSz.Height != 0) + { + //HACK: can aSz legally be empty? + xObj->setVisualAreaSize( pOle2Obj->GetAspect(), aSz ); + } + } + + // connect the object after the visual area is set + aTmpStr = aPersistName; + SvxShape::setPropertyValue( UNO_NAME_OLE2_PERSISTNAME, Any( aTmpStr ) ); + + // the object is inserted during setting of PersistName property usually + if( pOle2Obj->IsEmpty() ) + pOle2Obj->SetObjRef( xObj ); + } + + return xObj.is(); +} + +void SvxOle2Shape::createLink( const OUString& aLinkURL ) +{ + DBG_TESTSOLARMUTEX(); + + SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + if ( !pOle2Obj || !pOle2Obj->IsEmpty() ) + return; + + OUString aPersistName; + + ::comphelper::IEmbeddedHelper* pPersist = GetSdrObject()->getSdrModelFromSdrObject().GetPersist(); + + uno::Sequence< beans::PropertyValue > aMediaDescr{ comphelper::makePropertyValue("URL", + aLinkURL) }; + + uno::Reference< task::XInteractionHandler > xInteraction = pPersist->getInteractionHandler(); + if ( xInteraction.is() ) + { + aMediaDescr.realloc( 2 ); + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[1].Name = "InteractionHandler"; + pMediaDescr[1].Value <<= xInteraction; + } + + //TODO/LATER: how to cope with creation failure?! + uno::Reference< embed::XEmbeddedObject > xObj = + pPersist->getEmbeddedObjectContainer().InsertEmbeddedLink( aMediaDescr , aPersistName ); + + if( !xObj.is() ) + return; + + tools::Rectangle aRect = pOle2Obj->GetLogicRect(); + if ( aRect.GetWidth() == 101 && aRect.GetHeight() == 101 ) + { + // default size + try + { + awt::Size aSz = xObj->getVisualAreaSize( pOle2Obj->GetAspect() ); + aRect.SetSize( Size( aSz.Width, aSz.Height ) ); + } + catch( embed::NoVisualAreaSizeException& ) + {} + pOle2Obj->SetLogicRect( aRect ); + } + else + { + awt::Size aSz; + Size aSize = pOle2Obj->GetLogicRect().GetSize(); + aSz.Width = aSize.Width(); + aSz.Height = aSize.Height(); + xObj->setVisualAreaSize( pOle2Obj->GetAspect(), aSz ); + } + + // connect the object after the visual area is set + SvxShape::setPropertyValue( UNO_NAME_OLE2_PERSISTNAME, uno::Any( aPersistName ) ); + + // the object is inserted during setting of PersistName property usually + if ( pOle2Obj->IsEmpty() ) + pOle2Obj->SetObjRef( xObj ); +} + +void SvxOle2Shape::resetModifiedState() +{ + SdrObject* pObject = GetSdrObject(); + ::comphelper::IEmbeddedHelper* pPersist = pObject ? pObject->getSdrModelFromSdrObject().GetPersist() : nullptr; + if( pPersist && !pPersist->isEnableSetModified() ) + { + SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >(pObject); + if( pOle && !pOle->IsEmpty() ) + { + uno::Reference < util::XModifiable > xMod( pOle->GetObjRef(), uno::UNO_QUERY ); + if( xMod.is() ) + // TODO/MBA: what's this?! + xMod->setModified( false ); + } + } +} + +SvGlobalName SvxOle2Shape::GetClassName_Impl(OUString& rHexCLSID) +{ + DBG_TESTSOLARMUTEX(); + SvGlobalName aClassName; + SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + + if( pOle2Obj ) + { + rHexCLSID.clear(); + + if( pOle2Obj->IsEmpty() ) + { + ::comphelper::IEmbeddedHelper* pPersist = GetSdrObject()->getSdrModelFromSdrObject().GetPersist(); + if( pPersist ) + { + uno::Reference < embed::XEmbeddedObject > xObj = + pPersist->getEmbeddedObjectContainer().GetEmbeddedObject( pOle2Obj->GetPersistName() ); + if ( xObj.is() ) + { + aClassName = SvGlobalName( xObj->getClassID() ); + rHexCLSID = aClassName.GetHexName(); + } + } + } + + if (rHexCLSID.isEmpty()) + { + const uno::Reference < embed::XEmbeddedObject >& xObj( pOle2Obj->GetObjRef() ); + if ( xObj.is() ) + { + aClassName = SvGlobalName( xObj->getClassID() ); + rHexCLSID = aClassName.GetHexName(); + } + } + } + + return aClassName; +} + +OUString SvxOle2Shape::GetAndClearInitialFrameURL() +{ + return OUString(); +} + +SvxAppletShape::SvxAppletShape(SdrObject* pObject) + : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_APPLET), getSvxMapProvider().GetPropertySet(SVXMAP_APPLET, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ + SetShapeType( "com.sun.star.drawing.AppletShape" ); +} + +SvxAppletShape::~SvxAppletShape() noexcept +{ +} + +void SvxAppletShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) +{ + SvxShape::Create( pNewObj, pNewPage ); + const SvGlobalName aAppletClassId( SO3_APPLET_CLASSID ); + createObject(aAppletClassId); + SetShapeType( "com.sun.star.drawing.AppletShape" ); +} + +void SAL_CALL SvxAppletShape::setPropertyValue( const OUString& aPropertyName, const css::uno::Any& rValue ) +{ + SvxShape::setPropertyValue( aPropertyName, rValue ); + resetModifiedState(); +} + +void SAL_CALL SvxAppletShape::setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& rValues ) +{ + SvxShape::setPropertyValues( aPropertyNames, rValues ); + resetModifiedState(); +} + +bool SvxAppletShape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + if( (pProperty->nWID >= OWN_ATTR_APPLET_DOCBASE) && (pProperty->nWID <= OWN_ATTR_APPLET_ISSCRIPT) ) + { + if ( svt::EmbeddedObjectRef::TryRunningState( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef() ) ) + { + uno::Reference < beans::XPropertySet > xSet( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef()->getComponent(), uno::UNO_QUERY ); + if( xSet.is() ) + { + // allow exceptions to pass through + xSet->setPropertyValue( rName, rValue ); + } + } + return true; + } + else + { + return SvxOle2Shape::setPropertyValueImpl( rName, pProperty, rValue ); + } +} + +bool SvxAppletShape::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + if( (pProperty->nWID >= OWN_ATTR_APPLET_DOCBASE) && (pProperty->nWID <= OWN_ATTR_APPLET_ISSCRIPT) ) + { + if ( svt::EmbeddedObjectRef::TryRunningState( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef() ) ) + { + uno::Reference < beans::XPropertySet > xSet( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef()->getComponent(), uno::UNO_QUERY ); + if( xSet.is() ) + { + rValue = xSet->getPropertyValue( rName ); + } + } + return true; + } + else + { + return SvxOle2Shape::getPropertyValueImpl( rName, pProperty, rValue ); + } +} + +SvxPluginShape::SvxPluginShape(SdrObject* pObject) + : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_PLUGIN), getSvxMapProvider().GetPropertySet(SVXMAP_PLUGIN, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ + SetShapeType( "com.sun.star.drawing.PluginShape" ); +} + +SvxPluginShape::~SvxPluginShape() noexcept +{ +} + +void SvxPluginShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) +{ + SvxShape::Create( pNewObj, pNewPage ); + const SvGlobalName aPluginClassId( SO3_PLUGIN_CLASSID ); + createObject(aPluginClassId); + SetShapeType( "com.sun.star.drawing.PluginShape" ); +} + +void SAL_CALL SvxPluginShape::setPropertyValue( const OUString& aPropertyName, const css::uno::Any& rValue ) +{ + SvxShape::setPropertyValue( aPropertyName, rValue ); + resetModifiedState(); +} + +void SAL_CALL SvxPluginShape::setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& rValues ) +{ + SvxShape::setPropertyValues( aPropertyNames, rValues ); + resetModifiedState(); +} + +bool SvxPluginShape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + if( (pProperty->nWID >= OWN_ATTR_PLUGIN_MIMETYPE) && (pProperty->nWID <= OWN_ATTR_PLUGIN_COMMANDS) ) + { + if( svt::EmbeddedObjectRef::TryRunningState( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef() ) ) + { + uno::Reference < beans::XPropertySet > xSet( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef()->getComponent(), uno::UNO_QUERY ); + if( xSet.is() ) + { + // allow exceptions to pass through + xSet->setPropertyValue( rName, rValue ); + } + } + return true; + } + else + { + return SvxOle2Shape::setPropertyValueImpl( rName, pProperty, rValue ); + } +} + +bool SvxPluginShape::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + if( (pProperty->nWID >= OWN_ATTR_PLUGIN_MIMETYPE) && (pProperty->nWID <= OWN_ATTR_PLUGIN_COMMANDS) ) + { + if( svt::EmbeddedObjectRef::TryRunningState( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef() ) ) + { + uno::Reference < beans::XPropertySet > xSet( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef()->getComponent(), uno::UNO_QUERY ); + if( xSet.is() ) + { + rValue = xSet->getPropertyValue( rName ); + } + } + return true; + } + else + { + return SvxOle2Shape::getPropertyValueImpl( rName, pProperty, rValue ); + } +} + + +SvxFrameShape::SvxFrameShape(SdrObject* pObject) +: SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_FRAME), getSvxMapProvider().GetPropertySet(SVXMAP_FRAME, SdrObject::GetGlobalDrawObjectItemPool()) ) +{ + SetShapeType( "com.sun.star.drawing.FrameShape" ); +} + +SvxFrameShape::~SvxFrameShape() noexcept +{ +} + +OUString SvxFrameShape::GetAndClearInitialFrameURL() +{ + OUString sRet(m_sInitialFrameURL); + m_sInitialFrameURL.clear(); + return sRet; +} + +void SvxFrameShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) +{ + uno::Reference<beans::XPropertySet> xSet(static_cast<OWeakObject *>(this), uno::UNO_QUERY); + if (xSet) + xSet->getPropertyValue("FrameURL") >>= m_sInitialFrameURL; + + SvxShape::Create( pNewObj, pNewPage ); + const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID ); + createObject(aIFrameClassId); + SetShapeType( "com.sun.star.drawing.FrameShape" ); +} + +void SAL_CALL SvxFrameShape::setPropertyValue( const OUString& aPropertyName, const css::uno::Any& rValue ) +{ + SvxShape::setPropertyValue( aPropertyName, rValue ); + resetModifiedState(); +} + +void SAL_CALL SvxFrameShape::setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& rValues ) +{ + SvxShape::setPropertyValues( aPropertyNames, rValues ); + resetModifiedState(); +} + +bool SvxFrameShape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + if( (pProperty->nWID >= OWN_ATTR_FRAME_URL) && (pProperty->nWID <= OWN_ATTR_FRAME_MARGIN_HEIGHT) ) + { + if( svt::EmbeddedObjectRef::TryRunningState( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef() ) ) + { + uno::Reference < beans::XPropertySet > xSet( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef()->getComponent(), uno::UNO_QUERY ); + if( xSet.is() ) + { + // allow exceptions to pass through + xSet->setPropertyValue( rName, rValue ); + } + } + return true; + } + else + { + return SvxOle2Shape::setPropertyValueImpl( rName, pProperty, rValue ); + } +} + +bool SvxFrameShape::getPropertyValueImpl(const OUString& rName, const SfxItemPropertyMapEntry* pProperty, + css::uno::Any& rValue) +{ + if( (pProperty->nWID >= OWN_ATTR_FRAME_URL) && (pProperty->nWID <= OWN_ATTR_FRAME_MARGIN_HEIGHT) ) + { + if( svt::EmbeddedObjectRef::TryRunningState( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef() ) ) + { + uno::Reference < beans::XPropertySet > xSet( static_cast<SdrOle2Obj*>(GetSdrObject())->GetObjRef()->getComponent(), uno::UNO_QUERY ); + if( xSet.is() ) + { + rValue = xSet->getPropertyValue( rName ); + } + } + return true; + } + else + { + return SvxOle2Shape::getPropertyValueImpl( rName, pProperty, rValue ); + } +} +SvxMediaShape::SvxMediaShape(SdrObject* pObj, OUString const & referer) +: SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_MEDIA), getSvxMapProvider().GetPropertySet(SVXMAP_MEDIA, SdrObject::GetGlobalDrawObjectItemPool()) ), + referer_(referer) +{ + SetShapeType( "com.sun.star.drawing.MediaShape" ); +} + + +SvxMediaShape::~SvxMediaShape() noexcept +{ +} + + +bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + if( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM)) + || (pProperty->nWID == OWN_ATTR_MEDIA_STREAM) + || (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE) + || (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC) + || (pProperty->nWID == SDRATTR_GRAFCROP)) + { +#if HAVE_FEATURE_AVMEDIA + SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() ); + ::avmedia::MediaItem aItem; + bool bOk = false; +#endif + + switch( pProperty->nWID ) + { + case OWN_ATTR_MEDIA_URL: +#if HAVE_FEATURE_AVMEDIA + { + OUString aURL; + if( rValue >>= aURL ) + { + bOk = true; + aItem.setURL( aURL, "", referer_ ); + } + } +#endif + break; + + case OWN_ATTR_MEDIA_LOOP: +#if HAVE_FEATURE_AVMEDIA + { + bool bLoop; + + if( rValue >>= bLoop ) + { + bOk = true; + aItem.setLoop( bLoop ); + } + } +#endif + break; + + case OWN_ATTR_MEDIA_MUTE: +#if HAVE_FEATURE_AVMEDIA + { + bool bMute; + + if( rValue >>= bMute ) + { + bOk = true; + aItem.setMute( bMute ); + } + } +#endif + break; + + case OWN_ATTR_MEDIA_VOLUMEDB: +#if HAVE_FEATURE_AVMEDIA + { + sal_Int16 nVolumeDB = sal_Int16(); + + if( rValue >>= nVolumeDB ) + { + bOk = true; + aItem.setVolumeDB( nVolumeDB ); + } + } +#endif + break; + + case OWN_ATTR_MEDIA_ZOOM: +#if HAVE_FEATURE_AVMEDIA + { + css::media::ZoomLevel eLevel; + + if( rValue >>= eLevel ) + { + bOk = true; + aItem.setZoom( eLevel ); + } + } +#endif + break; + + case OWN_ATTR_MEDIA_MIMETYPE: +#if HAVE_FEATURE_AVMEDIA + { + OUString sMimeType; + if( rValue >>= sMimeType ) + { + bOk = true; + aItem.setMimeType( sMimeType ); + } + } +#endif + break; + + case OWN_ATTR_VALUE_GRAPHIC: +#if HAVE_FEATURE_AVMEDIA + { + uno::Reference<graphic::XGraphic> xGraphic(rValue, uno::UNO_QUERY); + if (xGraphic.is()) + { + bOk = true; + aItem.setGraphic(Graphic(xGraphic)); + } + } +#endif + break; + + case SDRATTR_GRAFCROP: +#if HAVE_FEATURE_AVMEDIA + { + text::GraphicCrop aCrop; + if (rValue >>= aCrop) + { + bOk = true; + aItem.setCrop(aCrop); + } + } +#endif + break; + + case OWN_ATTR_MEDIA_STREAM: +#if HAVE_FEATURE_AVMEDIA + try + { + uno::Reference<io::XInputStream> xStream; + if (rValue >>= xStream) + { + pMedia->SetInputStream(xStream); + } + } + catch (const css::ucb::ContentCreationException&) + { + css::uno::Any exc = cppu::getCaughtException(); + throw css::lang::WrappedTargetException( + "ContentCreationException Setting InputStream!", + static_cast<OWeakObject *>(this), + exc); + } + catch (const css::ucb::CommandFailedException&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetException( + "CommandFailedException Setting InputStream!", + static_cast<OWeakObject *>(this), + anyEx); + } +#endif + break; + + default: + OSL_FAIL("SvxMediaShape::setPropertyValueImpl(), unknown argument!"); + } + +#if HAVE_FEATURE_AVMEDIA + if( bOk ) + { + pMedia->setMediaProperties( aItem ); + return true; + } +#endif + } + else + { + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); + } + + throw IllegalArgumentException(); +} + + +bool SvxMediaShape::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + if ( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && + (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM)) + || (pProperty->nWID == OWN_ATTR_MEDIA_STREAM) + || (pProperty->nWID == OWN_ATTR_MEDIA_TEMPFILEURL) + || (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE) + || (pProperty->nWID == OWN_ATTR_FALLBACK_GRAPHIC) + || (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC) + || (pProperty->nWID == SDRATTR_GRAFCROP)) + { + SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() ); +#if HAVE_FEATURE_AVMEDIA + const ::avmedia::MediaItem aItem( pMedia->getMediaProperties() ); +#endif + + switch( pProperty->nWID ) + { + case OWN_ATTR_MEDIA_URL: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.getURL(); +#endif + break; + + case OWN_ATTR_MEDIA_LOOP: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.isLoop(); +#endif + break; + + case OWN_ATTR_MEDIA_MUTE: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.isMute(); +#endif + break; + + case OWN_ATTR_MEDIA_VOLUMEDB: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.getVolumeDB(); +#endif + break; + + case OWN_ATTR_MEDIA_ZOOM: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.getZoom(); +#endif + break; + + case OWN_ATTR_MEDIA_STREAM: + try + { + rValue <<= pMedia->GetInputStream(); + } + catch (const css::ucb::ContentCreationException&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetException( + "ContentCreationException Getting InputStream!", + static_cast < OWeakObject * > ( this ), anyEx ); + } + catch (const css::ucb::CommandFailedException&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetException( + "CommandFailedException Getting InputStream!", + static_cast < OWeakObject * > ( this ), anyEx ); + } + + break; + + case OWN_ATTR_MEDIA_TEMPFILEURL: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.getTempURL(); +#endif + break; + + case OWN_ATTR_MEDIA_MIMETYPE: +#if HAVE_FEATURE_AVMEDIA + rValue <<= aItem.getMimeType(); +#endif + break; + + case OWN_ATTR_VALUE_GRAPHIC: +#if HAVE_FEATURE_AVMEDIA + { + Graphic aGraphic = aItem.getGraphic(); + if (!aGraphic.IsNone()) + { + rValue <<= aGraphic.GetXGraphic(); + } + } +#endif + break; + + case SDRATTR_GRAFCROP: +#if HAVE_FEATURE_AVMEDIA + { + text::GraphicCrop aCrop = aItem.getCrop(); + rValue <<= aCrop; + } +#endif + break; + + case OWN_ATTR_FALLBACK_GRAPHIC: + rValue <<= pMedia->getSnapshot(); + break; + + default: + OSL_FAIL("SvxMediaShape::getPropertyValueImpl(), unknown property!"); + } + return true; + } + else + { + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); + } +} + +bool SvxMediaShape::getPropertyStateImpl(const SfxItemPropertyMapEntry* pProperty, + css::beans::PropertyState& rState) +{ +#if HAVE_FEATURE_AVMEDIA + if (pProperty->nWID == SDRATTR_GRAFCROP) + { + auto pMedia = static_cast<SdrMediaObj*>(GetSdrObject()); + const avmedia::MediaItem& rItem = pMedia->getMediaProperties(); + const text::GraphicCrop& rCrop = rItem.getCrop(); + if (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top > 0) + { + // The media has a crop, expose it to UNO-based export filters. + rState = beans::PropertyState_DIRECT_VALUE; + } + else + { + rState = beans::PropertyState_AMBIGUOUS_VALUE; + } + return true; + } +#endif + + return SvxShape::getPropertyStateImpl(pProperty, rState); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx new file mode 100644 index 000000000..a0c81180d --- /dev/null +++ b/svx/source/unodraw/unoshape.cxx @@ -0,0 +1,4042 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/drawing/CircleKind.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <vcl/svapp.hxx> +#include <svl/itemprop.hxx> +#include <o3tl/any.hxx> +#include <osl/mutex.hxx> +#include <editeng/unotext.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdoole2.hxx> +#include <svx/shapepropertynotifier.hxx> +#include <comphelper/interfacecontainer3.hxx> +#include <comphelper/scopeguard.hxx> +#include <comphelper/servicehelper.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/gfxlink.hxx> +#include <vcl/virdev.hxx> +#include <svx/sdangitm.hxx> +#include <svx/svdlayer.hxx> +#include <svx/svdopage.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdobjkind.hxx> +#include <svx/unopage.hxx> +#include <svx/unoshape.hxx> +#include <svx/unoshtxt.hxx> +#include <svx/svdpage.hxx> +#include <svx/unoshprp.hxx> +#include <svx/svdograf.hxx> +#include <svx/unoapi.hxx> +#include <svx/svdomeas.hxx> +#include <svx/svdpool.hxx> +#include <tools/diagnose_ex.h> +#include <tools/stream.hxx> +#include <tools/gen.hxx> +#include <tools/UnitConversion.hxx> +#include <svx/svdoedge.hxx> +#include <svx/svdocapt.hxx> +#include <svx/obj3d.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xtable.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlndsit.hxx> +#include <svx/unomaster.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include "gluepts.hxx" +#include "shapeimpl.hxx" +#include <sal/log.hxx> + +#include <svx/lathe3d.hxx> +#include <extrud3d.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <drawinglayer/converters.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> + +#include <vcl/gdimtf.hxx> +#include <vcl/wmf.hxx> +#include <svx/sdtfsitm.hxx> +#include <svx/svdopath.hxx> +#include <svx/SvxXTextColumns.hxx> +#include <svx/xflclit.hxx> + +#include <memory> +#include <optional> +#include <vector> +#include <iostream> + +#include <bitmaps.hlst> + +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using svx::PropertyValueProvider; + +class GDIMetaFile; + +struct SvxShapeImpl +{ + std::optional<SfxItemSet> mxItemSet; + SdrObjKind mnObjId; + SvxShapeMaster* mpMaster; + bool mbHasSdrObjectOwnership; + bool mbDisposing; + + /** CL, OD 2005-07-19 #i52126# - this is initially 0 and set when + * a SvxShape::Create() call is executed. It is then set to the created + * SdrObject so a multiple call to SvxShape::Create() with same SdrObject + * is prohibited. + */ + ::tools::WeakReference< SdrObject > mpCreatedObj; + + // for xComponent + ::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener> maDisposeListeners; + svx::PropertyChangeNotifier maPropertyNotifier; + + SvxShapeImpl( SvxShape& _rAntiImpl, ::osl::Mutex& _rMutex ) + :mnObjId( SdrObjKind::NONE ) + ,mpMaster( nullptr ) + ,mbHasSdrObjectOwnership( false ) + ,mbDisposing( false ) + ,maDisposeListeners( _rMutex ) + ,maPropertyNotifier( _rAntiImpl, _rMutex ) + { + } +}; + +namespace { + +class ShapePositionProvider : public PropertyValueProvider +{ +public: + explicit ShapePositionProvider( SvxShape& _shape ) + :PropertyValueProvider( _shape, "Position" ) + { + } + +protected: + virtual void getCurrentValue( Any& _out_rCurrentValue ) const override + { + _out_rCurrentValue <<= static_cast< SvxShape& >( getContext() ).getPosition(); + } +}; + + +class ShapeSizeProvider : public PropertyValueProvider +{ +public: + static constexpr OUStringLiteral sSize = u"Size"; + explicit ShapeSizeProvider( SvxShape& _shape ) + :PropertyValueProvider( _shape, sSize ) + { + } + +protected: + virtual void getCurrentValue( Any& _out_rCurrentValue ) const override + { + _out_rCurrentValue <<= static_cast< SvxShape& >( getContext() ).getSize(); + } +}; + +/// Calculates what scaling factor will be used for autofit text scaling of this shape. +sal_Int16 GetTextFitToSizeScale(SdrObject* pObject) +{ + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(pObject); + if (!pTextObj) + { + return 0; + } + + const SfxItemSet& rTextObjSet = pTextObj->GetMergedItemSet(); + if (rTextObjSet.GetItem<SdrTextFitToSizeTypeItem>(SDRATTR_TEXT_FITTOSIZE)->GetValue() + != drawing::TextFitToSizeType_AUTOFIT) + { + return 0; + } + + return pTextObj->GetFontScaleY(); +} +} + +SvxShape::SvxShape( SdrObject* pObject ) +: maSize(100,100) +, mpImpl( new SvxShapeImpl( *this, m_aMutex ) ) +, mbIsMultiPropertyCall(false) +, mpPropSet(getSvxMapProvider().GetPropertySet(SVXMAP_SHAPE, SdrObject::GetGlobalDrawObjectItemPool())) +, maPropMapEntries(getSvxMapProvider().GetMap(SVXMAP_SHAPE)) +, mpSdrObjectWeakReference(pObject) +, mnLockCount(0) +{ + impl_construct(); +} + + +SvxShape::SvxShape( SdrObject* pObject, const SfxItemPropertyMapEntry* pEntries, const SvxItemPropertySet* pPropertySet ) +: maSize(100,100) +, mpImpl( new SvxShapeImpl( *this, m_aMutex ) ) +, mbIsMultiPropertyCall(false) +, mpPropSet(pPropertySet) +, maPropMapEntries(pEntries) +, mpSdrObjectWeakReference(pObject) +, mnLockCount(0) +{ + impl_construct(); +} + + +SvxShape::~SvxShape() noexcept +{ + ::SolarMutexGuard aGuard; + + DBG_ASSERT( mnLockCount == 0, "Locked shape was disposed!" ); + + if ( mpImpl->mpMaster ) + mpImpl->mpMaster->dispose(); + + if ( HasSdrObject() ) + { + EndListening(GetSdrObject()->getSdrModelFromSdrObject()); + GetSdrObject()->setUnoShape(nullptr); + } + + if( HasSdrObjectOwnership() && HasSdrObject() ) + { + mpImpl->mbHasSdrObjectOwnership = false; + SdrObject* pObject = GetSdrObject(); + SdrObject::Free( pObject ); + } + + EndListeningAll(); // call explicitly within SolarMutexGuard +} + + +void SvxShape::TakeSdrObjectOwnership() +{ + mpImpl->mbHasSdrObjectOwnership = true; +} + + +void SvxShape::InvalidateSdrObject() +{ + if(HasSdrObject()) + { + EndListening(GetSdrObject()->getSdrModelFromSdrObject()); + } + + if (HasSdrObjectOwnership()) + return; + + mpSdrObjectWeakReference.reset(nullptr); +}; + +bool SvxShape::HasSdrObjectOwnership() const +{ + if ( !mpImpl->mbHasSdrObjectOwnership ) + return false; + + OSL_ENSURE( HasSdrObject(), "SvxShape::HasSdrObjectOwnership: have the ownership of an object which I don't know!" ); + return HasSdrObject(); +} + + +void SvxShape::setShapeKind( SdrObjKind nKind ) +{ + mpImpl->mnObjId = nKind; +} + + +SdrObjKind SvxShape::getShapeKind() const +{ + return mpImpl->mnObjId; +} + + +void SvxShape::setMaster( SvxShapeMaster* pMaster ) +{ + mpImpl->mpMaster = pMaster; +} + + +uno::Any SAL_CALL SvxShape::queryAggregation( const uno::Type& rType ) +{ + if( mpImpl->mpMaster ) + { + uno::Any aAny; + if( mpImpl->mpMaster->queryAggregation( rType, aAny ) ) + return aAny; + } + + return SvxShape_UnoImplHelper::queryAggregation(rType); +} + +const css::uno::Sequence< sal_Int8 > & SvxShape::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theSvxShapeUnoTunnelId; + return theSvxShapeUnoTunnelId.getSeq(); +} + +sal_Int64 SAL_CALL SvxShape::getSomething( const css::uno::Sequence< sal_Int8 >& rId ) +{ + return comphelper::getSomethingImpl(rId, this); +} + + +svx::PropertyChangeNotifier& SvxShape::getShapePropertyChangeNotifier() +{ + return mpImpl->maPropertyNotifier; +} + + +void SvxShape::impl_construct() +{ + mpImpl->maPropertyNotifier.registerProvider( svx::ShapePropertyProviderId::Position, + std::make_unique<ShapePositionProvider>( *this ) ); + mpImpl->maPropertyNotifier.registerProvider( svx::ShapePropertyProviderId::Size, + std::make_unique<ShapeSizeProvider>( *this ) ); + + if ( HasSdrObject() ) + { + StartListening(GetSdrObject()->getSdrModelFromSdrObject()); + impl_initFromSdrObject(); + } +} + + +void SvxShape::impl_initFromSdrObject() +{ + DBG_TESTSOLARMUTEX(); + OSL_PRECOND( HasSdrObject(), "SvxShape::impl_initFromSdrObject: not to be called without SdrObject!" ); + if ( !HasSdrObject() ) + return; + + osl_atomic_increment( &m_refCount ); + { + GetSdrObject()->setUnoShape(this); + } + osl_atomic_decrement( &m_refCount ); + + // #i40944# + // Do not simply return when no model but do the type corrections + // following below. + const SdrInventor nInventor = GetSdrObject()->GetObjInventor(); + + // is it one of ours (svx) ? + if( !(nInventor == SdrInventor::Default || nInventor == SdrInventor::E3d || nInventor == SdrInventor::FmForm) ) + return; + + if(nInventor == SdrInventor::FmForm) + { + mpImpl->mnObjId = SdrObjKind::UNO; + } + else + { + mpImpl->mnObjId = GetSdrObject()->GetObjIdentifier(); + } + + switch(mpImpl->mnObjId) + { + case SdrObjKind::CircleCut: // segment of circle + case SdrObjKind::CircleArc: // arc of circle + case SdrObjKind::CircleSection: // sector + mpImpl->mnObjId = SdrObjKind::CircleOrEllipse; + break; + default: ; + } +} + + +void SvxShape::Create( SdrObject* pNewObj, SvxDrawPage* /*pNewPage*/ ) +{ + DBG_TESTSOLARMUTEX(); + + assert( pNewObj && "SvxShape::Create: invalid new object!" ); + if ( !pNewObj ) + return; + + SdrObject* pCreatedObj = mpImpl->mpCreatedObj.get(); + assert( ( !pCreatedObj || ( pCreatedObj == pNewObj ) ) && + "SvxShape::Create: the same shape used for two different objects?! Strange ..." ); + + // Correct condition (#i52126#) + if ( pCreatedObj == pNewObj ) + return; + + // Correct condition (#i52126#) + mpImpl->mpCreatedObj = pNewObj; + + if( HasSdrObject() ) + { + EndListening( GetSdrObject()->getSdrModelFromSdrObject() ); + } + + mpSdrObjectWeakReference.reset( pNewObj ); + + if( HasSdrObject() ) + { + StartListening( GetSdrObject()->getSdrModelFromSdrObject() ); + } + + OSL_ENSURE( !mbIsMultiPropertyCall, "SvxShape::Create: hmm?" ); + // this was previously set in impl_initFromSdrObject, but I think it was superfluous + // (it definitely was in the other context where it was called, but I strongly suppose + // it was also superfluous when called from here) + impl_initFromSdrObject(); + + ObtainSettingsFromPropertySet( *mpPropSet ); + + // save user call + SdrObjUserCall* pUser = GetSdrObject()->GetUserCall(); + GetSdrObject()->SetUserCall(nullptr); + + setPosition( maPosition ); + setSize( maSize ); + + // restore user call after we set the initial size + GetSdrObject()->SetUserCall( pUser ); + + // if this shape was already named, use this name + if( !maShapeName.isEmpty() ) + { + GetSdrObject()->SetName( maShapeName ); + maShapeName.clear(); + } +} + +void SvxShape::ForceMetricToItemPoolMetric(Pair& rPoint) const noexcept +{ + DBG_TESTSOLARMUTEX(); + if(!HasSdrObject()) + return; + + MapUnit eMapUnit(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0)); + if(eMapUnit == MapUnit::Map100thMM) + return; + + if (const auto eTo = MapToO3tlLength(eMapUnit); eTo != o3tl::Length::invalid) + { + rPoint.A() = o3tl::convert(rPoint.A(), o3tl::Length::mm100, eTo); + rPoint.B() = o3tl::convert(rPoint.B(), o3tl::Length::mm100, eTo); + } + else + { + OSL_FAIL("AW: Missing unit translation to PoolMetric!"); + } +} + +void SvxShape::ForceMetricToItemPoolMetric(basegfx::B2DPolyPolygon& rPolyPolygon) const noexcept +{ + DBG_TESTSOLARMUTEX(); + if(!HasSdrObject()) + return; + + GetSdrObject()->ForceMetricToItemPoolMetric(rPolyPolygon); +} + +void SvxShape::ForceMetricToItemPoolMetric(basegfx::B2DHomMatrix& rB2DHomMatrix) const noexcept +{ + DBG_TESTSOLARMUTEX(); + if(!HasSdrObject()) + return; + + MapUnit eMapUnit(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0)); + if(eMapUnit == MapUnit::Map100thMM) + return; + + if (const auto eTo = MapToO3tlLength(eMapUnit); eTo != o3tl::Length::invalid) + { + const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100, eTo)); + const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(rB2DHomMatrix); + rB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( + aDecomposedTransform.getScale() * fConvert, + aDecomposedTransform.getShearX(), + aDecomposedTransform.getRotate(), + aDecomposedTransform.getTranslate() * fConvert); + } + else + { + OSL_FAIL("Missing unit translation to PoolMetric!"); + } +} + +void SvxShape::ForceMetricTo100th_mm(Pair& rPoint) const noexcept +{ + DBG_TESTSOLARMUTEX(); + if(!HasSdrObject()) + return; + + MapUnit eMapUnit = GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0); + if(eMapUnit == MapUnit::Map100thMM) + return; + + if (const auto eFrom = MapToO3tlLength(eMapUnit); eFrom != o3tl::Length::invalid) + { + rPoint.A() = o3tl::convert(rPoint.A(), eFrom, o3tl::Length::mm100); + rPoint.B() = o3tl::convert(rPoint.B(), eFrom, o3tl::Length::mm100); + } + else + { + OSL_FAIL("AW: Missing unit translation to 100th mm!"); + } +} + +void SvxShape::ForceMetricTo100th_mm(basegfx::B2DPolyPolygon& rPolyPolygon) const noexcept +{ + DBG_TESTSOLARMUTEX(); + if(!HasSdrObject()) + return; + + MapUnit eMapUnit = GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0); + if(eMapUnit == MapUnit::Map100thMM) + return; + + if (const auto eFrom = MapToO3tlLength(eMapUnit); eFrom != o3tl::Length::invalid) + { + const double fConvert(o3tl::convert(1.0, eFrom, o3tl::Length::mm100)); + rPolyPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert, fConvert)); + } + else + { + OSL_FAIL("Missing unit translation to 100th mm!"); + } +} + +void SvxShape::ForceMetricTo100th_mm(basegfx::B2DHomMatrix& rB2DHomMatrix) const noexcept +{ + DBG_TESTSOLARMUTEX(); + if(!HasSdrObject()) + return; + + MapUnit eMapUnit = GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0); + if(eMapUnit == MapUnit::Map100thMM) + return; + + if (const auto eFrom = MapToO3tlLength(eMapUnit); eFrom != o3tl::Length::invalid) + { + const double fConvert(o3tl::convert(1.0, eFrom, o3tl::Length::mm100)); + const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(rB2DHomMatrix); + rB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( + aDecomposedTransform.getScale() * fConvert, + aDecomposedTransform.getShearX(), + aDecomposedTransform.getRotate(), + aDecomposedTransform.getTranslate() * fConvert); + } + else + { + OSL_FAIL("Missing unit translation to 100th mm!"); + } +} + +static void SvxItemPropertySet_ObtainSettingsFromPropertySet(const SvxItemPropertySet& rPropSet, SvxItemPropertySetUsrAnys& rAnys, + SfxItemSet& rSet, const uno::Reference< beans::XPropertySet >& xSet, const SfxItemPropertyMap* pMap ) +{ + if(!rAnys.AreThereOwnUsrAnys()) + return; + + const SfxItemPropertyMap& rSrc = rPropSet.getPropertyMap(); + + for(const SfxItemPropertyMapEntry* pSrcProp : rSrc.getPropertyEntries()) + { + const sal_uInt16 nWID = pSrcProp->nWID; + if(SfxItemPool::IsWhich(nWID) + && (nWID < OWN_ATTR_VALUE_START || nWID > OWN_ATTR_VALUE_END) + && rAnys.GetUsrAnyForID(*pSrcProp)) + rSet.Put(rSet.GetPool()->GetDefaultItem(nWID)); + } + + for(const SfxItemPropertyMapEntry* pSrcProp : rSrc.getPropertyEntries()) + { + if(pSrcProp->nWID) + { + uno::Any* pUsrAny = rAnys.GetUsrAnyForID(*pSrcProp); + if(pUsrAny) + { + // search for equivalent entry in pDst + const SfxItemPropertyMapEntry* pEntry = pMap->getByName( pSrcProp->aName ); + if(pEntry) + { + // entry found + if(pEntry->nWID >= OWN_ATTR_VALUE_START && pEntry->nWID <= OWN_ATTR_VALUE_END) + { + // special ID in PropertySet, can only be set + // directly at the object + xSet->setPropertyValue( pSrcProp->aName, *pUsrAny); + } + else + { + SvxItemPropertySet_setPropertyValue(pEntry, *pUsrAny, rSet); + } + } + } + } + } + rAnys.ClearAllUsrAny(); +} + + +void SvxShape::ObtainSettingsFromPropertySet(const SvxItemPropertySet& rPropSet) +{ + DBG_TESTSOLARMUTEX(); + if(HasSdrObject() && maUrsAnys.AreThereOwnUsrAnys()) + { + SfxItemSetFixed<SDRATTR_START, SDRATTR_END> aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool() ); + Reference< beans::XPropertySet > xShape(this); + SvxItemPropertySet_ObtainSettingsFromPropertySet(rPropSet, maUrsAnys, aSet, xShape, &mpPropSet->getPropertyMap() ); + + GetSdrObject()->SetMergedItemSetAndBroadcast(aSet); + + GetSdrObject()->ApplyNotPersistAttr( aSet ); + } +} + +uno::Any SvxShape::GetBitmap( bool bMetaFile /* = false */ ) const +{ + DBG_TESTSOLARMUTEX(); + uno::Any aAny; + + if(!HasSdrObject() || nullptr == GetSdrObject()->getSdrPageFromSdrObject()) + { + return aAny; + } + + // tdf#118662 Emulate old behaviour of XclObjComment (see there) + const SdrCaptionObj* pSdrCaptionObj(dynamic_cast<SdrCaptionObj*>(GetSdrObject())); + if(nullptr != pSdrCaptionObj && pSdrCaptionObj->isSuppressGetBitmap()) + { + return aAny; + } + + // tdf#119180 If we do not ask for Metafile and we access a SdrGrafObj, + // and content exists and is a Bitmap, take the shortcut. + // Do *not* do this for Metafile - as can be seen, requested in that case + // is a byte-sequence of a saved WMF format file (see below) + if(!bMetaFile) + { + const SdrGrafObj* pSdrGrafObj(dynamic_cast<SdrGrafObj*>(GetSdrObject())); + + if(nullptr != pSdrGrafObj) + { + const Graphic& rGraphic(pSdrGrafObj->GetGraphic()); + + if(GraphicType::Bitmap == rGraphic.GetType()) + { + Reference< awt::XBitmap > xBmp( rGraphic.GetXGraphic(), UNO_QUERY ); + aAny <<= xBmp; + + return aAny; + } + } + } + + // tdf#118662 instead of creating an E3dView instance every time to paint + // a single SdrObject, use the existing SdrObject::SingleObjectPainter to + // use less resources and runtime + if(bMetaFile) + { + ScopedVclPtrInstance< VirtualDevice > pVDev; + const tools::Rectangle aBoundRect(GetSdrObject()->GetCurrentBoundRect()); + GDIMetaFile aMtf; + + pVDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + pVDev->EnableOutput(false); + aMtf.Record(pVDev); + GetSdrObject()->SingleObjectPainter(*pVDev); + aMtf.Stop(); + aMtf.WindStart(); + aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top()); + aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM)); + aMtf.SetPrefSize(aBoundRect.GetSize()); + + SvMemoryStream aDestStrm(65535, 65535); + + ConvertGDIMetaFileToWMF( + aMtf, + aDestStrm, + nullptr, + false); + + const uno::Sequence<sal_Int8> aSeq( + static_cast< const sal_Int8* >(aDestStrm.GetData()), + aDestStrm.GetEndOfData()); + + aAny <<= aSeq; + } + else + { + drawinglayer::primitive2d::Primitive2DContainer xPrimitives; + GetSdrObject()->GetViewContact().getViewIndependentPrimitive2DContainer(xPrimitives); + + if(!xPrimitives.empty()) + { + const drawinglayer::geometry::ViewInformation2D aViewInformation2D; + basegfx::B2DRange aRange( + xPrimitives.getB2DRange(aViewInformation2D)); + + if(!aRange.isEmpty()) + { + const MapUnit aSourceMapUnit(GetSdrObject()->getSdrModelFromSdrObject().GetScaleUnit()); + + if(MapUnit::Map100thMM != aSourceMapUnit) + { + // tdf#119180 This is UNO API and thus works in 100th_mm, + // so if the MapMode from the used SdrModel is *not* equal + // to Map100thMM we need to embed the primitives to an adapting + // homogen transformation for correct values + const basegfx::B2DHomMatrix aMapTransform( + OutputDevice::LogicToLogic( + MapMode(aSourceMapUnit), + MapMode(MapUnit::Map100thMM))); + + // Embed primitives to get them in 100th mm + drawinglayer::primitive2d::Primitive2DReference xEmbedRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aMapTransform, + std::move(xPrimitives))); + + xPrimitives = drawinglayer::primitive2d::Primitive2DContainer { xEmbedRef }; + + // Update basegfx::B2DRange aRange, too. Here we have the + // choice of transforming the existing value or get newly by + // again using 'xPrimitives.getB2DRange(aViewInformation2D)' + aRange.transform(aMapTransform); + } + + const BitmapEx aBmp( + drawinglayer::convertPrimitive2DContainerToBitmapEx( + std::move(xPrimitives), + aRange)); + + Graphic aGraph(aBmp); + + aGraph.SetPrefSize(aBmp.GetPrefSize()); + aGraph.SetPrefMapMode(aBmp.GetPrefMapMode()); + + Reference< awt::XBitmap > xBmp( aGraph.GetXGraphic(), UNO_QUERY ); + aAny <<= xBmp; + } + } + } + + return aAny; +} + +uno::Sequence< uno::Type > SAL_CALL SvxShape::getTypes() +{ + if( mpImpl->mpMaster ) + { + return mpImpl->mpMaster->getTypes(); + } + else + { + return _getTypes(); + } +} + + +uno::Sequence< uno::Type > const & SvxShape::_getTypes() +{ + switch( mpImpl->mnObjId ) + { + // shapes without text + case SdrObjKind::Page: + case SdrObjKind::OLEPluginFrame: + case SdrObjKind::OLE2Plugin: + case SdrObjKind::OLE2Applet: + case SdrObjKind::E3D_Cube: + case SdrObjKind::E3D_Sphere: + case SdrObjKind::E3D_Lathe: + case SdrObjKind::E3D_Extrusion: + case SdrObjKind::E3D_Polygon: + case SdrObjKind::Media: + case SdrObjKind::Table: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + }; + + return aTypeSequence; + } + // group shape + case SdrObjKind::Group: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + cppu::UnoType<drawing::XShapes>::get(), + cppu::UnoType<drawing::XShapeGroup>::get(), + }; + + return aTypeSequence; + } + // connector shape + case SdrObjKind::Edge: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + cppu::UnoType<drawing::XConnectorShape>::get(), + // from SvxUnoTextBase::getTypes() + cppu::UnoType<text::XTextAppend>::get(), + cppu::UnoType<text::XTextCopy>::get(), + cppu::UnoType<container::XEnumerationAccess>::get(), + cppu::UnoType<text::XTextRangeMover>::get(), + }; + + return aTypeSequence; + } + // control shape + case SdrObjKind::UNO: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + cppu::UnoType<drawing::XControlShape>::get(), + }; + + return aTypeSequence; + } + // 3d scene shape + case SdrObjKind::E3D_Scene: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + cppu::UnoType<drawing::XShapes>::get(), + }; + + return aTypeSequence; + } + case SdrObjKind::CustomShape: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + // from SvxUnoTextBase::getTypes() + cppu::UnoType<text::XText>::get(), + cppu::UnoType<container::XEnumerationAccess>::get(), + cppu::UnoType<text::XTextRangeMover>::get(), + cppu::UnoType<drawing::XEnhancedCustomShapeDefaulter>::get(), + }; + + return aTypeSequence; + } + // shapes with text + case SdrObjKind::Rectangle: + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::Measure: + case SdrObjKind::Line: + case SdrObjKind::Polygon: + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::PathFill: + case SdrObjKind::FreehandLine: + case SdrObjKind::FreehandFill: + case SdrObjKind::PathPoly: + case SdrObjKind::PathPolyLine: + case SdrObjKind::Graphic: + case SdrObjKind::Text: + case SdrObjKind::Caption: + case SdrObjKind::OLE2: // #i118485# Moved to shapes with text + default: + { + static uno::Sequence<uno::Type> aTypeSequence{ + cppu::UnoType<drawing::XShape>::get(), + cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<beans::XMultiPropertySet>::get(), + cppu::UnoType<beans::XPropertyState>::get(), + cppu::UnoType<beans::XMultiPropertyStates>::get(), + cppu::UnoType<drawing::XGluePointsSupplier>::get(), + cppu::UnoType<container::XChild>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<lang::XUnoTunnel>::get(), + cppu::UnoType<container::XNamed>::get(), + // from SvxUnoTextBase::getTypes() + cppu::UnoType<text::XTextAppend>::get(), + cppu::UnoType<text::XTextCopy>::get(), + cppu::UnoType<container::XEnumerationAccess>::get(), + cppu::UnoType<text::XTextRangeMover>::get(), + }; + + return aTypeSequence; + } + } +} + + +uno::Sequence< sal_Int8 > SAL_CALL SvxShape::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +void SvxShape::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept +{ + DBG_TESTSOLARMUTEX(); + + // do cheap checks first, this method is hot + if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) + return; + SdrObject* pSdrObject(mpSdrObjectWeakReference.get()); + if( !pSdrObject ) + return; + const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); + // #i55919# SdrHintKind::ObjectChange is only interesting if it's for this object + if ((pSdrHint->GetKind() != SdrHintKind::ModelCleared) && + (pSdrHint->GetKind() != SdrHintKind::ObjectChange || pSdrHint->GetObject() != pSdrObject )) + return; + + uno::Reference< uno::XInterface > xSelf( pSdrObject->getWeakUnoShape() ); + if( !xSelf.is() ) + { + EndListening(pSdrObject->getSdrModelFromSdrObject()); + mpSdrObjectWeakReference.reset(nullptr); + return; + } + + bool bClearMe = false; + + switch( pSdrHint->GetKind() ) + { + case SdrHintKind::ObjectChange: + { + updateShapeKind(); + break; + } + case SdrHintKind::ModelCleared: + { + bClearMe = true; + break; + } + default: + break; + }; + + if( !bClearMe ) + return; + + if(!HasSdrObjectOwnership()) + { + if(nullptr != pSdrObject) + { + EndListening(pSdrObject->getSdrModelFromSdrObject()); + pSdrObject->setUnoShape(nullptr); + } + + mpSdrObjectWeakReference.reset(nullptr); + + // SdrModel *is* going down, try to Free SdrObject even + // when !HasSdrObjectOwnership + if(nullptr != pSdrObject && !pSdrObject->IsInserted()) + { + SdrObject::Free(pSdrObject); + } + } + + if(!mpImpl->mbDisposing) + { + dispose(); + } +} + +// XShape + + +// The "*LogicRectHack" functions also existed in sch, and those +// duplicate symbols cause Bad Things To Happen (TM) #i9462#. +// Prefixing with 'svx' and marking static to make sure name collisions +// do not occur. + +static bool svx_needLogicRectHack( SdrObject const * pObj ) +{ + if( pObj->GetObjInventor() == SdrInventor::Default) + { + switch(pObj->GetObjIdentifier()) + { + case SdrObjKind::Group: + case SdrObjKind::Line: + case SdrObjKind::Polygon: + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::PathFill: + case SdrObjKind::FreehandLine: + case SdrObjKind::FreehandFill: + case SdrObjKind::SplineLine: + case SdrObjKind::SplineFill: + case SdrObjKind::Edge: + case SdrObjKind::PathPoly: + case SdrObjKind::PathPolyLine: + case SdrObjKind::Measure: + return true; + default: + break; + } + } + return false; +} + + +static tools::Rectangle svx_getLogicRectHack( SdrObject const * pObj ) +{ + if(svx_needLogicRectHack(pObj)) + { + return pObj->GetSnapRect(); + } + else + { + return pObj->GetLogicRect(); + } +} + + +static void svx_setLogicRectHack( SdrObject* pObj, const tools::Rectangle& rRect ) +{ + if(svx_needLogicRectHack(pObj)) + { + pObj->SetSnapRect( rRect ); + } + else + { + pObj->SetLogicRect( rRect ); + } +} + + +awt::Point SAL_CALL SvxShape::getPosition() +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + { + tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) ); + Point aPt( aRect.Left(), aRect.Top() ); + + // Position is relative to anchor, so recalc to absolute position + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aPt -= GetSdrObject()->GetAnchorPos(); + + ForceMetricTo100th_mm(aPt); + return css::awt::Point( aPt.X(), aPt.Y() ); + } + else + { + return maPosition; + } +} + + +void SAL_CALL SvxShape::setPosition( const awt::Point& Position ) +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + { + // do NOT move 3D objects, this would change the homogen + // transformation matrix + if(dynamic_cast<const E3dCompoundObject* >(GetSdrObject()) == nullptr) + { + tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) ); + Point aLocalPos( Position.X, Position.Y ); + ForceMetricToItemPoolMetric(aLocalPos); + + // Position is absolute, so recalc to position relative to anchor + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aLocalPos += GetSdrObject()->GetAnchorPos(); + + tools::Long nDX = aLocalPos.X() - aRect.Left(); + tools::Long nDY = aLocalPos.Y() - aRect.Top(); + + GetSdrObject()->Move( Size( nDX, nDY ) ); + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); + } + } + + maPosition = Position; +} + + +awt::Size SAL_CALL SvxShape::getSize() +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + { + tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) ); + Size aObjSize( aRect.getWidth(), aRect.getHeight() ); + ForceMetricTo100th_mm(aObjSize); + return css::awt::Size( aObjSize.getWidth(), aObjSize.getHeight() ); + } + else + return maSize; +} + + +void SAL_CALL SvxShape::setSize( const awt::Size& rSize ) +{ + ::SolarMutexGuard aGuard; + + if(HasSdrObject()) + { + tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) ); + Size aLocalSize( rSize.Width, rSize.Height ); + ForceMetricToItemPoolMetric(aLocalSize); + + if(GetSdrObject()->GetObjInventor() == SdrInventor::Default && GetSdrObject()->GetObjIdentifier() == SdrObjKind::Measure ) + { + Fraction aWdt(aLocalSize.Width(),aRect.Right()-aRect.Left()); + Fraction aHgt(aLocalSize.Height(),aRect.Bottom()-aRect.Top()); + Point aPt = GetSdrObject()->GetSnapRect().TopLeft(); + GetSdrObject()->Resize(aPt,aWdt,aHgt); + } + else + { + //aRect.SetSize(aLocalSize); // this call subtract 1 // https://bz.apache.org/ooo/show_bug.cgi?id=83193 + if ( !aLocalSize.Width() ) + { + aRect.SetWidthEmpty(); + } + else + aRect.setWidth(aLocalSize.Width()); + if ( !aLocalSize.Height() ) + { + aRect.SetHeightEmpty(); + } + else + aRect.setHeight(aLocalSize.Height()); + + svx_setLogicRectHack( GetSdrObject(), aRect ); + } + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); + } + maSize = rSize; +} + + +// XNamed +OUString SAL_CALL SvxShape::getName( ) +{ + ::SolarMutexGuard aGuard; + if( HasSdrObject() ) + { + return GetSdrObject()->GetName(); + } + else + { + return maShapeName; + } +} + + +void SAL_CALL SvxShape::setName( const OUString& aName ) +{ + ::SolarMutexGuard aGuard; + if( HasSdrObject() ) + { + GetSdrObject()->SetName( aName ); + } + else + { + maShapeName = aName; + } +} + +// XShapeDescriptor + + +OUString SAL_CALL SvxShape::getShapeType() +{ + if( !maShapeType.getLength() ) + return UHashMap::getNameFromId( mpImpl->mnObjId ); + else + return maShapeType; +} + +// XComponent + + +void SAL_CALL SvxShape::dispose() +{ + ::SolarMutexGuard aGuard; + + if( mpImpl->mbDisposing ) + return; // caught a recursion + + mpImpl->mbDisposing = true; + + lang::EventObject aEvt; + aEvt.Source = *static_cast<OWeakAggObject*>(this); + mpImpl->maDisposeListeners.disposeAndClear(aEvt); + mpImpl->maPropertyNotifier.disposing(); + + if ( !HasSdrObject() ) + return; + + SdrObject* pObject = GetSdrObject(); + + EndListening( pObject->getSdrModelFromSdrObject() ); + bool bFreeSdrObject = false; + + if ( pObject->IsInserted() && pObject->getSdrPageFromSdrObject() ) + { + SdrPage* pPage = pObject->getSdrPageFromSdrObject(); + // delete the SdrObject from the page + const size_t nCount = pPage->GetObjCount(); + for ( size_t nNum = 0; nNum < nCount; ++nNum ) + { + if ( pPage->GetObj( nNum ) == pObject ) + { + OSL_VERIFY( pPage->RemoveObject( nNum ) == pObject ); + if (HasSdrObjectOwnership()) + { + bFreeSdrObject = true; + } + break; + } + } + } + + pObject->setUnoShape(nullptr); + + if ( bFreeSdrObject ) + { + // in case we have the ownership of the SdrObject, a Free + // would do nothing. So ensure the ownership is reset. + mpImpl->mbHasSdrObjectOwnership = false; + SdrObject::Free( pObject ); + } +} + + +void SAL_CALL SvxShape::addEventListener( const Reference< lang::XEventListener >& xListener ) +{ + mpImpl->maDisposeListeners.addInterface(xListener); +} + + +void SAL_CALL SvxShape::removeEventListener( const Reference< lang::XEventListener >& aListener ) +{ + mpImpl->maDisposeListeners.removeInterface(aListener); +} + +// XPropertySet + + +Reference< beans::XPropertySetInfo > SAL_CALL + SvxShape::getPropertySetInfo() +{ + if( mpImpl->mpMaster ) + { + return mpImpl->mpMaster->getPropertySetInfo(); + } + else + { + return _getPropertySetInfo(); + } +} + +Reference< beans::XPropertySetInfo > const & + SvxShape::_getPropertySetInfo() +{ + return mpPropSet->getPropertySetInfo(); +} + + +void SAL_CALL SvxShape::addPropertyChangeListener( const OUString& _propertyName, const Reference< beans::XPropertyChangeListener >& _listener ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + mpImpl->maPropertyNotifier.addPropertyChangeListener( _propertyName, _listener ); +} + + +void SAL_CALL SvxShape::removePropertyChangeListener( const OUString& _propertyName, const Reference< beans::XPropertyChangeListener >& _listener ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + mpImpl->maPropertyNotifier.removePropertyChangeListener( _propertyName, _listener ); +} + + +void SAL_CALL SvxShape::addVetoableChangeListener( const OUString& , const Reference< beans::XVetoableChangeListener >& ) +{ + OSL_FAIL( "SvxShape::addVetoableChangeListener: don't have any vetoable properties, so why ...?" ); +} + + +void SAL_CALL SvxShape::removeVetoableChangeListener( const OUString& , const Reference< beans::XVetoableChangeListener >& ) +{ + OSL_FAIL( "SvxShape::removeVetoableChangeListener: don't have any vetoable properties, so why ...?" ); +} + + +bool SvxShape::SetFillAttribute( sal_uInt16 nWID, const OUString& rName ) +{ + if(HasSdrObject()) + { + SfxItemSet aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), nWID, nWID ); + + if( SetFillAttribute( nWID, rName, aSet, &GetSdrObject()->getSdrModelFromSdrObject() ) ) + { + //GetSdrObject()->SetItemSetAndBroadcast(aSet); + GetSdrObject()->SetMergedItemSetAndBroadcast(aSet); + + return true; + } + } + + return false; +} + + +bool SvxShape::SetFillAttribute( sal_uInt16 nWID, const OUString& rName, SfxItemSet& rSet, SdrModel const * pModel ) +{ + // check if an item with the given name and which id is inside the models + // pool or the stylesheet pool, if found it's put in the itemset + if( !SetFillAttribute( nWID, rName, rSet ) ) + { + // we did not find such item in one of the pools, so we check + // the property lists that are loaded for the model for items + // that support such. + OUString aStrName = SvxUnogetInternalNameForItem(nWID, rName); + + switch( nWID ) + { + case XATTR_FILLBITMAP: + { + XBitmapListRef pBitmapList = pModel->GetBitmapList(); + + if( !pBitmapList.is() ) + return false; + + tools::Long nPos = pBitmapList->GetIndex(aStrName); + if( nPos == -1 ) + return false; + + const XBitmapEntry* pEntry = pBitmapList->GetBitmap(nPos); + XFillBitmapItem aBmpItem(rName, pEntry->GetGraphicObject()); + rSet.Put(aBmpItem); + break; + } + case XATTR_FILLGRADIENT: + { + XGradientListRef pGradientList = pModel->GetGradientList(); + + if( !pGradientList.is() ) + return false; + + tools::Long nPos = pGradientList->GetIndex(aStrName); + if( nPos == -1 ) + return false; + + const XGradientEntry* pEntry = pGradientList->GetGradient(nPos); + XFillGradientItem aGrdItem(rName, pEntry->GetGradient()); + rSet.Put( aGrdItem ); + break; + } + case XATTR_FILLHATCH: + { + XHatchListRef pHatchList = pModel->GetHatchList(); + + if( !pHatchList.is() ) + return false; + + tools::Long nPos = pHatchList->GetIndex(aStrName); + if( nPos == -1 ) + return false; + + const XHatchEntry* pEntry = pHatchList->GetHatch( nPos ); + XFillHatchItem aHatchItem(rName, pEntry->GetHatch()); + rSet.Put( aHatchItem ); + break; + } + case XATTR_LINEEND: + case XATTR_LINESTART: + { + XLineEndListRef pLineEndList = pModel->GetLineEndList(); + + if( !pLineEndList.is() ) + return false; + + tools::Long nPos = pLineEndList->GetIndex(aStrName); + if( nPos == -1 ) + return false; + + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + if( sal_uInt16(XATTR_LINEEND) == nWID ) + { + XLineEndItem aLEItem(rName, pEntry->GetLineEnd()); + rSet.Put( aLEItem ); + } + else + { + XLineStartItem aLSItem(rName, pEntry->GetLineEnd()); + rSet.Put( aLSItem ); + } + + break; + } + case XATTR_LINEDASH: + { + XDashListRef pDashList = pModel->GetDashList(); + + if( !pDashList.is() ) + return false; + + tools::Long nPos = pDashList->GetIndex(aStrName); + if( nPos == -1 ) + return false; + + const XDashEntry* pEntry = pDashList->GetDash(nPos); + XLineDashItem aDashItem(rName, pEntry->GetDash()); + rSet.Put( aDashItem ); + break; + } + default: + return false; + } + } + + return true; +} + + +bool SvxShape::SetFillAttribute( sal_uInt16 nWID, const OUString& rName, SfxItemSet& rSet ) +{ + OUString aName = SvxUnogetInternalNameForItem(nWID, rName); + + if (aName.isEmpty()) + { + switch( nWID ) + { + case XATTR_LINEEND: + case XATTR_LINESTART: + { + const basegfx::B2DPolyPolygon aEmptyPoly; + if( nWID == sal_uInt16(XATTR_LINEEND) ) + rSet.Put( XLineEndItem( "", aEmptyPoly ) ); + else + rSet.Put( XLineStartItem( "", aEmptyPoly ) ); + + return true; + } + case XATTR_FILLFLOATTRANSPARENCE: + { + // #85953# Set a disabled XFillFloatTransparenceItem + rSet.Put(XFillFloatTransparenceItem()); + + return true; + } + } + + return false; + } + + for (const SfxPoolItem* p : rSet.GetPool()->GetItemSurrogates(nWID)) + { + const NameOrIndex* pItem = static_cast<const NameOrIndex*>(p); + if( pItem->GetName() == aName ) + { + rSet.Put( *pItem ); + return true; + } + } + + return false; +} + + +void SAL_CALL SvxShape::setPropertyValue( const OUString& rPropertyName, const uno::Any& rVal ) +{ + if( mpImpl->mpMaster ) + { + mpImpl->mpMaster->setPropertyValue( rPropertyName, rVal ); + } + else + { + _setPropertyValue( rPropertyName, rVal ); + } +} + +void SvxShape::_setPropertyValue( const OUString& rPropertyName, const uno::Any& rVal ) +{ + ::SolarMutexGuard aGuard; + + const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(rPropertyName); + + if (!HasSdrObject()) + { + // Since we have no actual sdr object right now, remember all + // properties in a list. These properties will be set when the sdr + // object is created. + + if (pMap && pMap->nWID) + { + // FIXME: We should throw a UnknownPropertyException here. + // But since this class is aggregated from classes that + // support additional properties that we don't know here we + // silently store *all* properties, even if they may be not + // supported after creation. + SvxItemPropertySet::setPropertyValue( pMap, rVal, maUrsAnys ); + } + + return; + } + + if (rPropertyName == "HandlePathObjScale") + { + auto pPathObj = dynamic_cast<SdrPathObj*>(GetSdrObject()); + if (pPathObj) + { + bool bHandleScale{}; + if (rVal >>= bHandleScale) + { + pPathObj->SetHandleScale(bHandleScale); + } + } + return; + } + + if (!pMap) + { + // reduce log noise by ignoring two properties that higher level code queries for on all objects + SAL_WARN_IF(rPropertyName != "FromWordArt" && rPropertyName != "GraphicColorMode", + "svx.uno", "Unknown Property: " << rPropertyName); + throw beans::UnknownPropertyException( rPropertyName, static_cast<cppu::OWeakObject*>(this)); + } + + if ((pMap->nFlags & beans::PropertyAttribute::READONLY) != 0) + throw beans::PropertyVetoException( + "Readonly property can't be set: " + rPropertyName, + uno::Reference<drawing::XShape>(this)); + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); + + if (setPropertyValueImpl(rPropertyName, pMap, rVal)) + return; + + DBG_ASSERT( pMap->nWID == SDRATTR_TEXTDIRECTION || pMap->nWID < SDRATTR_NOTPERSIST_FIRST || pMap->nWID > SDRATTR_NOTPERSIST_LAST, "Not persist item not handled!" ); + DBG_ASSERT( pMap->nWID < OWN_ATTR_VALUE_START || pMap->nWID > OWN_ATTR_VALUE_END, "Not item property not handled!" ); + + bool bIsNotPersist = pMap->nWID >= SDRATTR_NOTPERSIST_FIRST && pMap->nWID <= SDRATTR_NOTPERSIST_LAST && pMap->nWID != SDRATTR_TEXTDIRECTION; + + if( pMap->nWID == SDRATTR_CORNER_RADIUS ) + { + sal_Int32 nCornerRadius = 0; + if( !(rVal >>= nCornerRadius) || (nCornerRadius < 0) || (nCornerRadius > 5000000)) + throw IllegalArgumentException(); + } + + std::optional<SfxItemSet> xLocalSet; + SfxItemSet* pSet; + if( mbIsMultiPropertyCall && !bIsNotPersist ) + { + if( !mpImpl->mxItemSet ) + { + mpImpl->mxItemSet.emplace( GetSdrObject()->GetProperties().CreateObjectSpecificItemSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool() ) ); + } + pSet = &*mpImpl->mxItemSet; + } + else + { + xLocalSet.emplace( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID); + pSet = &*xLocalSet; + } + + if( pSet->GetItemState( pMap->nWID ) != SfxItemState::SET ) + pSet->Put(GetSdrObject()->GetMergedItem(pMap->nWID)); + + if( !SvxUnoTextRangeBase::SetPropertyValueHelper( pMap, rVal, *pSet )) + { + if( pSet->GetItemState( pMap->nWID ) != SfxItemState::SET ) + { + if(bIsNotPersist) + { + // not-persistent attribute, get those extra + GetSdrObject()->TakeNotPersistAttr(*pSet); + } + } + + if( pSet->GetItemState( pMap->nWID ) != SfxItemState::SET ) + { + // get default from ItemPool + if(SfxItemPool::IsWhich(pMap->nWID)) + pSet->Put(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetDefaultItem(pMap->nWID)); + } + + if( pSet->GetItemState( pMap->nWID ) == SfxItemState::SET ) + { + SvxItemPropertySet_setPropertyValue( pMap, rVal, *pSet ); + } + } + + if(bIsNotPersist) + { + // set not-persistent attribute extra + GetSdrObject()->ApplyNotPersistAttr( *pSet ); + } + else + { + // if we have a XMultiProperty call then the item set + // will be set in setPropertyValues later + if( !mbIsMultiPropertyCall ) + GetSdrObject()->SetMergedItemSetAndBroadcast( *pSet ); + } +} + + +uno::Any SAL_CALL SvxShape::getPropertyValue( const OUString& PropertyName ) +{ + if ( mpImpl->mpMaster ) + return mpImpl->mpMaster->getPropertyValue( PropertyName ); + else + return _getPropertyValue( PropertyName ); +} + + +uno::Any SvxShape::_getPropertyValue( const OUString& PropertyName ) +{ + ::SolarMutexGuard aGuard; + + const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName); + + uno::Any aAny; + if(HasSdrObject()) + { + if(pMap == nullptr ) + throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this)); + + if( !getPropertyValueImpl( PropertyName, pMap, aAny ) ) + { + DBG_ASSERT( pMap->nWID == SDRATTR_TEXTDIRECTION || (pMap->nWID < SDRATTR_NOTPERSIST_FIRST || pMap->nWID > SDRATTR_NOTPERSIST_LAST), "Not persist item not handled!" ); + DBG_ASSERT( pMap->nWID < OWN_ATTR_VALUE_START || pMap->nWID > OWN_ATTR_VALUE_END, "Not item property not handled!" ); + + SfxItemSet aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID ); + aSet.Put(GetSdrObject()->GetMergedItem(pMap->nWID)); + + if(SvxUnoTextRangeBase::GetPropertyValueHelper( aSet, pMap, aAny )) + return aAny; + + if(!aSet.Count()) + { + if(pMap->nWID >= SDRATTR_NOTPERSIST_FIRST && pMap->nWID <= SDRATTR_NOTPERSIST_LAST) + { + // not-persistent attribute, get those extra + GetSdrObject()->TakeNotPersistAttr(aSet); + } + } + + if(!aSet.Count()) + { + // get default from ItemPool + if(SfxItemPool::IsWhich(pMap->nWID)) + aSet.Put(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetDefaultItem(pMap->nWID)); + } + + if(aSet.Count()) + aAny = GetAnyForItem( aSet, pMap ); + } + } + else + { + +// Fixme: we should return default values for OWN_ATTR ! + + if(pMap && pMap->nWID) +// FixMe: see setPropertyValue + aAny = mpPropSet->getPropertyValue( pMap, maUrsAnys ); + + } + return aAny; +} + + +// XMultiPropertySet +void SAL_CALL SvxShape::setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) +{ + ::SolarMutexGuard aSolarGuard; + + const sal_Int32 nCount = aPropertyNames.getLength(); + const OUString* pNames = aPropertyNames.getConstArray(); + + const uno::Any* pValues = aValues.getConstArray(); + + // make sure mbIsMultiPropertyCall and mpImpl->mpItemSet are + // reset even when an exception is thrown + const ::comphelper::ScopeGuard aGuard( [this] () { return this->endSetPropertyValues(); } ); + + mbIsMultiPropertyCall = true; + + if( mpImpl->mpMaster ) + { + for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pNames++, pValues++ ) + { + try + { + setPropertyValue( *pNames, *pValues ); + } + catch (beans::UnknownPropertyException&) + { + DBG_UNHANDLED_EXCEPTION("svx"); + } + catch (uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("svx"); + } + } + } + else + { + uno::Reference< beans::XPropertySet > xSet; + queryInterface( cppu::UnoType<beans::XPropertySet>::get()) >>= xSet; + + for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pNames++, pValues++ ) + { + try + { + xSet->setPropertyValue( *pNames, *pValues ); + } + catch (beans::UnknownPropertyException&) + { + DBG_UNHANDLED_EXCEPTION("svx"); + } + catch (uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("svx"); + } + } + } + + if( mpImpl->mxItemSet && HasSdrObject() ) + GetSdrObject()->SetMergedItemSetAndBroadcast( *mpImpl->mxItemSet ); +} + + +void SvxShape::endSetPropertyValues() +{ + mbIsMultiPropertyCall = false; + mpImpl->mxItemSet.reset(); +} + + +css::uno::Sequence< css::uno::Any > SAL_CALL SvxShape::getPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames ) +{ + const sal_Int32 nCount = aPropertyNames.getLength(); + const OUString* pNames = aPropertyNames.getConstArray(); + + uno::Sequence< uno::Any > aRet( nCount ); + uno::Any* pValue = aRet.getArray(); + + if( mpImpl->mpMaster ) + { + for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pValue++, pNames++ ) + { + try + { + *pValue = getPropertyValue( *pNames ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "SvxShape::getPropertyValues, unknown property asked" ); + } + } + } + else + { + uno::Reference< beans::XPropertySet > xSet; + queryInterface( cppu::UnoType<beans::XPropertySet>::get()) >>= xSet; + + for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pValue++, pNames++ ) + { + try + { + *pValue = xSet->getPropertyValue( *pNames ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "SvxShape::getPropertyValues, unknown property asked" ); + } + } + } + + return aRet; +} + +void SAL_CALL SvxShape::addPropertiesChangeListener( const css::uno::Sequence< OUString >& , const css::uno::Reference< css::beans::XPropertiesChangeListener >& ) +{ +} + +void SAL_CALL SvxShape::removePropertiesChangeListener( const css::uno::Reference< css::beans::XPropertiesChangeListener >& ) +{ +} + +void SAL_CALL SvxShape::firePropertiesChangeEvent( const css::uno::Sequence< OUString >& , const css::uno::Reference< css::beans::XPropertiesChangeListener >& ) +{ +} + + +uno::Any SvxShape::GetAnyForItem( SfxItemSet const & aSet, const SfxItemPropertyMapEntry* pMap ) const +{ + DBG_TESTSOLARMUTEX(); + uno::Any aAny; + + switch(pMap->nWID) + { + case SDRATTR_CIRCSTARTANGLE: + { + if(const SdrAngleItem* pPoolItem = aSet.GetItemIfSet(SDRATTR_CIRCSTARTANGLE,false)) + { + Degree100 nAngle = pPoolItem->GetValue(); + aAny <<= nAngle.get(); + } + break; + } + + case SDRATTR_CIRCENDANGLE: + { + if (const SdrAngleItem* pPoolItem = aSet.GetItemIfSet(SDRATTR_CIRCENDANGLE,false)) + { + Degree100 nAngle = pPoolItem->GetValue(); + aAny <<= nAngle.get(); + } + break; + } + + case SDRATTR_CIRCKIND: + { + if( GetSdrObject()->GetObjInventor() == SdrInventor::Default) + { + drawing::CircleKind eKind; + switch(GetSdrObject()->GetObjIdentifier()) + { + case SdrObjKind::CircleOrEllipse: // circle, ellipse + eKind = drawing::CircleKind_FULL; + break; + case SdrObjKind::CircleCut: // segment of circle + eKind = drawing::CircleKind_CUT; + break; + case SdrObjKind::CircleArc: // arc of circle + eKind = drawing::CircleKind_ARC; + break; + case SdrObjKind::CircleSection: // sector + eKind = drawing::CircleKind_SECTION; + break; + default: + break; + } + aAny <<= eKind; + } + break; + } + default: + { + // get value from ItemSet + aAny = SvxItemPropertySet_getPropertyValue( pMap, aSet ); + + if( pMap->aType != aAny.getValueType() ) + { + // since the sfx uint16 item now exports a sal_Int32, we may have to fix this here + if( ( pMap->aType == ::cppu::UnoType<sal_Int16>::get()) && aAny.getValueType() == ::cppu::UnoType<sal_Int32>::get() ) + { + sal_Int32 nValue = 0; + aAny >>= nValue; + aAny <<= static_cast<sal_Int16>(nValue); + } + else + { + OSL_FAIL("SvxShape::GetAnyForItem() Returnvalue has wrong Type!" ); + } + } + + } + } + + return aAny; +} + + +// XPropertyState +beans::PropertyState SAL_CALL SvxShape::getPropertyState( const OUString& PropertyName ) +{ + if( mpImpl->mpMaster ) + { + return mpImpl->mpMaster->getPropertyState( PropertyName ); + } + else + { + return _getPropertyState( PropertyName ); + } +} + +beans::PropertyState SvxShape::_getPropertyState( const OUString& PropertyName ) +{ + ::SolarMutexGuard aGuard; + + const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName); + + if( !HasSdrObject() || pMap == nullptr ) + throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this)); + + beans::PropertyState eState; + if( !getPropertyStateImpl( pMap, eState ) ) + { + const SfxItemSet& rSet = GetSdrObject()->GetMergedItemSet(); + + switch( rSet.GetItemState( pMap->nWID, false ) ) + { + case SfxItemState::SET: + eState = beans::PropertyState_DIRECT_VALUE; + break; + case SfxItemState::DEFAULT: + eState = beans::PropertyState_DEFAULT_VALUE; + break; + default: + eState = beans::PropertyState_AMBIGUOUS_VALUE; + break; + } + + // if an item is set, this doesn't mean we want it :) + if( beans::PropertyState_DIRECT_VALUE == eState ) + { + switch( pMap->nWID ) + { + // the following items are disabled by changing the + // fill style or the line style. so there is no need + // to export items without names which should be empty + case XATTR_FILLBITMAP: + case XATTR_FILLGRADIENT: + case XATTR_FILLHATCH: + case XATTR_LINEDASH: + { + const NameOrIndex* pItem = rSet.GetItem<NameOrIndex>(pMap->nWID); + if( ( pItem == nullptr ) || pItem->GetName().isEmpty() ) + eState = beans::PropertyState_DEFAULT_VALUE; + } + break; + + // #i36115# + // If e.g. the LineStart is on NONE and thus the string has length 0, it still + // may be a hard attribute covering the set LineStart of the parent (Style). + // #i37644# + // same is for fill float transparency + case XATTR_LINEEND: + case XATTR_LINESTART: + case XATTR_FILLFLOATTRANSPARENCE: + { + const NameOrIndex* pItem = rSet.GetItem<NameOrIndex>(pMap->nWID); + if ( pItem == nullptr ) + eState = beans::PropertyState_DEFAULT_VALUE; + } + break; + case XATTR_FILLCOLOR: + if (pMap->nMemberId == MID_COLOR_THEME_INDEX) + { + const XFillColorItem* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID); + if (pColor->GetThemeColor().GetThemeIndex() == -1) + { + eState = beans::PropertyState_DEFAULT_VALUE; + } + } + else if (pMap->nMemberId == MID_COLOR_LUM_MOD) + { + const XFillColorItem* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID); + if (pColor->GetThemeColor().GetLumMod() == 10000) + { + eState = beans::PropertyState_DEFAULT_VALUE; + } + } + else if (pMap->nMemberId == MID_COLOR_LUM_OFF) + { + const XFillColorItem* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID); + if (pColor->GetThemeColor().GetLumOff() == 0) + { + eState = beans::PropertyState_DEFAULT_VALUE; + } + } + break; + } + } + } + return eState; +} + +bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_CAPTION_POINT: + { + awt::Point aPnt; + if( rValue >>= aPnt ) + { + Point aVclPoint( aPnt.X, aPnt.Y ); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + // Need to adapt aVclPoint from 100thmm to app-specific + ForceMetricToItemPoolMetric(aVclPoint); + + // #90763# position is relative to top left, make it absolute + basegfx::B2DPolyPolygon aNewPolyPolygon; + basegfx::B2DHomMatrix aNewHomogenMatrix; + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + + aVclPoint.AdjustX(basegfx::fround(aNewHomogenMatrix.get(0, 2)) ); + aVclPoint.AdjustY(basegfx::fround(aNewHomogenMatrix.get(1, 2)) ); + + // #88491# position relative to anchor + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + { + aVclPoint += GetSdrObject()->GetAnchorPos(); + } + + static_cast<SdrCaptionObj*>(GetSdrObject())->SetTailPos(aVclPoint); + + return true; + } + break; + } + case OWN_ATTR_TRANSFORMATION: + { + drawing::HomogenMatrix3 aMatrix; + if(rValue >>= aMatrix) + { + basegfx::B2DPolyPolygon aNewPolyPolygon; + basegfx::B2DHomMatrix aNewHomogenMatrix; + + // tdf#117145 SdrModel data is app-specific + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + + aNewHomogenMatrix.set(0, 0, aMatrix.Line1.Column1); + aNewHomogenMatrix.set(0, 1, aMatrix.Line1.Column2); + aNewHomogenMatrix.set(0, 2, aMatrix.Line1.Column3); + aNewHomogenMatrix.set(1, 0, aMatrix.Line2.Column1); + aNewHomogenMatrix.set(1, 1, aMatrix.Line2.Column2); + aNewHomogenMatrix.set(1, 2, aMatrix.Line2.Column3); + aNewHomogenMatrix.set(2, 0, aMatrix.Line3.Column1); + aNewHomogenMatrix.set(2, 1, aMatrix.Line3.Column2); + aNewHomogenMatrix.set(2, 2, aMatrix.Line3.Column3); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + // Need to adapt aNewHomogenMatrix from 100thmm to app-specific + ForceMetricToItemPoolMetric(aNewHomogenMatrix); + + GetSdrObject()->TRSetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + return true; + } + break; + } + + case OWN_ATTR_ZORDER: + { + sal_Int32 nNewOrdNum = 0; + if(rValue >>= nNewOrdNum) + { + SdrObjList* pObjList = GetSdrObject()->getParentSdrObjListFromSdrObject(); + if( pObjList ) + pObjList->SetExistingObjectOrdNum( GetSdrObject(), static_cast<size_t>(nNewOrdNum) ); + return true; + } + break; + } + case OWN_ATTR_FRAMERECT: + { + awt::Rectangle aUnoRect; + if(rValue >>= aUnoRect) + { + Point aTopLeft( aUnoRect.X, aUnoRect.Y ); + Size aObjSize( aUnoRect.Width, aUnoRect.Height ); + ForceMetricToItemPoolMetric(aTopLeft); + ForceMetricToItemPoolMetric(aObjSize); + tools::Rectangle aRect; + aRect.SetPos(aTopLeft); + aRect.SetSize(aObjSize); + GetSdrObject()->SetSnapRect(aRect); + return true; + } + break; + } + case OWN_ATTR_MIRRORED: + { + bool bMirror; + if(rValue >>= bMirror ) + { + SdrGrafObj* pObj = dynamic_cast< SdrGrafObj* >( GetSdrObject() ); + if( pObj ) + pObj->SetMirrored(bMirror); + return true; + } + break; + } + case OWN_ATTR_EDGE_START_OBJ: + case OWN_ATTR_EDGE_END_OBJ: + case OWN_ATTR_GLUEID_HEAD: + case OWN_ATTR_GLUEID_TAIL: + case OWN_ATTR_EDGE_START_POS: + case OWN_ATTR_EDGE_END_POS: + case OWN_ATTR_EDGE_POLYPOLYGONBEZIER: + { + SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >(GetSdrObject()); + if(pEdgeObj) + { + switch(pProperty->nWID) + { + case OWN_ATTR_EDGE_START_OBJ: + case OWN_ATTR_EDGE_END_OBJ: + { + Reference< drawing::XShape > xShape; + if( rValue >>= xShape ) + { + SdrObject* pNode = SdrObject::getSdrObjectFromXShape(xShape); + if( pNode ) + { + pEdgeObj->ConnectToNode( pProperty->nWID == OWN_ATTR_EDGE_START_OBJ, pNode ); + pEdgeObj->setGluePointIndex( pProperty->nWID == OWN_ATTR_EDGE_START_OBJ ); + return true; + } + } + break; + } + + case OWN_ATTR_EDGE_START_POS: + case OWN_ATTR_EDGE_END_POS: + { + awt::Point aUnoPoint; + if( rValue >>= aUnoPoint ) + { + Point aPoint( aUnoPoint.X, aUnoPoint.Y ); + + // Reintroduction of fix for issue i59051 (#i108851#) + // perform metric change before applying anchor position, + // because the anchor position is in pool metric. + ForceMetricToItemPoolMetric( aPoint ); + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aPoint += GetSdrObject()->GetAnchorPos(); + + pEdgeObj->SetTailPoint( pProperty->nWID == OWN_ATTR_EDGE_START_POS, aPoint ); + return true; + } + break; + } + + case OWN_ATTR_GLUEID_HEAD: + case OWN_ATTR_GLUEID_TAIL: + { + sal_Int32 nId = 0; + if( rValue >>= nId ) + { + pEdgeObj->setGluePointIndex( pProperty->nWID == OWN_ATTR_GLUEID_HEAD, nId ); + return true; + } + break; + } + case OWN_ATTR_EDGE_POLYPOLYGONBEZIER: + { + basegfx::B2DPolyPolygon aNewPolyPolygon; + + // #123616# be a little bit more flexible regarding the data type used + if( auto s = o3tl::tryAccess<drawing::PointSequenceSequence>(rValue) ) + { + // get polygpon data from PointSequenceSequence + aNewPolyPolygon = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon( + *s); + } + else if( auto cs = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(rValue) ) + { + // get polygpon data from PolyPolygonBezierCoords + aNewPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( + *cs); + } + + if(aNewPolyPolygon.count()) + { + // Reintroduction of fix for issue i59051 (#i108851#) + ForceMetricToItemPoolMetric( aNewPolyPolygon ); + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + { + Point aPoint( GetSdrObject()->GetAnchorPos() ); + aNewPolyPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix(aPoint.X(), aPoint.Y())); + } + pEdgeObj->SetEdgeTrackPath( aNewPolyPolygon ); + return true; + } + } + } + } + break; + } + case OWN_ATTR_MEASURE_START_POS: + case OWN_ATTR_MEASURE_END_POS: + { + SdrMeasureObj* pMeasureObj = dynamic_cast< SdrMeasureObj* >(GetSdrObject()); + awt::Point aUnoPoint; + if(pMeasureObj && ( rValue >>= aUnoPoint ) ) + { + Point aPoint( aUnoPoint.X, aUnoPoint.Y ); + + // Reintroduction of fix for issue #i59051# (#i108851#) + ForceMetricToItemPoolMetric( aPoint ); + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aPoint += GetSdrObject()->GetAnchorPos(); + + pMeasureObj->NbcSetPoint( aPoint, pProperty->nWID == OWN_ATTR_MEASURE_START_POS ? 0 : 1 ); + pMeasureObj->SetChanged(); + pMeasureObj->BroadcastObjectChange(); + return true; + } + break; + } + case OWN_ATTR_FILLBMP_MODE: + { + drawing::BitmapMode eMode; + if(!(rValue >>= eMode) ) + { + sal_Int32 nMode = 0; + if(!(rValue >>= nMode)) + break; + + eMode = static_cast<drawing::BitmapMode>(nMode); + } + GetSdrObject()->SetMergedItem( XFillBmpStretchItem( eMode == drawing::BitmapMode_STRETCH ) ); + GetSdrObject()->SetMergedItem( XFillBmpTileItem( eMode == drawing::BitmapMode_REPEAT ) ); + return true; + } + + case SDRATTR_LAYERID: + { + sal_Int16 nLayerId = sal_Int16(); + if( rValue >>= nLayerId ) + { + SdrLayer* pLayer = GetSdrObject()->getSdrModelFromSdrObject().GetLayerAdmin().GetLayerPerID(SdrLayerID(nLayerId)); + if( pLayer ) + { + GetSdrObject()->SetLayer(SdrLayerID(nLayerId)); + return true; + } + } + break; + } + + case SDRATTR_LAYERNAME: + { + OUString aLayerName; + if( rValue >>= aLayerName ) + { + const SdrLayer* pLayer = GetSdrObject()->getSdrModelFromSdrObject().GetLayerAdmin().GetLayer(aLayerName); + if( pLayer != nullptr ) + { + GetSdrObject()->SetLayer( pLayer->GetID() ); + return true; + } + } + break; + } + case SDRATTR_ROTATEANGLE: + { + sal_Int32 nTmp = 0; + if( rValue >>= nTmp ) + { + Degree100 nAngle(nTmp); + Point aRef1(GetSdrObject()->GetSnapRect().Center()); + nAngle -= GetSdrObject()->GetRotateAngle(); + if (nAngle) + { + double nSin = sin(toRadians(nAngle)); + double nCos = cos(toRadians(nAngle)); + GetSdrObject()->Rotate(aRef1,nAngle,nSin,nCos); + } + return true; + } + + break; + } + + case SDRATTR_SHEARANGLE: + { + sal_Int32 nTmp = 0; + if( rValue >>= nTmp ) + { + Degree100 nShear(nTmp); + nShear -= GetSdrObject()->GetShearAngle(); + if(nShear) + { + Point aRef1(GetSdrObject()->GetSnapRect().Center()); + double nTan = tan(toRadians(nShear)); + GetSdrObject()->Shear(aRef1,nShear,nTan,false); + return true; + } + } + + break; + } + + case OWN_ATTR_INTEROPGRABBAG: + { + GetSdrObject()->SetGrabBagItem(rValue); + return true; + } + + case SDRATTR_OBJMOVEPROTECT: + { + bool bMoveProtect; + if( rValue >>= bMoveProtect ) + { + GetSdrObject()->SetMoveProtect(bMoveProtect); + return true; + } + break; + } + case SDRATTR_OBJECTNAME: + { + OUString aName; + if( rValue >>= aName ) + { + GetSdrObject()->SetName( aName ); + return true; + } + break; + } + + case OWN_ATTR_TEXTFITTOSIZESCALE: + { + sal_Int16 nMaxScale = 0; + if (rValue >>= nMaxScale) + { + SdrTextFitToSizeTypeItem aItem(GetSdrObject()->GetMergedItem(SDRATTR_TEXT_FITTOSIZE)); + aItem.SetMaxScale(nMaxScale); + GetSdrObject()->SetMergedItem(aItem); + return true; + } + break; + } + + // #i68101# + case OWN_ATTR_MISC_OBJ_TITLE: + { + OUString aTitle; + if( rValue >>= aTitle ) + { + GetSdrObject()->SetTitle( aTitle ); + return true; + } + break; + } + case OWN_ATTR_MISC_OBJ_DESCRIPTION: + { + OUString aDescription; + if( rValue >>= aDescription ) + { + GetSdrObject()->SetDescription( aDescription ); + return true; + } + break; + } + + case SDRATTR_OBJPRINTABLE: + { + bool bPrintable; + if( rValue >>= bPrintable ) + { + GetSdrObject()->SetPrintable(bPrintable); + return true; + } + break; + } + case SDRATTR_OBJVISIBLE: + { + bool bVisible; + if( rValue >>= bVisible ) + { + GetSdrObject()->SetVisible(bVisible); + return true; + } + break; + } + case SDRATTR_OBJSIZEPROTECT: + { + bool bResizeProtect; + if( rValue >>= bResizeProtect ) + { + GetSdrObject()->SetResizeProtect(bResizeProtect); + return true; + } + break; + } + case OWN_ATTR_PAGE_NUMBER: + { + sal_Int32 nPageNum = 0; + if( (rValue >>= nPageNum) && ( nPageNum >= 0 ) && ( nPageNum <= 0xffff ) ) + { + SdrPageObj* pPageObj = dynamic_cast< SdrPageObj* >(GetSdrObject()); + if( pPageObj ) + { + SdrModel& rModel(pPageObj->getSdrModelFromSdrObject()); + SdrPage* pNewPage = nullptr; + const sal_uInt16 nDestinationPageNum(static_cast<sal_uInt16>((nPageNum << 1) - 1)); + + if(nDestinationPageNum < rModel.GetPageCount()) + { + pNewPage = rModel.GetPage(nDestinationPageNum); + } + + pPageObj->SetReferencedPage(pNewPage); + } + + return true; + } + break; + } + case XATTR_FILLBITMAP: + case XATTR_FILLGRADIENT: + case XATTR_FILLHATCH: + case XATTR_FILLFLOATTRANSPARENCE: + case XATTR_LINEEND: + case XATTR_LINESTART: + case XATTR_LINEDASH: + { + if( pProperty->nMemberId == MID_NAME ) + { + OUString aApiName; + if( rValue >>= aApiName ) + { + if( SetFillAttribute( pProperty->nWID, aApiName ) ) + return true; + } + break; + } + else + { + return false; + } + } + + case OWN_ATTR_TEXTCOLUMNS: + { + if (auto pTextObj = dynamic_cast<SdrTextObj*>(GetSdrObject())) + { + css::uno::Reference<css::text::XTextColumns> xTextColumns; + if (rValue >>= xTextColumns) + { + pTextObj->SetTextColumnsNumber(xTextColumns->getColumnCount()); + if (css::uno::Reference<css::beans::XPropertySet> xPropSet{ xTextColumns, + css::uno::UNO_QUERY }) + { + auto aVal = xPropSet->getPropertyValue("AutomaticDistance"); + if (sal_Int32 nSpacing; aVal >>= nSpacing) + pTextObj->SetTextColumnsSpacing(nSpacing); + } + } + } + return true; + } + + case OWN_ATTR_HYPERLINK: + { + OUString sHyperlink; + if (rValue >>= sHyperlink) + { + GetSdrObject()->setHyperlink(sHyperlink); + return true; + } + break; + } + + default: + { + return false; + } + } + + OUString sExceptionMessage ("IllegalArgumentException in SvxShape::setPropertyValueImpl." + " Property Type: " + pProperty->aType.getTypeName() + " Property nWID: " + OUString::number(pProperty->nWID) + + " Value Type: " + (rValue.hasValue() ? rValue.getValueTypeName() : "void (no value)")); + + throw lang::IllegalArgumentException(sExceptionMessage, nullptr, 1); +} + + +bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + switch( pProperty->nWID ) + { + case OWN_ATTR_CAPTION_POINT: + { + Point aVclPoint = static_cast<SdrCaptionObj*>(GetSdrObject())->GetTailPos(); + + // #88491# make pos relative to anchor + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + { + aVclPoint -= GetSdrObject()->GetAnchorPos(); + } + + // #90763# pos is absolute, make it relative to top left + basegfx::B2DPolyPolygon aNewPolyPolygon; + basegfx::B2DHomMatrix aNewHomogenMatrix; + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + + aVclPoint.AdjustX( -(basegfx::fround(aNewHomogenMatrix.get(0, 2))) ); + aVclPoint.AdjustY( -(basegfx::fround(aNewHomogenMatrix.get(1, 2))) ); + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + // Need to adapt aVclPoint from app-specific to 100thmm + ForceMetricTo100th_mm(aVclPoint); + + awt::Point aPnt( aVclPoint.X(), aVclPoint.Y() ); + rValue <<= aPnt; + break; + } + + case OWN_ATTR_TRANSFORMATION: + { + basegfx::B2DPolyPolygon aNewPolyPolygon; + basegfx::B2DHomMatrix aNewHomogenMatrix; + GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon); + drawing::HomogenMatrix3 aMatrix; + + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + // Need to adapt aNewHomogenMatrix from app-specific to 100thmm + ForceMetricTo100th_mm(aNewHomogenMatrix); + + aMatrix.Line1.Column1 = aNewHomogenMatrix.get(0, 0); + aMatrix.Line1.Column2 = aNewHomogenMatrix.get(0, 1); + aMatrix.Line1.Column3 = aNewHomogenMatrix.get(0, 2); + aMatrix.Line2.Column1 = aNewHomogenMatrix.get(1, 0); + aMatrix.Line2.Column2 = aNewHomogenMatrix.get(1, 1); + aMatrix.Line2.Column3 = aNewHomogenMatrix.get(1, 2); + aMatrix.Line3.Column1 = aNewHomogenMatrix.get(2, 0); + aMatrix.Line3.Column2 = aNewHomogenMatrix.get(2, 1); + aMatrix.Line3.Column3 = aNewHomogenMatrix.get(2, 2); + + rValue <<= aMatrix; + + break; + } + + case OWN_ATTR_ZORDER: + { + rValue <<= static_cast<sal_Int32>(GetSdrObject()->GetOrdNum()); + break; + } + + case OWN_ATTR_BITMAP: + { + rValue = GetBitmap(); + if(!rValue.hasValue()) + throw uno::RuntimeException(); + + break; + } + + case OWN_ATTR_ISFONTWORK: + { + bool bIsFontwork = false; + if (const SdrTextObj* pTextObj = dynamic_cast<const SdrTextObj*>(GetSdrObject())) + bIsFontwork = pTextObj->IsFontwork(); + rValue <<= bIsFontwork; + break; + } + + case OWN_ATTR_FRAMERECT: + { + tools::Rectangle aRect( GetSdrObject()->GetSnapRect() ); + Point aTopLeft( aRect.TopLeft() ); + Size aObjSize( aRect.GetWidth(), aRect.GetHeight() ); + ForceMetricTo100th_mm(aTopLeft); + ForceMetricTo100th_mm(aObjSize); + css::awt::Rectangle aUnoRect( + aTopLeft.X(), aTopLeft.Y(), + aObjSize.getWidth(), aObjSize.getHeight() ); + rValue <<= aUnoRect; + break; + } + + case OWN_ATTR_BOUNDRECT: + { + tools::Rectangle aRect( GetSdrObject()->GetCurrentBoundRect() ); + Point aTopLeft( aRect.TopLeft() ); + Size aObjSize( aRect.GetWidth(), aRect.GetHeight() ); + ForceMetricTo100th_mm(aTopLeft); + ForceMetricTo100th_mm(aObjSize); + css::awt::Rectangle aUnoRect( + aTopLeft.X(), aTopLeft.Y(), + aObjSize.getWidth(), aObjSize.getHeight() ); + rValue <<= aUnoRect; + break; + } + + case OWN_ATTR_LDNAME: + { + OUString aName( GetSdrObject()->GetName() ); + rValue <<= aName; + break; + } + + case OWN_ATTR_LDBITMAP: + { + OUString sId; + if( GetSdrObject()->GetObjInventor() == SdrInventor::Default && GetSdrObject()->GetObjIdentifier() == SdrObjKind::OLE2 ) + { + sId = RID_UNODRAW_OLE2; + } + else if( GetSdrObject()->GetObjInventor() == SdrInventor::Default && GetSdrObject()->GetObjIdentifier() == SdrObjKind::Graphic ) + { + sId = RID_UNODRAW_GRAPHICS; + } + else + { + sId = RID_UNODRAW_OBJECTS; + } + + BitmapEx aBmp(sId); + Reference<awt::XBitmap> xBmp(VCLUnoHelper::CreateBitmap(aBmp)); + + rValue <<= xBmp; + break; + } + + case OWN_ATTR_MIRRORED: + { + bool bMirror = false; + if( HasSdrObject() ) + if (auto pGrafObj = dynamic_cast<SdrGrafObj*>(GetSdrObject()) ) + bMirror = pGrafObj->IsMirrored(); + + rValue <<= bMirror; + break; + } + + case OWN_ATTR_EDGE_START_OBJ: + case OWN_ATTR_EDGE_START_POS: + case OWN_ATTR_EDGE_END_POS: + case OWN_ATTR_EDGE_END_OBJ: + case OWN_ATTR_GLUEID_HEAD: + case OWN_ATTR_GLUEID_TAIL: + case OWN_ATTR_EDGE_POLYPOLYGONBEZIER: + { + SdrEdgeObj* pEdgeObj = dynamic_cast<SdrEdgeObj*>(GetSdrObject()); + if(pEdgeObj) + { + switch(pProperty->nWID) + { + case OWN_ATTR_EDGE_START_OBJ: + case OWN_ATTR_EDGE_END_OBJ: + { + SdrObject* pNode = pEdgeObj->GetConnectedNode(pProperty->nWID == OWN_ATTR_EDGE_START_OBJ); + if(pNode) + { + Reference< drawing::XShape > xShape( GetXShapeForSdrObject( pNode ) ); + if(xShape.is()) + rValue <<= xShape; + + } + break; + } + + case OWN_ATTR_EDGE_START_POS: + case OWN_ATTR_EDGE_END_POS: + { + Point aPoint( pEdgeObj->GetTailPoint( pProperty->nWID == OWN_ATTR_EDGE_START_POS ) ); + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aPoint -= GetSdrObject()->GetAnchorPos(); + + ForceMetricTo100th_mm( aPoint ); + awt::Point aUnoPoint( aPoint.X(), aPoint.Y() ); + + rValue <<= aUnoPoint; + break; + } + case OWN_ATTR_GLUEID_HEAD: + case OWN_ATTR_GLUEID_TAIL: + { + rValue <<= pEdgeObj->getGluePointIndex( pProperty->nWID == OWN_ATTR_GLUEID_HEAD ); + break; + } + case OWN_ATTR_EDGE_POLYPOLYGONBEZIER: + { + basegfx::B2DPolyPolygon aPolyPoly( pEdgeObj->GetEdgeTrackPath() ); + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + { + Point aPoint( GetSdrObject()->GetAnchorPos() ); + aPolyPoly.transform(basegfx::utils::createTranslateB2DHomMatrix(-aPoint.X(), -aPoint.Y())); + } + // Reintroduction of fix for issue #i59051# (#i108851#) + ForceMetricTo100th_mm( aPolyPoly ); + drawing::PolyPolygonBezierCoords aRetval; + basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( aPolyPoly, aRetval); + rValue <<= aRetval; + break; + } + } + } + break; + } + + case OWN_ATTR_MEASURE_START_POS: + case OWN_ATTR_MEASURE_END_POS: + { + SdrMeasureObj* pMeasureObj = dynamic_cast<SdrMeasureObj*>(GetSdrObject()); + if(pMeasureObj) + { + Point aPoint( pMeasureObj->GetPoint( pProperty->nWID == OWN_ATTR_MEASURE_START_POS ? 0 : 1 ) ); + if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() ) + aPoint -= GetSdrObject()->GetAnchorPos(); + + // Reintroduction of fix for issue #i59051# (#i108851#) + ForceMetricTo100th_mm( aPoint ); + awt::Point aUnoPoint( aPoint.X(), aPoint.Y() ); + + rValue <<= aUnoPoint; + break; + } + break; + } + + case OWN_ATTR_FILLBMP_MODE: + { + const SfxItemSet& rObjItemSet = GetSdrObject()->GetMergedItemSet(); + + if (rObjItemSet.Get(XATTR_FILLBMP_TILE).GetValue()) + { + rValue <<= drawing::BitmapMode_REPEAT; + } + else if (rObjItemSet.Get(XATTR_FILLBMP_STRETCH).GetValue()) + { + rValue <<= drawing::BitmapMode_STRETCH; + } + else + { + rValue <<= drawing::BitmapMode_NO_REPEAT; + } + break; + } + case SDRATTR_LAYERID: + rValue <<= GetSdrObject()->GetLayer().get(); + break; + + case SDRATTR_LAYERNAME: + { + SdrLayer* pLayer = GetSdrObject()->getSdrModelFromSdrObject().GetLayerAdmin().GetLayerPerID(GetSdrObject()->GetLayer()); + if( pLayer ) + { + rValue <<= pLayer->GetName(); + } + break; + } + + case SDRATTR_ROTATEANGLE: + rValue <<= static_cast<sal_Int32>(GetSdrObject()->GetRotateAngle()); + break; + + case SDRATTR_SHEARANGLE: + rValue <<= static_cast<sal_Int32>(GetSdrObject()->GetShearAngle()); + break; + + case OWN_ATTR_INTEROPGRABBAG: + { + GetSdrObject()->GetGrabBagItem(rValue); + break; + } + + case SDRATTR_OBJMOVEPROTECT: + rValue <<= GetSdrObject()->IsMoveProtect(); + break; + + case SDRATTR_OBJECTNAME: + { + OUString aName( GetSdrObject()->GetName() ); + rValue <<= aName; + break; + } + + // #i68101# + case OWN_ATTR_MISC_OBJ_TITLE: + { + OUString aTitle( GetSdrObject()->GetTitle() ); + rValue <<= aTitle; + break; + } + + case OWN_ATTR_MISC_OBJ_DESCRIPTION: + { + OUString aDescription( GetSdrObject()->GetDescription() ); + rValue <<= aDescription; + break; + } + + case SDRATTR_OBJPRINTABLE: + rValue <<= GetSdrObject()->IsPrintable(); + break; + + case SDRATTR_OBJVISIBLE: + rValue <<= GetSdrObject()->IsVisible(); + break; + + case SDRATTR_OBJSIZEPROTECT: + rValue <<= GetSdrObject()->IsResizeProtect(); + break; + + case OWN_ATTR_PAGE_NUMBER: + { + SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(GetSdrObject()); + if(pPageObj) + { + SdrPage* pPage = pPageObj->GetReferencedPage(); + sal_Int32 nPageNumber = pPage ? pPage->GetPageNum() : 0; + nPageNumber++; + nPageNumber >>= 1; + rValue <<= nPageNumber; + } + break; + } + + case OWN_ATTR_UINAME_SINGULAR: + { + rValue <<= GetSdrObject()->TakeObjNameSingul(); + break; + } + + case OWN_ATTR_TEXTFITTOSIZESCALE: + { + rValue <<= GetTextFitToSizeScale(GetSdrObject()); + break; + } + + case OWN_ATTR_UINAME_PLURAL: + { + rValue <<= GetSdrObject()->TakeObjNamePlural(); + break; + } + case OWN_ATTR_METAFILE: + { + SdrOle2Obj* pObj = dynamic_cast<SdrOle2Obj*>(GetSdrObject()); + if( pObj ) + { + const Graphic* pGraphic = pObj->GetGraphic(); + if( pGraphic ) + { + bool bIsWMF = false; + if ( pGraphic->IsGfxLink() ) + { + GfxLink aLnk = pGraphic->GetGfxLink(); + if ( aLnk.GetType() == GfxLinkType::NativeWmf ) + { + bIsWMF = true; + uno::Sequence<sal_Int8> aSeq(reinterpret_cast<sal_Int8 const *>(aLnk.GetData()), static_cast<sal_Int32>(aLnk.GetDataSize())); + rValue <<= aSeq; + } + } + if ( !bIsWMF ) + { + // #119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically + GDIMetaFile aMtf(pObj->GetGraphic()->GetGDIMetaFile()); + SvMemoryStream aDestStrm( 65535, 65535 ); + ConvertGDIMetaFileToWMF( aMtf, aDestStrm, nullptr, false ); + const uno::Sequence<sal_Int8> aSeq( + static_cast< const sal_Int8* >(aDestStrm.GetData()), + aDestStrm.GetEndOfData()); + rValue <<= aSeq; + } + } + } + else + { + rValue = GetBitmap( true ); + } + break; + } + + case OWN_ATTR_TEXTCOLUMNS: + { + if (auto pTextObj = dynamic_cast<const SdrTextObj*>(GetSdrObject())) + { + if (pTextObj->HasTextColumnsNumber() || pTextObj->HasTextColumnsSpacing()) + { + auto xIf = SvxXTextColumns_createInstance(); + css::uno::Reference<css::text::XTextColumns> xCols(xIf, css::uno::UNO_QUERY_THROW); + xCols->setColumnCount(pTextObj->GetTextColumnsNumber()); + css::uno::Reference<css::beans::XPropertySet> xProp(xIf, css::uno::UNO_QUERY_THROW); + xProp->setPropertyValue("AutomaticDistance", + css::uno::Any(pTextObj->GetTextColumnsSpacing())); + rValue <<= xIf; + } + } + break; + } + + case OWN_ATTR_HYPERLINK: + { + rValue <<= GetSdrObject()->getHyperlink(); + break; + } + + default: + return false; + } + return true; +} + + +bool SvxShape::getPropertyStateImpl( const SfxItemPropertyMapEntry* pProperty, css::beans::PropertyState& rState ) +{ + if( pProperty->nWID == OWN_ATTR_FILLBMP_MODE ) + { + const SfxItemSet& rSet = GetSdrObject()->GetMergedItemSet(); + + if( rSet.GetItemState( XATTR_FILLBMP_STRETCH, false ) == SfxItemState::SET || + rSet.GetItemState( XATTR_FILLBMP_TILE, false ) == SfxItemState::SET ) + { + rState = beans::PropertyState_DIRECT_VALUE; + } + else + { + rState = beans::PropertyState_AMBIGUOUS_VALUE; + } + } + else if((( pProperty->nWID >= OWN_ATTR_VALUE_START && pProperty->nWID <= OWN_ATTR_VALUE_END ) || + ( pProperty->nWID >= SDRATTR_NOTPERSIST_FIRST && pProperty->nWID <= SDRATTR_NOTPERSIST_LAST )) && ( pProperty->nWID != SDRATTR_TEXTDIRECTION ) ) + { + rState = beans::PropertyState_DIRECT_VALUE; + } + else + { + return false; + } + + return true; +} + + +bool SvxShape::setPropertyToDefaultImpl( const SfxItemPropertyMapEntry* pProperty ) +{ + if( pProperty->nWID == OWN_ATTR_FILLBMP_MODE ) + { + GetSdrObject()->ClearMergedItem( XATTR_FILLBMP_STRETCH ); + GetSdrObject()->ClearMergedItem( XATTR_FILLBMP_TILE ); + return true; + } + else if((pProperty->nWID >= OWN_ATTR_VALUE_START && pProperty->nWID <= OWN_ATTR_VALUE_END ) || + ( pProperty->nWID >= SDRATTR_NOTPERSIST_FIRST && pProperty->nWID <= SDRATTR_NOTPERSIST_LAST )) + { + return true; + } + else + { + return false; + } +} + + +uno::Sequence< beans::PropertyState > SAL_CALL SvxShape::getPropertyStates( const uno::Sequence< OUString >& aPropertyName ) +{ + const sal_Int32 nCount = aPropertyName.getLength(); + uno::Sequence< beans::PropertyState > aRet( nCount ); + + std::transform(aPropertyName.begin(), aPropertyName.end(), aRet.getArray(), + [this](const OUString& rName) -> beans::PropertyState { return getPropertyState(rName); }); + + return aRet; +} + + +void SAL_CALL SvxShape::setPropertyToDefault( const OUString& PropertyName ) +{ + if( mpImpl->mpMaster ) + { + mpImpl->mpMaster->setPropertyToDefault( PropertyName ); + } + else + { + _setPropertyToDefault( PropertyName ); + } +} + +void SvxShape::_setPropertyToDefault( const OUString& PropertyName ) +{ + ::SolarMutexGuard aGuard; + + const SfxItemPropertyMapEntry* pProperty = mpPropSet->getPropertyMapEntry(PropertyName); + + if( !HasSdrObject() || pProperty == nullptr ) + throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this)); + + if( !setPropertyToDefaultImpl( pProperty ) ) + { + GetSdrObject()->ClearMergedItem( pProperty->nWID ); + } + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + + +uno::Any SAL_CALL SvxShape::getPropertyDefault( const OUString& aPropertyName ) +{ + if( mpImpl->mpMaster ) + { + return mpImpl->mpMaster->getPropertyDefault( aPropertyName ); + } + else + { + return _getPropertyDefault( aPropertyName ); + } +} + +uno::Any SvxShape::_getPropertyDefault( const OUString& aPropertyName ) +{ + ::SolarMutexGuard aGuard; + + const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(aPropertyName); + + if( !HasSdrObject() || pMap == nullptr ) + throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this)); + + if(( pMap->nWID >= OWN_ATTR_VALUE_START && pMap->nWID <= OWN_ATTR_VALUE_END ) || + ( pMap->nWID >= SDRATTR_NOTPERSIST_FIRST && pMap->nWID <= SDRATTR_NOTPERSIST_LAST )) + { + return getPropertyValue( aPropertyName ); + } + + // get default from ItemPool + if(!SfxItemPool::IsWhich(pMap->nWID)) + throw beans::UnknownPropertyException( "No WhichID " + OUString::number(pMap->nWID) + " for " + aPropertyName, static_cast<cppu::OWeakObject*>(this)); + + SfxItemSet aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID ); + aSet.Put(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetDefaultItem(pMap->nWID)); + + return GetAnyForItem( aSet, pMap ); +} + +// XMultiPropertyStates +void SvxShape::setAllPropertiesToDefault() +{ + ::SolarMutexGuard aGuard; + + if( !HasSdrObject() ) + throw lang::DisposedException(); + GetSdrObject()->ClearMergedItem(); // nWhich == 0 => all + + if(dynamic_cast<const SdrGrafObj*>(GetSdrObject()) != nullptr) + { + // defaults for graphic objects have changed: + GetSdrObject()->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) ); + GetSdrObject()->SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) ); + } + + // #i68523# special handling for Svx3DCharacterModeItem, this is not saved + // but needs to be sal_True in svx, pool default (false) in sch. Since sch + // does not load lathe or extrude objects, it is possible to set the items + // here. + // For other solution possibilities, see task description. + if( dynamic_cast<const E3dLatheObj* >(GetSdrObject()) != nullptr|| dynamic_cast<const E3dExtrudeObj* >(GetSdrObject()) != nullptr) + { + GetSdrObject()->SetMergedItem(Svx3DCharacterModeItem(true)); + } + + GetSdrObject()->getSdrModelFromSdrObject().SetChanged(); +} + +void SvxShape::setPropertiesToDefault( + const uno::Sequence<OUString>& aPropertyNames ) +{ + for ( const auto& rPropertyName : aPropertyNames ) + setPropertyToDefault( rPropertyName ); +} + +uno::Sequence<uno::Any> SvxShape::getPropertyDefaults( + const uno::Sequence<OUString>& aPropertyNames ) +{ + ::std::vector<uno::Any> ret; + ret.reserve(aPropertyNames.getLength()); + std::transform(aPropertyNames.begin(), aPropertyNames.end(), std::back_inserter(ret), + [this](const OUString& rName) -> uno::Any { return getPropertyDefault(rName); }); + return uno::Sequence<uno::Any>( ret.data(), ret.size() ); +} + + +// XServiceInfo + +OUString SAL_CALL SvxShape::getImplementationName() +{ + return "SvxShape"; +} + +constexpr OUStringLiteral sUNO_service_style_ParagraphProperties = u"com.sun.star.style.ParagraphProperties"; +constexpr OUStringLiteral sUNO_service_style_ParagraphPropertiesComplex = u"com.sun.star.style.ParagraphPropertiesComplex"; +constexpr OUStringLiteral sUNO_service_style_ParagraphPropertiesAsian = u"com.sun.star.style.ParagraphPropertiesAsian"; +constexpr OUStringLiteral sUNO_service_style_CharacterProperties = u"com.sun.star.style.CharacterProperties"; +constexpr OUStringLiteral sUNO_service_style_CharacterPropertiesComplex = u"com.sun.star.style.CharacterPropertiesComplex"; +constexpr OUStringLiteral sUNO_service_style_CharacterPropertiesAsian = u"com.sun.star.style.CharacterPropertiesAsian"; + +constexpr OUStringLiteral sUNO_service_drawing_FillProperties = u"com.sun.star.drawing.FillProperties"; +constexpr OUStringLiteral sUNO_service_drawing_TextProperties = u"com.sun.star.drawing.TextProperties"; +constexpr OUStringLiteral sUNO_service_drawing_LineProperties = u"com.sun.star.drawing.LineProperties"; +constexpr OUStringLiteral sUNO_service_drawing_ConnectorProperties = u"com.sun.star.drawing.ConnectorProperties"; +constexpr OUStringLiteral sUNO_service_drawing_MeasureProperties = u"com.sun.star.drawing.MeasureProperties"; +constexpr OUStringLiteral sUNO_service_drawing_ShadowProperties = u"com.sun.star.drawing.ShadowProperties"; + +constexpr OUStringLiteral sUNO_service_drawing_RotationDescriptor = u"com.sun.star.drawing.RotationDescriptor"; + +constexpr OUStringLiteral sUNO_service_drawing_Text = u"com.sun.star.drawing.Text"; +constexpr OUStringLiteral sUNO_service_drawing_GroupShape = u"com.sun.star.drawing.GroupShape"; + +constexpr OUStringLiteral sUNO_service_drawing_CustomShapeProperties = u"com.sun.star.drawing.CustomShapeProperties"; +constexpr OUStringLiteral sUNO_service_drawing_CustomShape = u"com.sun.star.drawing.CustomShape"; + +constexpr OUStringLiteral sUNO_service_drawing_PolyPolygonDescriptor = u"com.sun.star.drawing.PolyPolygonDescriptor"; +constexpr OUStringLiteral sUNO_service_drawing_PolyPolygonBezierDescriptor= u"com.sun.star.drawing.PolyPolygonBezierDescriptor"; + +constexpr OUStringLiteral sUNO_service_drawing_LineShape = u"com.sun.star.drawing.LineShape"; +constexpr OUStringLiteral sUNO_service_drawing_Shape = u"com.sun.star.drawing.Shape"; +constexpr OUStringLiteral sUNO_service_drawing_RectangleShape = u"com.sun.star.drawing.RectangleShape"; +constexpr OUStringLiteral sUNO_service_drawing_EllipseShape = u"com.sun.star.drawing.EllipseShape"; +constexpr OUStringLiteral sUNO_service_drawing_PolyPolygonShape = u"com.sun.star.drawing.PolyPolygonShape"; +constexpr OUStringLiteral sUNO_service_drawing_PolyLineShape = u"com.sun.star.drawing.PolyLineShape"; +constexpr OUStringLiteral sUNO_service_drawing_OpenBezierShape = u"com.sun.star.drawing.OpenBezierShape"; +constexpr OUStringLiteral sUNO_service_drawing_ClosedBezierShape = u"com.sun.star.drawing.ClosedBezierShape"; +constexpr OUStringLiteral sUNO_service_drawing_TextShape = u"com.sun.star.drawing.TextShape"; +constexpr OUStringLiteral sUNO_service_drawing_GraphicObjectShape = u"com.sun.star.drawing.GraphicObjectShape"; +constexpr OUStringLiteral sUNO_service_drawing_OLE2Shape = u"com.sun.star.drawing.OLE2Shape"; +constexpr OUStringLiteral sUNO_service_drawing_PageShape = u"com.sun.star.drawing.PageShape"; +constexpr OUStringLiteral sUNO_service_drawing_CaptionShape = u"com.sun.star.drawing.CaptionShape"; +constexpr OUStringLiteral sUNO_service_drawing_MeasureShape = u"com.sun.star.drawing.MeasureShape"; +constexpr OUStringLiteral sUNO_service_drawing_FrameShape = u"com.sun.star.drawing.FrameShape"; +constexpr OUStringLiteral sUNO_service_drawing_ControlShape = u"com.sun.star.drawing.ControlShape"; +constexpr OUStringLiteral sUNO_service_drawing_ConnectorShape = u"com.sun.star.drawing.ConnectorShape"; +constexpr OUStringLiteral sUNO_service_drawing_MediaShape = u"com.sun.star.drawing.MediaShape"; + + +uno::Sequence< OUString > SAL_CALL SvxShape::getSupportedServiceNames() +{ + if( mpImpl->mpMaster ) + { + return mpImpl->mpMaster->getSupportedServiceNames(); + } + else + { + return _getSupportedServiceNames(); + } +} + +uno::Sequence< OUString > SvxShape::_getSupportedServiceNames() +{ + ::SolarMutexGuard aGuard; + + if( HasSdrObject() && GetSdrObject()->GetObjInventor() == SdrInventor::Default) + { + const SdrObjKind nIdent = GetSdrObject()->GetObjIdentifier(); + + switch(nIdent) + { + case SdrObjKind::Group: + { + static const uno::Sequence<OUString> aSvxShape_GroupServices + = { sUNO_service_drawing_GroupShape, + sUNO_service_drawing_Shape }; + return aSvxShape_GroupServices; + } + case SdrObjKind::CustomShape: + { + static const uno::Sequence<OUString> aSvxShape_CustomShapeServices + = { sUNO_service_drawing_CustomShape, + sUNO_service_drawing_Shape, + sUNO_service_drawing_CustomShapeProperties, + sUNO_service_drawing_FillProperties, + sUNO_service_drawing_LineProperties, + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_CustomShapeServices; + } + case SdrObjKind::Line: + { + static const uno::Sequence<OUString> aSvxShape_LineServices + = { sUNO_service_drawing_LineShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_PolyPolygonDescriptor, + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_LineServices; + } + + case SdrObjKind::Rectangle: + { + static const uno::Sequence<OUString> aSvxShape_RectServices + = { sUNO_service_drawing_RectangleShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_FillProperties, + sUNO_service_drawing_LineProperties, + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_RectServices; + } + + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::CircleSection: + case SdrObjKind::CircleArc: + case SdrObjKind::CircleCut: + { + static const uno::Sequence<OUString> aSvxShape_CircServices + = { sUNO_service_drawing_EllipseShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_FillProperties, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_CircServices; + } + + case SdrObjKind::PathPolyLine: + case SdrObjKind::PolyLine: + { + static const uno::Sequence<OUString> aSvxShape_PathServices + = { sUNO_service_drawing_PolyLineShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_PolyPolygonDescriptor, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_PathServices; + } + + case SdrObjKind::PathPoly: + case SdrObjKind::Polygon: + { + static const uno::Sequence<OUString> aSvxShape_PolyServices + = { sUNO_service_drawing_PolyPolygonShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + sUNO_service_drawing_FillProperties, + + sUNO_service_drawing_PolyPolygonDescriptor, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_PolyServices; + } + + case SdrObjKind::FreehandLine: + case SdrObjKind::PathLine: + { + static const uno::Sequence<OUString> aSvxShape_FreeLineServices + = { sUNO_service_drawing_OpenBezierShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + sUNO_service_drawing_FillProperties, + + sUNO_service_drawing_PolyPolygonBezierDescriptor, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_FreeLineServices; + } + + case SdrObjKind::FreehandFill: + case SdrObjKind::PathFill: + { + static const uno::Sequence<OUString> aSvxShape_FreeFillServices + = { sUNO_service_drawing_ClosedBezierShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + sUNO_service_drawing_FillProperties, + + sUNO_service_drawing_PolyPolygonBezierDescriptor, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_FreeFillServices; + } + + case SdrObjKind::OutlineText: + case SdrObjKind::TitleText: + case SdrObjKind::Text: + { + static const uno::Sequence<OUString> aSvxShape_TextServices + = { sUNO_service_drawing_TextShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_FillProperties, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_TextServices; + } + + case SdrObjKind::Graphic: + { + static const uno::Sequence<OUString> aSvxShape_GrafServices + = { sUNO_service_drawing_GraphicObjectShape, + + sUNO_service_drawing_Shape, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor}; + return aSvxShape_GrafServices; + } + + case SdrObjKind::OLE2: + { + static const uno::Sequence<OUString> aSvxShape_Ole2Services + = { sUNO_service_drawing_OLE2Shape, + sUNO_service_drawing_Shape, + + // #i118485# Added Text, Shadow and Rotation + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_Ole2Services; + } + + case SdrObjKind::Caption: + { + static const uno::Sequence<OUString> aSvxShape_CaptionServices + = { sUNO_service_drawing_CaptionShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_FillProperties, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_CaptionServices; + } + + case SdrObjKind::Page: + { + static const uno::Sequence<OUString> aSvxShape_PageServices + = { sUNO_service_drawing_PageShape, + sUNO_service_drawing_Shape }; + return aSvxShape_PageServices; + } + + case SdrObjKind::Measure: + { + static const uno::Sequence<OUString> aSvxShape_MeasureServices + = { sUNO_service_drawing_MeasureShape, + + sUNO_service_drawing_MeasureProperties, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_PolyPolygonDescriptor, + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_MeasureServices; + } + + case SdrObjKind::OLEPluginFrame: + { + static const uno::Sequence<OUString> aSvxShape_FrameServices + = { sUNO_service_drawing_FrameShape, + sUNO_service_drawing_Shape }; + return aSvxShape_FrameServices; + } + + case SdrObjKind::UNO: + { + static const uno::Sequence<OUString> aSvxShape_UnoServices + = { sUNO_service_drawing_ControlShape, + sUNO_service_drawing_Shape }; + return aSvxShape_UnoServices; + } + + case SdrObjKind::Edge: + { + static const uno::Sequence<OUString> aSvxShape_EdgeServices + = { sUNO_service_drawing_ConnectorShape, + sUNO_service_drawing_ConnectorProperties, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_PolyPolygonDescriptor, + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor }; + return aSvxShape_EdgeServices; + } + case SdrObjKind::Media: + { + static const uno::Sequence<OUString> aSvxShape_MediaServices + = { sUNO_service_drawing_MediaShape, + sUNO_service_drawing_Shape }; + return aSvxShape_MediaServices; + } + default: ; + } + } + else if( HasSdrObject() && GetSdrObject()->GetObjInventor() == SdrInventor::FmForm) + { +#if OSL_DEBUG_LEVEL > 0 + const SdrObjKind nIdent = GetSdrObject()->GetObjIdentifier(); + OSL_ENSURE( nIdent == SdrObjKind::UNO, "SvxShape::_getSupportedServiceNames: SdrInventor::FmForm, but no UNO object?" ); +#endif + static const uno::Sequence<OUString> aSvxShape_UnoServices + = { sUNO_service_drawing_ControlShape, + sUNO_service_drawing_Shape }; + return aSvxShape_UnoServices; + } + OSL_FAIL( "SvxShape::_getSupportedServiceNames: could not determine object type!" ); + uno::Sequence< OUString > aSeq; + return aSeq; +} + +sal_Bool SAL_CALL SvxShape::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +// XGluePointsSupplier +uno::Reference< container::XIndexContainer > SAL_CALL SvxShape::getGluePoints() +{ + ::SolarMutexGuard aGuard; + uno::Reference< container::XIndexContainer > xGluePoints( mxGluePoints ); + + if( HasSdrObject() && !xGluePoints.is() ) + { + uno::Reference< container::XIndexContainer > xNew( SvxUnoGluePointAccess_createInstance( GetSdrObject() ), uno::UNO_QUERY ); + mxGluePoints = xGluePoints = xNew; + } + + return xGluePoints; +} + +// XChild +uno::Reference<uno::XInterface> SAL_CALL SvxShape::getParent() +{ + ::SolarMutexGuard aGuard; + const SdrObject* pSdrObject(GetSdrObject()); + + if(nullptr != pSdrObject) + { + const SdrObjList* pParentSdrObjList(GetSdrObject()->getParentSdrObjListFromSdrObject()); + + if(nullptr != pParentSdrObjList) + { + // SdrObject is member of a SdrObjList. That may be a SdrObject + // (SdrObjGroup or E3dScene) or a SdrPage. + // Check for SdrObject first - using getSdrPageFromSdrObjList + // *will* get the SdrPage even when the SdrObject is deep buried + // in a construct of SdrObjGroup. + // We want to ask for the direct parent here... + SdrObject* pParentSdrObject(pParentSdrObjList->getSdrObjectFromSdrObjList()); + + if(nullptr != pParentSdrObject) + { + // SdrObject is member of a SdrObject-based Group (SdrObjGroup or E3dScene). + return pParentSdrObject->getUnoShape(); + } + else + { + SdrPage* pParentSdrPage(pParentSdrObjList->getSdrPageFromSdrObjList()); + + if(nullptr != pParentSdrPage) + { + // SdrObject is inserted to a SdrPage. Since + // we checked for getSdrObjectFromSdrObjList first, + // we can even say that it is directly member of that + // SdrPage. + return pParentSdrPage->getUnoPage(); + } + } + + // not member of any SdrObjList, no parent + OSL_FAIL( "SvxShape::getParent( ): unexpected Parent SdrObjList" ); + } + } + + // no SdrObject, no parent + return uno::Reference<uno::XInterface>(); +} + +void SAL_CALL SvxShape::setParent( const css::uno::Reference< css::uno::XInterface >& ) +{ + throw lang::NoSupportException(); +} + + +/** called from the XActionLockable interface methods on initial locking */ +void SvxShape::lock() +{ +} + + +/** called from the XActionLockable interface methods on final unlock */ +void SvxShape::unlock() +{ +} + + +// XActionLockable +sal_Bool SAL_CALL SvxShape::isActionLocked( ) +{ + ::SolarMutexGuard aGuard; + + return mnLockCount != 0; +} + + +void SAL_CALL SvxShape::addActionLock( ) +{ + ::SolarMutexGuard aGuard; + + DBG_ASSERT( mnLockCount < 0xffff, "lock overflow in SvxShape!" ); + mnLockCount++; + + if( mnLockCount == 1 ) + lock(); +} + + +void SAL_CALL SvxShape::removeActionLock( ) +{ + ::SolarMutexGuard aGuard; + + DBG_ASSERT( mnLockCount > 0, "lock underflow in SvxShape!" ); + mnLockCount--; + + if( mnLockCount == 0 ) + unlock(); +} + + +void SAL_CALL SvxShape::setActionLocks( sal_Int16 nLock ) +{ + ::SolarMutexGuard aGuard; + + if( (mnLockCount == 0) && (nLock != 0) ) + unlock(); + + if( (mnLockCount != 0) && (nLock == 0) ) + lock(); + + mnLockCount = static_cast<sal_uInt16>(nLock); +} + + +sal_Int16 SAL_CALL SvxShape::resetActionLocks( ) +{ + ::SolarMutexGuard aGuard; + + if( mnLockCount != 0 ) + unlock(); + + sal_Int16 nOldLocks = static_cast<sal_Int16>(mnLockCount); + mnLockCount = 0; + + return nOldLocks; +} + + +/** since polygon shapes can change their kind during editing, we have + to recheck it here. + Circle shapes also change their kind, but they are all treated equal + so no update is necessary. +*/ +void SvxShape::updateShapeKind() +{ + switch( mpImpl->mnObjId ) + { + case SdrObjKind::Line: + case SdrObjKind::Polygon: + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::PathFill: + case SdrObjKind::FreehandLine: + case SdrObjKind::FreehandFill: + case SdrObjKind::PathPoly: + case SdrObjKind::PathPolyLine: + { + const SdrObjKind nId = GetSdrObject()->GetObjIdentifier(); + + if( nId != mpImpl->mnObjId ) + { + mpImpl->mnObjId = nId; + + } + break; + } + default: ; + } +} + +SvxShapeText::SvxShapeText(SdrObject* pObject) +: SvxShape( pObject, getSvxMapProvider().GetMap(SVXMAP_TEXT), getSvxMapProvider().GetPropertySet(SVXMAP_TEXT, SdrObject::GetGlobalDrawObjectItemPool()) ), SvxUnoTextBase( ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() ) +{ + if( pObject ) + SetEditSource( new SvxTextEditSource( pObject, nullptr ) ); +} + + +SvxShapeText::SvxShapeText(SdrObject* pObject, const SfxItemPropertyMapEntry* pPropertyMap, const SvxItemPropertySet* pPropertySet) +: SvxShape( pObject, pPropertyMap, pPropertySet ), SvxUnoTextBase( ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() ) +{ + if( pObject ) + SetEditSource( new SvxTextEditSource( pObject, nullptr ) ); +} + + +SvxShapeText::~SvxShapeText() noexcept +{ + // check if only this instance is registered at the ranges + DBG_ASSERT( (nullptr == GetEditSource()) || (GetEditSource()->getRanges().size()==1), + "svx::SvxShapeText::~SvxShapeText(), text shape with living text ranges destroyed!"); +} + +void SvxShapeText::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) +{ + if( pNewObj && (nullptr == GetEditSource())) + SetEditSource( new SvxTextEditSource( pNewObj, nullptr ) ); + SvxShape::Create( pNewObj, pNewPage ); +} + +// XInterface + +uno::Any SAL_CALL SvxShapeText::queryInterface( const uno::Type & rType ) +{ + return SvxShape::queryInterface( rType ); +} + + +uno::Any SAL_CALL SvxShapeText::queryAggregation( const uno::Type & rType ) +{ + uno::Any aAny( SvxShape::queryAggregation( rType ) ); + if( aAny.hasValue() ) + return aAny; + + return SvxUnoTextBase::queryAggregation( rType ); +} + + +// XServiceInfo + +OUString SAL_CALL SvxShapeText::getImplementationName() +{ + return "SvxShapeText"; +} + + +uno::Sequence< OUString > SAL_CALL SvxShapeText::getSupportedServiceNames() +{ + return SvxShape::getSupportedServiceNames(); +} + + +sal_Bool SAL_CALL SvxShapeText::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(static_cast<SvxShape*>(this), ServiceName); +} + + // XTypeProvider + +uno::Sequence< uno::Type > SAL_CALL SvxShapeText::getTypes() +{ + return SvxShape::getTypes(); +} + +sal_Int64 SAL_CALL SvxShapeText::getSomething( const css::uno::Sequence< sal_Int8 >& rId ) +{ + const sal_Int64 nReturn = SvxShape::getSomething( rId ); + if( nReturn ) + return nReturn; + + return SvxUnoTextBase::getSomething( rId ); +} + + +uno::Sequence< sal_Int8 > SAL_CALL SvxShapeText::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + + +/** called from the XActionLockable interface methods on initial locking */ +void SvxShapeText::lock() +{ + SvxTextEditSource* pEditSource = static_cast<SvxTextEditSource*>(GetEditSource()); + if( pEditSource ) + pEditSource->lock(); +} + + +/** called from the XActionLockable interface methods on final unlock */ +void SvxShapeText::unlock() +{ + SvxTextEditSource* pEditSource = static_cast<SvxTextEditSource*>(GetEditSource()); + if( pEditSource ) + pEditSource->unlock(); +} + +// css::text::XTextRange +uno::Reference< text::XTextRange > SAL_CALL SvxShapeText::getStart() +{ + ::SolarMutexGuard aGuard; + SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; + if( pForwarder ) + ::GetSelection( maSelection, pForwarder ); + return SvxUnoTextBase::getStart(); + +} + +uno::Reference< text::XTextRange > SAL_CALL SvxShapeText::getEnd() +{ + ::SolarMutexGuard aGuard; + SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; + if( pForwarder ) + ::GetSelection( maSelection, pForwarder ); + return SvxUnoTextBase::getEnd(); +} + +OUString SAL_CALL SvxShapeText::getString() +{ + ::SolarMutexGuard aGuard; + SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; + if( pForwarder ) + ::GetSelection( maSelection, pForwarder ); + return SvxUnoTextBase::getString(); +} + + +void SAL_CALL SvxShapeText::setString( const OUString& aString ) +{ + ::SolarMutexGuard aGuard; + SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; + if( pForwarder ) + ::GetSelection( maSelection, pForwarder ); + SvxUnoTextBase::setString( aString ); +} + +// override these for special property handling in subcasses. Return true if property is handled +bool SvxShapeText::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) +{ + // HACK-fix #99090# + // since SdrTextObj::SetVerticalWriting exchanges + // SDRATTR_TEXT_AUTOGROWWIDTH and SDRATTR_TEXT_AUTOGROWHEIGHT, + // we have to set the textdirection here + + if( pProperty->nWID == SDRATTR_TEXTDIRECTION ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( GetSdrObject() ); + if( pTextObj ) + { + css::text::WritingMode eMode; + if( rValue >>= eMode ) + { + pTextObj->SetVerticalWriting( eMode == css::text::WritingMode_TB_RL ); + } + } + return true; + } + return SvxShape::setPropertyValueImpl( rName, pProperty, rValue ); +} + +bool SvxShapeText::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) +{ + if( pProperty->nWID == SDRATTR_TEXTDIRECTION ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( GetSdrObject() ); + if( pTextObj && pTextObj->IsVerticalWriting() ) + rValue <<= css::text::WritingMode_TB_RL; + else + rValue <<= css::text::WritingMode_LR_TB; + return true; + } + + return SvxShape::getPropertyValueImpl( rName, pProperty, rValue ); +} + +bool SvxShapeText::getPropertyStateImpl( const SfxItemPropertyMapEntry* pProperty, css::beans::PropertyState& rState ) +{ + return SvxShape::getPropertyStateImpl( pProperty, rState ); +} + +bool SvxShapeText::setPropertyToDefaultImpl( const SfxItemPropertyMapEntry* pProperty ) +{ + return SvxShape::setPropertyToDefaultImpl( pProperty ); +} + +SvxShapeRect::SvxShapeRect(SdrObject* pObj) +: SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_SHAPE), getSvxMapProvider().GetPropertySet(SVXMAP_SHAPE, SdrObject::GetGlobalDrawObjectItemPool())) +{ +} + +SvxShapeRect::~SvxShapeRect() noexcept +{ +} + +uno::Any SAL_CALL SvxShapeRect::queryInterface( const uno::Type & rType ) +{ + return SvxShapeText::queryInterface( rType ); +} + +uno::Any SAL_CALL SvxShapeRect::queryAggregation( const uno::Type & rType ) +{ + return SvxShapeText::queryAggregation( rType ); +} + +// XServiceInfo + +uno::Sequence< OUString > SvxShapeRect::getSupportedServiceNames() +{ + return SvxShape::getSupportedServiceNames(); +} + +/** returns a StarOffice API wrapper for the given SdrObject */ +uno::Reference< drawing::XShape > GetXShapeForSdrObject( SdrObject* pObj ) noexcept +{ + uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY ); + return xShape; +} + + +SdrObject* SdrObject::getSdrObjectFromXShape( const css::uno::Reference< css::uno::XInterface >& xInt ) +{ + SvxShape* pSvxShape = comphelper::getFromUnoTunnel<SvxShape>( xInt ); + return pSvxShape ? pSvxShape->GetSdrObject() : nullptr; +} + +uno::Any SvxItemPropertySet_getPropertyValue( const SfxItemPropertyMapEntry* pMap, const SfxItemSet& rSet ) +{ + if(!pMap || !pMap->nWID) + return uno::Any(); + + // Check is for items that store either metric values if they are positive or percentage if they are negative. + bool bDontConvertNegativeValues = ( pMap->nWID == XATTR_FILLBMP_SIZEX || pMap->nWID == XATTR_FILLBMP_SIZEY ); + return SvxItemPropertySet::getPropertyValue( pMap, rSet, (pMap->nWID != SDRATTR_XMLATTRIBUTES), bDontConvertNegativeValues ); +} + +void SvxItemPropertySet_setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rVal, SfxItemSet& rSet ) +{ + if(!pMap || !pMap->nWID) + return; + + bool bDontConvertNegativeValues = ( pMap->nWID == XATTR_FILLBMP_SIZEX || pMap->nWID == XATTR_FILLBMP_SIZEY ); + SvxItemPropertySet::setPropertyValue( pMap, rVal, rSet, bDontConvertNegativeValues ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoshcol.cxx b/svx/source/unodraw/unoshcol.cxx new file mode 100644 index 000000000..105ca6523 --- /dev/null +++ b/svx/source/unodraw/unoshcol.cxx @@ -0,0 +1,252 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/document/EventObject.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <comphelper/interfacecontainer3.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <osl/mutex.hxx> +#include <sal/log.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace { + +class SvxShapeCollection : + public cppu::BaseMutex, + public cppu::WeakAggImplHelper3<drawing::XShapes, lang::XServiceInfo, lang::XComponent> +{ +private: + comphelper::OInterfaceContainerHelper3<drawing::XShape> maShapeContainer; + + cppu::OBroadcastHelper mrBHelper; + +public: + SvxShapeCollection() noexcept; + + // XInterface + virtual void SAL_CALL release() noexcept override; + + // XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; + + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount() override ; + virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override; + + // XElementAccess + virtual css::uno::Type SAL_CALL getElementType() override; + virtual sal_Bool SAL_CALL hasElements() override; + + // XShapes + virtual void SAL_CALL add( const css::uno::Reference< css::drawing::XShape >& xShape ) override; + virtual void SAL_CALL remove( const css::uno::Reference< css::drawing::XShape >& xShape ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +SvxShapeCollection::SvxShapeCollection() noexcept +: maShapeContainer( m_aMutex ), mrBHelper( m_aMutex ) +{ +} + +// XInterface +void SvxShapeCollection::release() noexcept +{ + uno::Reference< uno::XInterface > x( xDelegator ); + if (! x.is()) + { + if (osl_atomic_decrement( &m_refCount ) == 0) + { + if (! mrBHelper.bDisposed) + { + uno::Reference< uno::XInterface > xHoldAlive( static_cast<uno::XWeak*>(this) ); + // First dispose + try + { + dispose(); + } + catch(css::uno::Exception&) + { + // release should not throw exceptions + } + + // only the alive ref holds the object + OSL_ASSERT( m_refCount == 1 ); + // destroy the object if xHoldAlive decrement the refcount to 0 + return; + } + } + // restore the reference count + osl_atomic_increment( &m_refCount ); + } + OWeakAggObject::release(); +} + +// XComponent +void SvxShapeCollection::dispose() +{ + // An frequently programming error is to release the last + // reference to this object in the disposing message. + // Make it robust, hold a self Reference. + uno::Reference< lang::XComponent > xSelf( this ); + + // Guard dispose against multiple threading + // Remark: It is an error to call dispose more than once + bool bDoDispose = false; + { + osl::MutexGuard aGuard( mrBHelper.rMutex ); + if( !mrBHelper.bDisposed && !mrBHelper.bInDispose ) + { + // only one call go into this section + mrBHelper.bInDispose = true; + bDoDispose = true; + } + } + + // Do not hold the mutex because we are broadcasting + if( bDoDispose ) + { + // Create an event with this as sender + try + { + uno::Reference< uno::XInterface > xSource( uno::Reference< uno::XInterface >::query( static_cast<lang::XComponent *>(this) ) ); + document::EventObject aEvt; + aEvt.Source = xSource; + // inform all listeners to release this object + // The listener container are automatically cleared + mrBHelper.aLC.disposeAndClear( aEvt ); + maShapeContainer.clear(); + } + catch(const css::uno::Exception&) + { + // catch exception and throw again but signal that + // the object was disposed. Dispose should be called + // only once. + mrBHelper.bDisposed = true; + mrBHelper.bInDispose = false; + throw; + } + + // the values bDispose and bInDisposing must set in this order. + // No multithread call overcome the "!rBHelper.bDisposed && !rBHelper.bInDispose" guard. + mrBHelper.bDisposed = true; + mrBHelper.bInDispose = false; + } + else + { + // in a multithreaded environment, it can't be avoided, that dispose is called twice. + // However this condition is traced, because it MAY indicate an error. + SAL_INFO("svx", "dispose called twice" ); + } +} + +// XComponent +void SAL_CALL SvxShapeCollection::addEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) +{ + mrBHelper.addListener( cppu::UnoType<decltype(aListener)>::get() , aListener ); +} + +// XComponent +void SAL_CALL SvxShapeCollection::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) +{ + mrBHelper.removeListener( cppu::UnoType<decltype(aListener)>::get() , aListener ); +} + +// XShapes + +void SAL_CALL SvxShapeCollection::add( const Reference< drawing::XShape >& xShape ) +{ + maShapeContainer.addInterface( xShape ); +} + + +void SAL_CALL SvxShapeCollection::remove( const uno::Reference< drawing::XShape >& xShape ) +{ + maShapeContainer.removeInterface( xShape ); +} + + +sal_Int32 SAL_CALL SvxShapeCollection::getCount() +{ + return maShapeContainer.getLength(); +} + + +uno::Any SAL_CALL SvxShapeCollection::getByIndex( sal_Int32 Index ) +{ + if( Index < 0 || Index >= getCount() ) + throw lang::IndexOutOfBoundsException(); + + Reference<drawing::XShape> xShape = maShapeContainer.getInterface(Index); + return uno::Any( xShape ); +} + +// XElementAccess +uno::Type SAL_CALL SvxShapeCollection::getElementType() +{ + return cppu::UnoType<drawing::XShape>::get(); +} + +sal_Bool SAL_CALL SvxShapeCollection::hasElements() +{ + return getCount() != 0; +} + +// XServiceInfo +OUString SAL_CALL SvxShapeCollection::getImplementationName() +{ + return "com.sun.star.drawing.SvxShapeCollection"; +} + +sal_Bool SAL_CALL SvxShapeCollection::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL SvxShapeCollection::getSupportedServiceNames() +{ + return { "com.sun.star.drawing.Shapes", "com.sun.star.drawing.ShapeCollection" }; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_drawing_SvxShapeCollection_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SvxShapeCollection); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unoshtxt.cxx b/svx/source/unodraw/unoshtxt.cxx new file mode 100644 index 000000000..71e63997e --- /dev/null +++ b/svx/source/unodraw/unoshtxt.cxx @@ -0,0 +1,1009 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <memory> + +#include <vcl/svapp.hxx> + +#include <svx/unoshtxt.hxx> +#include <editeng/unoedhlp.hxx> +#include <svl/lstner.hxx> +#include <rtl/ref.hxx> +#include <tools/debug.hxx> +#include <svl/hint.hxx> +#include <svl/style.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdview.hxx> +#include <editeng/outliner.hxx> +#include <editeng/unoforou.hxx> +#include <editeng/unoviwou.hxx> +#include <editeng/outlobj.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdpage.hxx> +#include <editeng/editeng.hxx> + +#include <editeng/unotext.hxx> +#include <com/sun/star/linguistic2/LinguServiceManager.hpp> +#include <comphelper/processfactory.hxx> +#include <svx/svdotable.hxx> +#include <cell.hxx> +#include <unotools/configmgr.hxx> + + +// SvxTextEditSourceImpl + + +/** @descr + <p>This class essentially provides the text and view forwarders. If + no SdrView is given, this class handles the UNO objects, which are + currently not concerned with view issues. In this case, + GetViewForwarder() always returns NULL and the underlying + EditEngine of the SvxTextForwarder is a background one (i.e. not + the official DrawOutliner, but one created exclusively for this + object, with no relation to a view). + </p> + + <p>If a SdrView is given at construction time, the caller is + responsible for destroying this object when the view becomes + invalid (the views cannot notify). If GetViewForwarder(sal_True) + is called, the underlying shape is put into edit mode, the view + forwarder returned encapsulates the OutlinerView and the next call + to GetTextForwarder() yields a forwarder encapsulating the actual + DrawOutliner. Thus, changes on that Outliner are immediately + reflected on the screen. If the object leaves edit mode, the old + behaviour is restored.</p> + */ +class SvxTextEditSourceImpl : public SfxListener, public SfxBroadcaster, public sdr::ObjectUser +{ +private: + oslInterlockedCount maRefCount; + + SdrObject* mpObject; // TTTT could be reference (?) + SdrText* mpText; + SdrView* mpView; + VclPtr<const OutputDevice> mpWindow; + SdrModel* mpModel; // TTTT probably not needed -> use SdrModel from SdrObject (?) + std::unique_ptr<SdrOutliner> mpOutliner; + std::unique_ptr<SvxOutlinerForwarder> mpTextForwarder; + std::unique_ptr<SvxDrawOutlinerViewForwarder> mpViewForwarder; // if non-NULL, use GetViewModeTextForwarder text forwarder + css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager; + Point maTextOffset; + bool mbDataValid; + bool mbIsLocked; + bool mbNeedsUpdate; + bool mbOldUndoMode; + bool mbForwarderIsEditMode; // have to reflect that, since ENDEDIT can happen more often + bool mbShapeIsEditMode; // only true, if SdrHintKind::BeginEdit was received + bool mbNotificationsDisabled; // prevent EditEngine/Outliner notifications (e.g. when setting up forwarder) + bool mbNotifyEditOutlinerSet; + + SvxUnoTextRangeBaseVec mvTextRanges; + + SvxTextForwarder* GetBackgroundTextForwarder(); + SvxTextForwarder* GetEditModeTextForwarder(); + std::unique_ptr<SvxDrawOutlinerViewForwarder> CreateViewForwarder(); + + void SetupOutliner(); + + bool HasView() const { return mpView != nullptr; } + bool IsEditMode() const + { + if (!mbShapeIsEditMode) + return false; + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + return pTextObj && pTextObj->IsTextEditActive(); + } + + void dispose(); + +public: + SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText ); + SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const OutputDevice& rWindow ); + virtual ~SvxTextEditSourceImpl() override; + + void acquire(); + void release(); + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + + SvxTextForwarder* GetTextForwarder(); + SvxEditViewForwarder* GetEditViewForwarder( bool ); + void UpdateData(); + + void addRange( SvxUnoTextRangeBase* pNewRange ); + void removeRange( SvxUnoTextRangeBase* pOldRange ); + const SvxUnoTextRangeBaseVec& getRanges() const { return mvTextRanges;} + + void lock(); + void unlock(); + + bool IsValid() const; + + Point LogicToPixel( const Point&, const MapMode& rMapMode ); + Point PixelToLogic( const Point&, const MapMode& rMapMode ); + + DECL_LINK( NotifyHdl, EENotify&, void ); + + virtual void ObjectInDestruction(const SdrObject& rObject) override; + + void UpdateOutliner(); +}; + + +SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText ) + : maRefCount ( 0 ), + mpObject ( pObject ), + mpText ( pText ), + mpView ( nullptr ), + mpWindow ( nullptr ), + mpModel ( pObject ? &pObject->getSdrModelFromSdrObject() : nullptr ), // TTTT should be reference + mbDataValid ( false ), + mbIsLocked ( false ), + mbNeedsUpdate ( false ), + mbOldUndoMode ( false ), + mbForwarderIsEditMode ( false ), + mbShapeIsEditMode ( false ), + mbNotificationsDisabled ( false ), + mbNotifyEditOutlinerSet ( false ) +{ + DBG_ASSERT( mpObject, "invalid pObject!" ); + + if( !mpText ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject ); + if( pTextObj ) + mpText = pTextObj->getText( 0 ); + } + + if( mpModel ) + StartListening( *mpModel ); + + if( mpObject ) + mpObject->AddObjectUser( *this ); +} + + +SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const OutputDevice& rWindow ) + : maRefCount ( 0 ), + mpObject ( &rObject ), + mpText ( pText ), + mpView ( &rView ), + mpWindow ( &rWindow ), + mpModel ( &rObject.getSdrModelFromSdrObject() ), // TTTT should be reference + mbDataValid ( false ), + mbIsLocked ( false ), + mbNeedsUpdate ( false ), + mbOldUndoMode ( false ), + mbForwarderIsEditMode ( false ), + mbShapeIsEditMode ( true ), + mbNotificationsDisabled ( false ), + mbNotifyEditOutlinerSet ( false ) +{ + if( !mpText ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject ); + if( pTextObj ) + mpText = pTextObj->getText( 0 ); + } + + StartListening( *mpModel ); + StartListening( *mpView ); + mpObject->AddObjectUser( *this ); + + // Init edit mode state from shape info (IsTextEditActive()) + mbShapeIsEditMode = IsEditMode(); +} + + +SvxTextEditSourceImpl::~SvxTextEditSourceImpl() +{ + DBG_ASSERT( !mbIsLocked, "text edit source was not unlocked before dispose!" ); + if( mpObject ) + mpObject->RemoveObjectUser( *this ); + + dispose(); +} + + +void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase* pNewRange ) +{ + if( pNewRange ) + if( std::find( mvTextRanges.begin(), mvTextRanges.end(), pNewRange ) == mvTextRanges.end() ) + mvTextRanges.push_back( pNewRange ); +} + + +void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange ) +{ + if( pOldRange ) + mvTextRanges.erase( std::remove(mvTextRanges.begin(), mvTextRanges.end(), pOldRange), mvTextRanges.end() ); +} + + +void SvxTextEditSourceImpl::acquire() +{ + osl_atomic_increment( &maRefCount ); +} + + +void SvxTextEditSourceImpl::release() +{ + if( ! osl_atomic_decrement( &maRefCount ) ) + delete this; +} + +void SvxTextEditSourceImpl::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + // #i105988 keep reference to this object + rtl::Reference< SvxTextEditSourceImpl > xThis( this ); + + if (SfxHintId::Dying == rHint.GetId()) + { + if (&rBC == mpView) + { + mpView = nullptr; + mpViewForwarder.reset(); + } + } + else if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint) + { + const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); + switch( pSdrHint->GetKind() ) + { + case SdrHintKind::ObjectChange: + { + mbDataValid = false; // Text has to be get again + + if( HasView() ) + { + // Update maTextOffset, object has changed + // Cannot call that here, since TakeTextRect() (called from there) + // changes outliner content. + // UpdateOutliner(); + + // Broadcast object changes, as they might change visible attributes + SvxViewChangedHint aHint; + Broadcast( aHint ); + } + break; + } + + case SdrHintKind::BeginEdit: + if( mpObject == pSdrHint->GetObject() ) + { + // Once SdrHintKind::BeginEdit is broadcast, each EditSource of + // AccessibleCell will handle it here and call below: + // mpView->GetTextEditOutliner()->SetNotifyHdl(), which + // will replace the Notifier for current editable cell. It + // is totally wrong. So add check here to avoid the + // incorrect replacement of notifier. + + // Currently it only happens on the editsource of + // AccessibleCell + if (mpObject && mpText) + { + sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mpObject ); + if(pTableObj) + { + const sdr::table::CellRef& xCell = pTableObj->getActiveCell(); + if (xCell.is()) + { + sdr::table::Cell* pCellObj = dynamic_cast< sdr::table::Cell* >( mpText ); + if (pCellObj && xCell.get() != pCellObj) + break; + } + } + } + // invalidate old forwarder + if( !mbForwarderIsEditMode ) + { + mpTextForwarder.reset(); + } + + // register as listener - need to broadcast state change messages + if( mpView && mpView->GetTextEditOutliner() ) + { + mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) ); + mbNotifyEditOutlinerSet = true; + } + + // Only now we're really in edit mode + mbShapeIsEditMode = true; + + Broadcast( *pSdrHint ); + } + break; + + case SdrHintKind::EndEdit: + if( mpObject == pSdrHint->GetObject() ) + { + Broadcast( *pSdrHint ); + + // We're no longer in edit mode + mbShapeIsEditMode = false; + + // remove as listener - outliner might outlive ourselves + if( mpView && mpView->GetTextEditOutliner() ) + { + mpView->GetTextEditOutliner()->SetNotifyHdl( Link<EENotify&,void>() ); + mbNotifyEditOutlinerSet = false; + } + + // destroy view forwarder, OutlinerView no longer + // valid (no need for UpdateData(), it's been + // synched on SdrEndTextEdit) + mpViewForwarder.reset(); + + // Invalidate text forwarder, we might + // not be called again before entering edit mode a + // second time! Then, the old outliner might be + // invalid. + if( mbForwarderIsEditMode ) + { + mbForwarderIsEditMode = false; + mpTextForwarder.reset(); + } + } + break; + + case SdrHintKind::ModelCleared: + dispose(); + break; + default: + break; + } + } + else if (const SvxViewChangedHint* pViewHint = dynamic_cast<const SvxViewChangedHint*>(&rHint)) + { + Broadcast( *pViewHint ); + } +} + +/* this is a callback from the attached SdrObject when it is actually deleted */ +void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject&) +{ + mpObject = nullptr; + dispose(); + Broadcast( SfxHint( SfxHintId::Dying ) ); +} + +/* unregister at all objects and set all references to 0 */ +void SvxTextEditSourceImpl::dispose() +{ + mpTextForwarder.reset(); + mpViewForwarder.reset(); + + if( mpOutliner ) + { + if( mpModel ) + { + mpModel->disposeOutliner( std::move(mpOutliner) ); + } + else + { + mpOutliner.reset(); + } + } + + if( mpModel ) + { + EndListening( *mpModel ); + mpModel = nullptr; + } + + if( mpView ) + { + // remove as listener - outliner might outlive ourselves + if (mbNotifyEditOutlinerSet && mpView->GetTextEditOutliner()) + { + mpView->GetTextEditOutliner()->SetNotifyHdl(Link<EENotify&,void>()); + mbNotifyEditOutlinerSet = false; + } + EndListening( *mpView ); + mpView = nullptr; + } + + if( mpObject ) + { + mpObject->RemoveObjectUser( *this ); + mpObject = nullptr; + } + mpWindow = nullptr; +} + + +void SvxTextEditSourceImpl::SetupOutliner() +{ + // only for UAA edit source: setup outliner equivalently as in + // SdrTextObj::Paint(), such that formatting equals screen + // layout + if( !(mpObject && mpOutliner) ) + return; + + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + if( pTextObj ) + { + tools::Rectangle aPaintRect; + tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() ); + pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect ); + + // calc text offset from shape anchor + maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft(); + } +} + + +void SvxTextEditSourceImpl::UpdateOutliner() +{ + // only for UAA edit source: update outliner equivalently as in + // SdrTextObj::Paint(), such that formatting equals screen + // layout + if( !(mpObject && mpOutliner) ) + return; + + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + if( pTextObj ) + { + tools::Rectangle aPaintRect; + tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() ); + pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect ); + + // calc text offset from shape anchor + maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft(); + } +} + + +SvxTextForwarder* SvxTextEditSourceImpl::GetBackgroundTextForwarder() +{ + bool bCreated = false; + + // prevent EE/Outliner notifications during setup + mbNotificationsDisabled = true; + + if (!mpTextForwarder) + { + if( mpOutliner == nullptr ) + { + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + OutlinerMode nOutlMode = OutlinerMode::TextObject; + if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == SdrObjKind::OutlineText ) + nOutlMode = OutlinerMode::OutlineObject; + + mpOutliner = mpModel->createOutliner( nOutlMode ); + + // Do the setup after outliner creation, would be useless otherwise + if( HasView() ) + { + // Setup outliner _before_ filling it + SetupOutliner(); + } + + mpOutliner->SetTextObjNoInit( pTextObj ); + if( mbIsLocked ) + { + const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateLayout( false ); + mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled(); + const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false ); + } + + if (!utl::ConfigManager::IsFuzzing()) + { + if ( !m_xLinguServiceManager.is() ) + { + css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + m_xLinguServiceManager.set(css::linguistic2::LinguServiceManager::create(xContext)); + } + + css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator = m_xLinguServiceManager->getHyphenator(); + if( xHyphenator.is() ) + mpOutliner->SetHyphenator( xHyphenator ); + } + } + + + mpTextForwarder.reset(new SvxOutlinerForwarder( *mpOutliner, (mpObject->GetObjInventor() == SdrInventor::Default) && (mpObject->GetObjIdentifier() == SdrObjKind::OutlineText) )); + // delay listener subscription and UAA initialization until Outliner is fully setup + bCreated = true; + + mbForwarderIsEditMode = false; + mbDataValid = false; + } + + if( mpObject && mpText && !mbDataValid && mpObject->IsInserted() && mpObject->getSdrPageFromSdrObject() ) + { + mpTextForwarder->flushCache(); + + std::optional<OutlinerParaObject> pOutlinerParaObject; + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + if( pTextObj && pTextObj->getActiveText() == mpText ) + pOutlinerParaObject = pTextObj->CreateEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active + bool bOwnParaObj(false); + + if( pOutlinerParaObject ) + bOwnParaObj = true; // text edit active + else if (mpText->GetOutlinerParaObject()) + pOutlinerParaObject = *mpText->GetOutlinerParaObject(); + + if( pOutlinerParaObject && ( bOwnParaObj || !mpObject->IsEmptyPresObj() || mpObject->getSdrPageFromSdrObject()->IsMasterPage() ) ) + { + mpOutliner->SetText( *pOutlinerParaObject ); + + // put text to object and set EmptyPresObj to FALSE + if( mpText && bOwnParaObj && mpObject->IsEmptyPresObj() && pTextObj->IsReallyEdited() ) + { + mpObject->SetEmptyPresObj( false ); + static_cast< SdrTextObj* >( mpObject)->NbcSetOutlinerParaObjectForText( pOutlinerParaObject, mpText ); + + // #i103982# Here, due to mpObject->NbcSetOutlinerParaObjectForText, we LOSE ownership of the + // OPO, so do NOT delete it when leaving this method (!) + bOwnParaObj = false; + } + } + else + { + bool bVertical = pOutlinerParaObject && pOutlinerParaObject->IsEffectivelyVertical(); + + // set objects style sheet on empty outliner + SfxStyleSheetPool* pPool = static_cast<SfxStyleSheetPool*>(mpObject->getSdrModelFromSdrObject().GetStyleSheetPool()); + if( pPool ) + mpOutliner->SetStyleSheetPool( pPool ); + + SfxStyleSheet* pStyleSheet = mpObject->getSdrPageFromSdrObject()->GetTextStyleSheetForObject( mpObject ); + if( pStyleSheet ) + mpOutliner->SetStyleSheet( 0, pStyleSheet ); + + if( bVertical ) + { + mpOutliner->SetVertical( pOutlinerParaObject->GetVertical()); + mpOutliner->SetRotation( pOutlinerParaObject->GetRotation()); + } + } + + // maybe we have to set the border attributes + if (mpOutliner->GetParagraphCount()==1) + { + // if we only have one paragraph we check if it is empty + OUString aStr(mpOutliner->GetText(mpOutliner->GetParagraph(0))); + + if (aStr.isEmpty()) + { + // its empty, so we have to force the outliner to initialise itself + mpOutliner->SetText( "", mpOutliner->GetParagraph( 0 ) ); + + if(mpObject->GetStyleSheet()) + mpOutliner->SetStyleSheet( 0, mpObject->GetStyleSheet()); + } + } + + mbDataValid = true; + } + + if( bCreated && mpOutliner && HasView() ) + { + // register as listener - need to broadcast state change messages + // registration delayed until outliner is completely set up + mpOutliner->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) ); + } + + // prevent EE/Outliner notifications during setup + mbNotificationsDisabled = false; + + return mpTextForwarder.get(); +} + + +SvxTextForwarder* SvxTextEditSourceImpl::GetEditModeTextForwarder() +{ + if( !mpTextForwarder && HasView() ) + { + SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner(); + + if( pEditOutliner ) + { + mpTextForwarder.reset(new SvxOutlinerForwarder( *pEditOutliner, (mpObject->GetObjInventor() == SdrInventor::Default) && (mpObject->GetObjIdentifier() == SdrObjKind::OutlineText) )); + mbForwarderIsEditMode = true; + } + } + + return mpTextForwarder.get(); +} + + +SvxTextForwarder* SvxTextEditSourceImpl::GetTextForwarder() +{ + if( mpObject == nullptr ) + return nullptr; + + if( mpModel == nullptr ) + mpModel = &mpObject->getSdrModelFromSdrObject(); + + // distinguish the cases + // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner + // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code) + if( HasView() ) + { + if( IsEditMode() != mbForwarderIsEditMode ) + { + // forwarder mismatch - create new + mpTextForwarder.reset(); + } + + if( IsEditMode() ) + return GetEditModeTextForwarder(); + else + return GetBackgroundTextForwarder(); + } + else + { + // tdf#123470 if the text edit mode of the shape is active, then we + // cannot trust a previously cached TextForwarder state as the text may + // be out of date, so force a refetch in that case, unless locked against + // changes + if (IsEditMode() && mpTextForwarder && !mbIsLocked) + { + assert(!mbForwarderIsEditMode); // because without a view there is no other option except !mbForwarderIsEditMode + bool bTextEditActive = false; + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(mpObject); + // similar to the GetBackgroundTextForwarder check, see if the text edit is active + if (pTextObj && pTextObj->getActiveText() == mpText && pTextObj->CanCreateEditOutlinerParaObject()) + bTextEditActive = true; // text edit active + if (bTextEditActive) + mbDataValid = false; + } + + return GetBackgroundTextForwarder(); + } +} + +std::unique_ptr<SvxDrawOutlinerViewForwarder> SvxTextEditSourceImpl::CreateViewForwarder() +{ + if( mpView->GetTextEditOutlinerView() && mpObject ) + { + // register as listener - need to broadcast state change messages + mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) ); + mbNotifyEditOutlinerSet = true; + + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + if( pTextObj ) + { + tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() ); + OutlinerView& rOutlView = *mpView->GetTextEditOutlinerView(); + + return std::unique_ptr<SvxDrawOutlinerViewForwarder>(new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() )); + } + } + + return nullptr; +} + +SvxEditViewForwarder* SvxTextEditSourceImpl::GetEditViewForwarder( bool bCreate ) +{ + if( mpObject == nullptr ) + return nullptr; + + if( mpModel == nullptr ) + mpModel = &mpObject->getSdrModelFromSdrObject(); + + // shall we delete? + if( mpViewForwarder ) + { + if( !IsEditMode() ) + { + // destroy all forwarders (no need for UpdateData(), + // it's been synched on SdrEndTextEdit) + mpViewForwarder.reset(); + } + } + // which to create? Directly in edit mode, create new, or none? + else if( mpView ) + { + if( IsEditMode() ) + { + // create new view forwarder + mpViewForwarder = CreateViewForwarder(); + } + else if( bCreate ) + { + // dispose old text forwarder + UpdateData(); + + mpTextForwarder.reset(); + + // enter edit mode + mpView->SdrEndTextEdit(); + + if(mpView->SdrBeginTextEdit(mpObject)) + { + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject ); + if (pTextObj && pTextObj->IsTextEditActive()) + { + // create new view forwarder + mpViewForwarder = CreateViewForwarder(); + } + else + { + // failure. Somehow, SdrBeginTextEdit did not set + // our SdrTextObj into edit mode + mpView->SdrEndTextEdit(); + } + } + } + } + + return mpViewForwarder.get(); +} + + +void SvxTextEditSourceImpl::UpdateData() +{ + // if we have a view and in edit mode, we're working with the + // DrawOutliner. Thus, all changes made on the text forwarder are + // reflected on the view and committed to the model on + // SdrEndTextEdit(). Thus, no need for explicit updates here. + if( HasView() && IsEditMode() ) + return; + + if( mbIsLocked ) + { + mbNeedsUpdate = true; + } + else + { + if( mpOutliner && mpObject && mpText ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject ); + if( pTextObj ) + { + if( (mpOutliner->GetParagraphCount() == 1 && mpOutliner->GetEditEngine().GetTextLen( 0 ) == 0 ) + || (mpOutliner->GetParagraphCount() == 2 && mpOutliner->GetEditEngine().GetTextLen( 0 ) == 0 + && mpOutliner->GetEditEngine().GetTextLen( 1 ) == 0) ) + { + pTextObj->NbcSetOutlinerParaObjectForText( std::nullopt, mpText ); + } + else + { + pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText ); + } + } + + if( mpObject->IsEmptyPresObj() ) + mpObject->SetEmptyPresObj(false); + } + } +} + +void SvxTextEditSourceImpl::lock() +{ + // if this assert ever fires, we will need to make this a counter instead of a boolean + assert(!mbIsLocked && "cannot nest these loc() calls"); + mbIsLocked = true; + if( mpOutliner ) + { + const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateLayout( false ); + mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled(); + const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false ); + } +} + +void SvxTextEditSourceImpl::unlock() +{ + mbIsLocked = false; + + if( mbNeedsUpdate ) + { + UpdateData(); + mbNeedsUpdate = false; + } + + if( mpOutliner ) + { + const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateLayout( true ); + const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode ); + } +} + +bool SvxTextEditSourceImpl::IsValid() const +{ + return mpView && mpWindow; +} + +Point SvxTextEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) +{ + // The responsibilities of ViewForwarder happen to be + // somewhat mixed in this case. On the one hand, we need the + // different interface queries on the SvxEditSource interface, + // since we need both VisAreas. On the other hand, if an + // EditViewForwarder exists, maTextOffset does not remain static, + // but may change with every key press. + if( IsEditMode() ) + { + SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false); + + if( pForwarder ) + return pForwarder->LogicToPixel( rPoint, rMapMode ); + } + else if( IsValid() && mpModel ) + { + Point aPoint1( rPoint ); + aPoint1.AdjustX(maTextOffset.X() ); + aPoint1.AdjustY(maTextOffset.Y() ); + + Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode, + MapMode(mpModel->GetScaleUnit()) ) ); + MapMode aMapMode(mpWindow->GetMapMode()); + aMapMode.SetOrigin(Point()); + return mpWindow->LogicToPixel( aPoint2, aMapMode ); + } + + return Point(); +} + +Point SvxTextEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) +{ + // The responsibilities of ViewForwarder happen to be + // somewhat mixed in this case. On the one hand, we need the + // different interface queries on the SvxEditSource interface, + // since we need both VisAreas. On the other hand, if an + // EditViewForwarder exists, maTextOffset does not remain static, + // but may change with every key press. + if( IsEditMode() ) + { + SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false); + + if( pForwarder ) + return pForwarder->PixelToLogic( rPoint, rMapMode ); + } + else if( IsValid() && mpModel ) + { + MapMode aMapMode(mpWindow->GetMapMode()); + aMapMode.SetOrigin(Point()); + Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) ); + Point aPoint2( OutputDevice::LogicToLogic( aPoint1, + MapMode(mpModel->GetScaleUnit()), + rMapMode ) ); + aPoint2.AdjustX( -(maTextOffset.X()) ); + aPoint2.AdjustY( -(maTextOffset.Y()) ); + + return aPoint2; + } + + return Point(); +} + +IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify&, rNotify, void) +{ + if( !mbNotificationsDisabled ) + { + std::unique_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( &rNotify) ); + + if (aHint) + Broadcast(*aHint); + } +} + +SvxTextEditSource::SvxTextEditSource( SdrObject* pObject, SdrText* pText ) +{ + mpImpl = new SvxTextEditSourceImpl( pObject, pText ); +} + + +SvxTextEditSource::SvxTextEditSource( SdrObject& rObj, SdrText* pText, SdrView& rView, const OutputDevice& rWindow ) +{ + mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow ); +} + + +SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl* pImpl ) +{ + mpImpl = pImpl; +} + + +SvxTextEditSource::~SvxTextEditSource() +{ + ::SolarMutexGuard aGuard; + mpImpl.clear(); +} + + +std::unique_ptr<SvxEditSource> SvxTextEditSource::Clone() const +{ + return std::unique_ptr<SvxEditSource>(new SvxTextEditSource( mpImpl.get() )); +} + + +SvxTextForwarder* SvxTextEditSource::GetTextForwarder() +{ + return mpImpl->GetTextForwarder(); +} + + +SvxEditViewForwarder* SvxTextEditSource::GetEditViewForwarder( bool bCreate ) +{ + return mpImpl->GetEditViewForwarder( bCreate ); +} + + +SvxViewForwarder* SvxTextEditSource::GetViewForwarder() +{ + return this; +} + + +void SvxTextEditSource::UpdateData() +{ + mpImpl->UpdateData(); +} + +SfxBroadcaster& SvxTextEditSource::GetBroadcaster() const +{ + return *mpImpl; +} + +void SvxTextEditSource::lock() +{ + mpImpl->lock(); +} + +void SvxTextEditSource::unlock() +{ + mpImpl->unlock(); +} + +bool SvxTextEditSource::IsValid() const +{ + return mpImpl->IsValid(); +} + +Point SvxTextEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const +{ + return mpImpl->LogicToPixel( rPoint, rMapMode ); +} + +Point SvxTextEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const +{ + return mpImpl->PixelToLogic( rPoint, rMapMode ); +} + +void SvxTextEditSource::addRange( SvxUnoTextRangeBase* pNewRange ) +{ + mpImpl->addRange( pNewRange ); +} + +void SvxTextEditSource::removeRange( SvxUnoTextRangeBase* pOldRange ) +{ + mpImpl->removeRange( pOldRange ); +} + +const SvxUnoTextRangeBaseVec& SvxTextEditSource::getRanges() const +{ + return mpImpl->getRanges(); +} + +void SvxTextEditSource::UpdateOutliner() +{ + mpImpl->UpdateOutliner(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unottabl.cxx b/svx/source/unodraw/unottabl.cxx new file mode 100644 index 000000000..6233bccb9 --- /dev/null +++ b/svx/source/unodraw/unottabl.cxx @@ -0,0 +1,85 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/awt/Gradient.hpp> +#include <svx/xflftrit.hxx> + +#include <svx/svdmodel.hxx> +#include <svx/unofill.hxx> +#include <svx/unomid.hxx> +#include "UnoNameItemTable.hxx" + +using namespace ::com::sun::star; +using namespace ::cppu; + +namespace +{ +class SvxUnoTransGradientTable : public SvxUnoNameItemTable +{ +public: + explicit SvxUnoTransGradientTable(SdrModel* pModel) noexcept; + + virtual NameOrIndex* createItem() const override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() override; +}; +} + +SvxUnoTransGradientTable::SvxUnoTransGradientTable(SdrModel* pModel) noexcept + : SvxUnoNameItemTable(pModel, XATTR_FILLFLOATTRANSPARENCE, MID_FILLGRADIENT) +{ +} + +OUString SAL_CALL SvxUnoTransGradientTable::getImplementationName() +{ + return "SvxUnoTransGradientTable"; +} + +uno::Sequence<OUString> SAL_CALL SvxUnoTransGradientTable::getSupportedServiceNames() +{ + return { "com.sun.star.drawing.TransparencyGradientTable" }; +} + +NameOrIndex* SvxUnoTransGradientTable::createItem() const +{ + XFillFloatTransparenceItem* pNewItem = new XFillFloatTransparenceItem(); + pNewItem->SetEnabled(true); + return pNewItem; +} + +// XElementAccess +uno::Type SAL_CALL SvxUnoTransGradientTable::getElementType() +{ + return cppu::UnoType<awt::Gradient>::get(); +} + +/** + * Create a hatchtable + */ +uno::Reference<uno::XInterface> SvxUnoTransGradientTable_createInstance(SdrModel* pModel) +{ + return *new SvxUnoTransGradientTable(pModel); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |