summaryrefslogtreecommitdiffstats
path: root/svx/source/xoutdev
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /svx/source/xoutdev
parentInitial commit. (diff)
downloadlibreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz
libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svx/source/xoutdev')
-rw-r--r--svx/source/xoutdev/XPropertyEntry.cxx32
-rw-r--r--svx/source/xoutdev/_xoutbmp.cxx399
-rw-r--r--svx/source/xoutdev/_xpoly.cxx948
-rw-r--r--svx/source/xoutdev/xattr.cxx3037
-rw-r--r--svx/source/xoutdev/xattr2.cxx696
-rw-r--r--svx/source/xoutdev/xattrbmp.cxx342
-rw-r--r--svx/source/xoutdev/xpool.cxx225
-rw-r--r--svx/source/xoutdev/xtabbtmp.cxx115
-rw-r--r--svx/source/xoutdev/xtabcolr.cxx174
-rw-r--r--svx/source/xoutdev/xtabdash.cxx223
-rw-r--r--svx/source/xoutdev/xtabgrdt.cxx222
-rw-r--r--svx/source/xoutdev/xtabhtch.cxx197
-rw-r--r--svx/source/xoutdev/xtable.cxx392
-rw-r--r--svx/source/xoutdev/xtablend.cxx166
-rw-r--r--svx/source/xoutdev/xtabptrn.cxx150
15 files changed, 7318 insertions, 0 deletions
diff --git a/svx/source/xoutdev/XPropertyEntry.cxx b/svx/source/xoutdev/XPropertyEntry.cxx
new file mode 100644
index 000000000..974a5bb20
--- /dev/null
+++ b/svx/source/xoutdev/XPropertyEntry.cxx
@@ -0,0 +1,32 @@
+/* -*- 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/XPropertyEntry.hxx>
+
+XPropertyEntry::XPropertyEntry(const OUString& rPropEntryName)
+: maPropEntryName(rPropEntryName),
+ maUiBitmap()
+{
+}
+
+XPropertyEntry::~XPropertyEntry()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx
new file mode 100644
index 000000000..15123e853
--- /dev/null
+++ b/svx/source/xoutdev/_xoutbmp.cxx
@@ -0,0 +1,399 @@
+/* -*- 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 <sal/log.hxx>
+
+#include <comphelper/base64.hxx>
+#include <comphelper/graphicmimetype.hxx>
+#include <tools/debug.hxx>
+#include <vcl/virdev.hxx>
+#include <sfx2/docfile.hxx>
+#include <svx/xoutbmp.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <memory>
+
+#define FORMAT_BMP "bmp"
+#define FORMAT_GIF "gif"
+#define FORMAT_JPG "jpg"
+#define FORMAT_PNG "png"
+
+using namespace com::sun::star;
+
+GraphicFilter* XOutBitmap::pGrfFilter = nullptr;
+
+Animation XOutBitmap::MirrorAnimation( const Animation& rAnimation, bool bHMirr, bool bVMirr )
+{
+ Animation aNewAnim( rAnimation );
+
+ if( bHMirr || bVMirr )
+ {
+ const Size& rGlobalSize = aNewAnim.GetDisplaySizePixel();
+ BmpMirrorFlags nMirrorFlags = BmpMirrorFlags::NONE;
+
+ if( bHMirr )
+ nMirrorFlags |= BmpMirrorFlags::Horizontal;
+
+ if( bVMirr )
+ nMirrorFlags |= BmpMirrorFlags::Vertical;
+
+ for( sal_uInt16 i = 0, nCount = aNewAnim.Count(); i < nCount; i++ )
+ {
+ AnimationBitmap aAnimationBitmap( aNewAnim.Get( i ) );
+
+ // mirror the BitmapEx
+ aAnimationBitmap.maBitmapEx.Mirror( nMirrorFlags );
+
+ // Adjust the positions inside the whole bitmap
+ if( bHMirr )
+ aAnimationBitmap.maPositionPixel.setX(rGlobalSize.Width() - aAnimationBitmap.maPositionPixel.X() -
+ aAnimationBitmap.maSizePixel.Width());
+
+ if( bVMirr )
+ aAnimationBitmap.maPositionPixel.setY(rGlobalSize.Height() - aAnimationBitmap.maPositionPixel.Y() -
+ aAnimationBitmap.maSizePixel.Height());
+
+ aNewAnim.Replace(aAnimationBitmap, i);
+ }
+ }
+
+ return aNewAnim;
+}
+
+Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const BmpMirrorFlags nMirrorFlags )
+{
+ Graphic aRetGraphic;
+
+ if( nMirrorFlags != BmpMirrorFlags::NONE )
+ {
+ if( rGraphic.IsAnimated() )
+ {
+ aRetGraphic = MirrorAnimation( rGraphic.GetAnimation(),
+ bool( nMirrorFlags & BmpMirrorFlags::Horizontal ),
+ bool( nMirrorFlags & BmpMirrorFlags::Vertical ) );
+ }
+ else
+ {
+ BitmapEx aBmp( rGraphic.GetBitmapEx() );
+ aBmp.Mirror( nMirrorFlags );
+ aRetGraphic = aBmp;
+ }
+ }
+ else
+ aRetGraphic = rGraphic;
+
+ return aRetGraphic;
+}
+
+ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
+ const OUString& rFilterName, const XOutFlags nFlags,
+ const Size* pMtfSize_100TH_MM,
+ const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
+{
+ if( rGraphic.GetType() != GraphicType::NONE )
+ {
+ INetURLObject aURL( rFileName );
+ Graphic aGraphic;
+ OUString aExt;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ ErrCode nErr = ERRCODE_GRFILTER_FILTERERROR;
+ sal_uInt16 nFilter = GRFILTER_FORMAT_NOTFOUND;
+ bool bTransparent = rGraphic.IsTransparent(), bAnimated = rGraphic.IsAnimated();
+
+ DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "XOutBitmap::WriteGraphic(...): invalid URL" );
+
+ // calculate correct file name
+ if( !( nFlags & XOutFlags::DontExpandFilename ) )
+ {
+ OUString aStr( OUString::number( rGraphic.GetChecksum(), 16 ) );
+ if ( aStr[0] == '-' )
+ aStr = "m" + aStr.copy(1);
+ OUString aName = aURL.getBase() + "_" + aURL.getExtension() + "_" + aStr;
+ aURL.setBase( aName );
+ }
+
+ // #i121128# use shortcut to write Vector Graphic Data data in original form (if possible)
+ auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
+
+ if (rVectorGraphicDataPtr && rVectorGraphicDataPtr->getVectorGraphicDataArrayLength())
+ {
+ const bool bIsSvg(rFilterName.equalsIgnoreAsciiCase("svg") && VectorGraphicDataType::Svg == rVectorGraphicDataPtr->getVectorGraphicDataType());
+ const bool bIsWmf(rFilterName.equalsIgnoreAsciiCase("wmf") && VectorGraphicDataType::Wmf == rVectorGraphicDataPtr->getVectorGraphicDataType());
+ const bool bIsEmf(rFilterName.equalsIgnoreAsciiCase("emf") && VectorGraphicDataType::Emf == rVectorGraphicDataPtr->getVectorGraphicDataType());
+ const bool bIsPdf(rFilterName.equalsIgnoreAsciiCase("pdf") && VectorGraphicDataType::Pdf == rVectorGraphicDataPtr->getVectorGraphicDataType());
+
+ if (bIsSvg || bIsWmf || bIsEmf || bIsPdf)
+ {
+ if (!(nFlags & XOutFlags::DontAddExtension))
+ {
+ aURL.setExtension(rFilterName);
+ }
+
+ rFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ SfxMedium aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC);
+ SvStream* pOStm = aMedium.GetOutStream();
+
+ if (pOStm)
+ {
+ pOStm->WriteBytes(rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength());
+ aMedium.Commit();
+
+ if (!aMedium.GetError())
+ {
+ nErr = ERRCODE_NONE;
+ }
+ }
+ }
+ }
+
+ if( ERRCODE_NONE != nErr )
+ {
+ if( ( nFlags & XOutFlags::UseNativeIfPossible ) &&
+ !( nFlags & XOutFlags::MirrorHorz ) &&
+ !( nFlags & XOutFlags::MirrorVert ) &&
+ ( rGraphic.GetType() != GraphicType::GdiMetafile ) && rGraphic.IsGfxLink() )
+ {
+ // try to write native link
+ const GfxLink aGfxLink( rGraphic.GetGfxLink() );
+
+ switch( aGfxLink.GetType() )
+ {
+ case GfxLinkType::NativeGif: aExt = FORMAT_GIF; break;
+
+ // #i15508# added BMP type for better exports (no call/trigger found, prob used in HTML export)
+ case GfxLinkType::NativeBmp: aExt = FORMAT_BMP; break;
+
+ case GfxLinkType::NativeJpg: aExt = FORMAT_JPG; break;
+ case GfxLinkType::NativePng: aExt = FORMAT_PNG; break;
+
+ default:
+ break;
+ }
+
+ // tdf#60684: use native format if possible but it must correspond to filter name
+ // or no specific format has been required
+ // without this, you may save for example file with png extension but jpg content
+ if( !aExt.isEmpty() && (aExt == rFilterName || rFilterName.isEmpty()) )
+ {
+ if( !(nFlags & XOutFlags::DontAddExtension) )
+ aURL.setExtension( aExt );
+ rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ SfxMedium aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC);
+ SvStream* pOStm = aMedium.GetOutStream();
+
+ if( pOStm && aGfxLink.GetDataSize() && aGfxLink.GetData() )
+ {
+ pOStm->WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
+ aMedium.Commit();
+
+ if( !aMedium.GetError() )
+ nErr = ERRCODE_NONE;
+ }
+ }
+ }
+ }
+
+ if( ERRCODE_NONE != nErr )
+ {
+ OUString aFilter( rFilterName );
+ bool bWriteTransGrf = ( aFilter.equalsIgnoreAsciiCase( "transgrf" ) ) ||
+ ( aFilter.equalsIgnoreAsciiCase( "gif" ) ) ||
+ ( nFlags & XOutFlags::UseGifIfPossible ) ||
+ ( ( nFlags & XOutFlags::UseGifIfSensible ) && ( bAnimated || bTransparent ) );
+
+ // get filter and extension
+ if( bWriteTransGrf )
+ aFilter = FORMAT_GIF;
+
+ nFilter = rFilter.GetExportFormatNumberForShortName( aFilter );
+
+ if( GRFILTER_FORMAT_NOTFOUND == nFilter )
+ {
+ nFilter = rFilter.GetExportFormatNumberForShortName( FORMAT_PNG );
+
+ if( GRFILTER_FORMAT_NOTFOUND == nFilter )
+ nFilter = rFilter.GetExportFormatNumberForShortName( FORMAT_BMP );
+ }
+
+ if( GRFILTER_FORMAT_NOTFOUND != nFilter )
+ {
+ aExt = rFilter.GetExportFormatShortName( nFilter ).toAsciiLowerCase();
+
+ if( bWriteTransGrf )
+ {
+ if( bAnimated )
+ aGraphic = rGraphic;
+ else
+ {
+ if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GraphicType::Bitmap ) )
+ {
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ const Size aSize(pVDev->LogicToPixel(*pMtfSize_100TH_MM, MapMode(MapUnit::Map100thMM)));
+
+ if( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ const Wallpaper aWallpaper( pVDev->GetBackground() );
+ const Point aPt;
+
+ pVDev->SetBackground( Wallpaper( COL_BLACK ) );
+ pVDev->Erase();
+ rGraphic.Draw( pVDev.get(), aPt, aSize );
+
+ const Bitmap aBitmap( pVDev->GetBitmap( aPt, aSize ) );
+
+ pVDev->SetBackground( aWallpaper );
+ pVDev->Erase();
+ rGraphic.Draw( pVDev.get(), aPt, aSize );
+
+ pVDev->SetRasterOp( RasterOp::Xor );
+ pVDev->DrawBitmap( aPt, aSize, aBitmap );
+ aGraphic = BitmapEx( aBitmap, pVDev->GetBitmap( aPt, aSize ) );
+ }
+ else
+ aGraphic = rGraphic.GetBitmapEx();
+ }
+ else
+ aGraphic = rGraphic.GetBitmapEx();
+ }
+ }
+ else
+ {
+ if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GraphicType::Bitmap ) )
+ {
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ const Size aSize(pVDev->LogicToPixel(*pMtfSize_100TH_MM, MapMode(MapUnit::Map100thMM)));
+
+ if( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ rGraphic.Draw( pVDev.get(), Point(), aSize );
+ aGraphic = pVDev->GetBitmap( Point(), aSize );
+ }
+ else
+ aGraphic = rGraphic.GetBitmapEx();
+ }
+ else
+ aGraphic = rGraphic.GetBitmapEx();
+ }
+
+ // mirror?
+ if( ( nFlags & XOutFlags::MirrorHorz ) || ( nFlags & XOutFlags::MirrorVert ) )
+ {
+ BmpMirrorFlags nBmpMirrorFlags = BmpMirrorFlags::NONE;
+ if( nFlags & XOutFlags::MirrorHorz )
+ nBmpMirrorFlags |= BmpMirrorFlags::Horizontal;
+ if( nFlags & XOutFlags::MirrorVert )
+ nBmpMirrorFlags |= BmpMirrorFlags::Vertical;
+ aGraphic = MirrorGraphic( aGraphic, nBmpMirrorFlags );
+ }
+
+ if (aGraphic.GetType() != GraphicType::NONE)
+ {
+ if( !(nFlags & XOutFlags::DontAddExtension) )
+ aURL.setExtension( aExt );
+ rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ nErr = ExportGraphic( aGraphic, aURL, rFilter, nFilter, pFilterData );
+ }
+ }
+ }
+
+ return nErr;
+ }
+ else
+ {
+ return ERRCODE_NONE;
+ }
+}
+
+bool XOutBitmap::GraphicToBase64(const Graphic& rGraphic, OUString& rOUString, bool bAddPrefix,
+ ConvertDataFormat aTargetFormat)
+{
+ SvMemoryStream aOStm;
+ GfxLink aLink = rGraphic.GetGfxLink();
+
+ if (aTargetFormat == ConvertDataFormat::Unknown)
+ {
+ switch (aLink.GetType())
+ {
+ case GfxLinkType::NativeJpg:
+ aTargetFormat = ConvertDataFormat::JPG;
+ break;
+ case GfxLinkType::NativePng:
+ aTargetFormat = ConvertDataFormat::PNG;
+ break;
+ case GfxLinkType::NativeSvg:
+ aTargetFormat = ConvertDataFormat::SVG;
+ break;
+ default:
+ // save everything else (including gif) into png
+ aTargetFormat = ConvertDataFormat::PNG;
+ break;
+ }
+ }
+
+ ErrCode nErr = GraphicConverter::Export(aOStm,rGraphic,aTargetFormat);
+ if ( nErr )
+ {
+ SAL_WARN("svx", "XOutBitmap::GraphicToBase64() invalid Graphic? error: " << nErr );
+ return false;
+ }
+ css::uno::Sequence<sal_Int8> aOStmSeq( static_cast<sal_Int8 const *>(aOStm.GetData()),aOStm.TellEnd() );
+ OUStringBuffer aStrBuffer;
+ ::comphelper::Base64::encode(aStrBuffer,aOStmSeq);
+ rOUString = aStrBuffer.makeStringAndClear();
+
+ if (bAddPrefix)
+ {
+ OUString aMimeType
+ = comphelper::GraphicMimeTypeHelper::GetMimeTypeForConvertDataFormat(aTargetFormat);
+ rOUString = aMimeType + ";base64," + rOUString;
+ }
+
+ return true;
+}
+
+ErrCode XOutBitmap::ExportGraphic( const Graphic& rGraphic, const INetURLObject& rURL,
+ GraphicFilter& rFilter, const sal_uInt16 nFormat,
+ const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
+{
+ DBG_ASSERT( rURL.GetProtocol() != INetProtocol::NotValid, "XOutBitmap::ExportGraphic(...): invalid URL" );
+
+ SfxMedium aMedium( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC );
+ SvStream* pOStm = aMedium.GetOutStream();
+ ErrCode nRet = ERRCODE_GRFILTER_IOERROR;
+
+ if( pOStm )
+ {
+ pGrfFilter = &rFilter;
+
+ nRet = rFilter.ExportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), *pOStm, nFormat, pFilterData );
+
+ pGrfFilter = nullptr;
+ aMedium.Commit();
+
+ if( aMedium.GetError() && ( ERRCODE_NONE == nRet ) )
+ nRet = ERRCODE_GRFILTER_IOERROR;
+ }
+
+ return nRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/_xpoly.cxx b/svx/source/xoutdev/_xpoly.cxx
new file mode 100644
index 000000000..abb536aed
--- /dev/null
+++ b/svx/source/xoutdev/_xpoly.cxx
@@ -0,0 +1,948 @@
+/* -*- 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 <tools/debug.hxx>
+#include <tools/poly.hxx>
+#include <tools/helpers.hxx>
+#include <tools/gen.hxx>
+
+#include <svx/xpoly.hxx>
+#include <xpolyimp.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+
+ImpXPolygon::ImpXPolygon(sal_uInt16 nInitSize, sal_uInt16 _nResize)
+ : pOldPointAry(nullptr)
+ , bDeleteOldPoints(false)
+ , nSize(0)
+ , nResize(_nResize)
+ , nPoints(0)
+{
+ Resize(nInitSize);
+}
+
+ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
+ : pOldPointAry(nullptr)
+ , bDeleteOldPoints(false)
+ , nSize(0)
+ , nResize(rImpXPoly.nResize)
+ , nPoints(0)
+{
+ rImpXPoly.CheckPointDelete();
+
+ Resize( rImpXPoly.nSize );
+
+ // copy
+ nPoints = rImpXPoly.nPoints;
+ memcpy( pPointAry.get(), rImpXPoly.pPointAry.get(), nSize*sizeof( Point ) );
+ memcpy( pFlagAry.get(), rImpXPoly.pFlagAry.get(), nSize );
+}
+
+ImpXPolygon::~ImpXPolygon()
+{
+ pPointAry.reset();
+ if ( bDeleteOldPoints )
+ {
+ delete[] pOldPointAry;
+ pOldPointAry = nullptr;
+ }
+}
+
+bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
+{
+ return nPoints==rImpXPoly.nPoints &&
+ (nPoints==0 ||
+ (memcmp(pPointAry.get(), rImpXPoly.pPointAry.get(), nPoints*sizeof(Point))==0 &&
+ memcmp(pFlagAry.get(), rImpXPoly.pFlagAry.get(), nPoints)==0));
+}
+
+/** Change polygon size
+ *
+ * @param nNewSize the new size of the polygon
+ * @param bDeletePoints if FALSE, do not delete the point array directly but
+ * wait for the next call before doing so. This prevents
+ * errors with XPoly[n] = XPoly[0] where a resize might
+ * destroy the right side point array too early.
+ */
+void ImpXPolygon::Resize( sal_uInt16 nNewSize, bool bDeletePoints )
+{
+ if( nNewSize == nSize )
+ return;
+
+ PolyFlags* pOldFlagAry = pFlagAry.release();
+ sal_uInt16 nOldSize = nSize;
+
+ CheckPointDelete();
+ pOldPointAry = pPointAry.release();
+
+ // Round the new size to a multiple of nResize, if
+ // the object was not newly created (nSize != 0)
+ if ( nSize != 0 && nNewSize > nSize )
+ {
+ DBG_ASSERT(nResize, "Trying to resize but nResize = 0 !");
+ nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
+ }
+ // create point array
+ nSize = nNewSize;
+ pPointAry.reset( new Point[ nSize ] );
+
+ // create flag array
+ pFlagAry.reset( new PolyFlags[ nSize ] );
+ memset( pFlagAry.get(), 0, nSize );
+
+ // copy if needed
+ if( nOldSize )
+ {
+ if( nOldSize < nSize )
+ {
+ memcpy( pPointAry.get(), pOldPointAry, nOldSize*sizeof( Point ) );
+ memcpy( pFlagAry.get(), pOldFlagAry, nOldSize );
+ }
+ else
+ {
+ memcpy( pPointAry.get(), pOldPointAry, nSize*sizeof( Point ) );
+ memcpy( pFlagAry.get(), pOldFlagAry, nSize );
+
+ // adjust number of valid points
+ if( nPoints > nSize )
+ nPoints = nSize;
+ }
+ if ( bDeletePoints )
+ {
+ delete[] pOldPointAry;
+ pOldPointAry = nullptr;
+ }
+ else
+ bDeleteOldPoints = true;
+ delete[] pOldFlagAry;
+ }
+}
+
+void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
+{
+ CheckPointDelete();
+
+ if ( nPos > nPoints )
+ nPos = nPoints;
+
+ // if the polygon is too small then enlarge it
+ if( (nPoints + nCount) > nSize )
+ Resize( nPoints + nCount );
+
+ // If the insert is not at the last position, move everything after backwards
+ if( nPos < nPoints )
+ {
+ sal_uInt16 nMove = nPoints - nPos;
+ memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
+ nMove * sizeof(Point) );
+ memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
+ }
+ std::fill(pPointAry.get() + nPos, pPointAry.get() + nPos + nCount, Point());
+ memset( &pFlagAry [nPos], 0, nCount );
+
+ nPoints = nPoints + nCount;
+}
+
+void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
+{
+ CheckPointDelete();
+
+ if( (nPos + nCount) <= nPoints )
+ {
+ sal_uInt16 nMove = nPoints - nPos - nCount;
+
+ if( nMove )
+ {
+ memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
+ nMove * sizeof(Point) );
+ memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
+ }
+ std::fill(pPointAry.get() + (nPoints - nCount), pPointAry.get() + nPoints, Point());
+ memset( &pFlagAry [nPoints - nCount], 0, nCount );
+ nPoints = nPoints - nCount;
+ }
+}
+
+void ImpXPolygon::CheckPointDelete() const
+{
+ if ( bDeleteOldPoints )
+ {
+ delete[] pOldPointAry;
+ const_cast< ImpXPolygon* >(this)->pOldPointAry = nullptr;
+ const_cast< ImpXPolygon* >(this)->bDeleteOldPoints = false;
+ }
+}
+
+XPolygon::XPolygon( sal_uInt16 nSize )
+ : pImpXPolygon( ImpXPolygon( nSize, 16 ) )
+{
+}
+
+XPolygon::XPolygon( const XPolygon& ) = default;
+
+XPolygon::XPolygon( XPolygon&& ) = default;
+
+/// create a XPolygon out of a standard polygon
+XPolygon::XPolygon( const tools::Polygon& rPoly )
+ : pImpXPolygon( rPoly.GetSize() )
+{
+ sal_uInt16 nSize = rPoly.GetSize();
+ pImpXPolygon->nPoints = nSize;
+
+ for( sal_uInt16 i = 0; i < nSize; i++ )
+ {
+ pImpXPolygon->pPointAry[i] = rPoly[i];
+ pImpXPolygon->pFlagAry[i] = rPoly.GetFlags( i );
+ }
+}
+
+/// create a rectangle (also with rounded corners) as a Bézier polygon
+XPolygon::XPolygon(const tools::Rectangle& rRect, long nRx, long nRy)
+ : pImpXPolygon( 17 )
+{
+ long nWh = (rRect.GetWidth() - 1) / 2;
+ long nHh = (rRect.GetHeight() - 1) / 2;
+
+ if ( nRx > nWh ) nRx = nWh;
+ if ( nRy > nHh ) nRy = nHh;
+
+ // negate Rx => circle clockwise
+ nRx = -nRx;
+
+ // factor for control points of the Bézier curve: 8/3 * (sin(45g) - 0.5)
+ long nXHdl = static_cast<long>(0.552284749 * nRx);
+ long nYHdl = static_cast<long>(0.552284749 * nRy);
+ sal_uInt16 nPos = 0;
+
+ if ( nRx && nRy )
+ {
+ Point aCenter;
+
+ for (sal_uInt16 nQuad = 0; nQuad < 4; nQuad++)
+ {
+ switch ( nQuad )
+ {
+ case 0: aCenter = rRect.TopLeft();
+ aCenter.AdjustX( -nRx );
+ aCenter.AdjustY(nRy );
+ break;
+ case 1: aCenter = rRect.TopRight();
+ aCenter.AdjustX(nRx );
+ aCenter.AdjustY(nRy );
+ break;
+ case 2: aCenter = rRect.BottomRight();
+ aCenter.AdjustX(nRx );
+ aCenter.AdjustY( -nRy );
+ break;
+ case 3: aCenter = rRect.BottomLeft();
+ aCenter.AdjustX( -nRx );
+ aCenter.AdjustY( -nRy );
+ break;
+ }
+ GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
+ pImpXPolygon->pFlagAry[nPos ] = PolyFlags::Smooth;
+ pImpXPolygon->pFlagAry[nPos+3] = PolyFlags::Smooth;
+ nPos += 4;
+ }
+ }
+ else
+ {
+ pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
+ pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
+ pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
+ pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
+ }
+ pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
+ pImpXPolygon->nPoints = nPos + 1;
+}
+
+/// create an ellipse (curve) as Bézier polygon
+XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
+ sal_uInt16 nStartAngle, sal_uInt16 nEndAngle, bool bClose)
+ : pImpXPolygon( 17 )
+{
+ nStartAngle %= 3600;
+ if ( nEndAngle > 3600 ) nEndAngle %= 3600;
+ bool bFull = (nStartAngle == 0 && nEndAngle == 3600);
+
+ // factor for control points of the Bézier curve: 8/3 * (sin(45g) - 0.5)
+ long nXHdl = static_cast<long>(0.552284749 * nRx);
+ long nYHdl = static_cast<long>(0.552284749 * nRy);
+ sal_uInt16 nPos = 0;
+ bool bLoopEnd = false;
+
+ do
+ {
+ sal_uInt16 nA1, nA2;
+ sal_uInt16 nQuad = nStartAngle / 900;
+ if ( nQuad == 4 ) nQuad = 0;
+ bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
+ GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
+ nPos += 3;
+ if ( !bLoopEnd )
+ pImpXPolygon->pFlagAry[nPos] = PolyFlags::Smooth;
+
+ } while ( !bLoopEnd );
+
+ // if not a full circle then connect edges with center point if necessary
+ if ( !bFull && bClose )
+ pImpXPolygon->pPointAry[++nPos] = rCenter;
+
+ if ( bFull )
+ {
+ pImpXPolygon->pFlagAry[0 ] = PolyFlags::Smooth;
+ pImpXPolygon->pFlagAry[nPos] = PolyFlags::Smooth;
+ }
+ pImpXPolygon->nPoints = nPos + 1;
+}
+
+XPolygon::~XPolygon() = default;
+
+void XPolygon::SetPointCount( sal_uInt16 nPoints )
+{
+ pImpXPolygon->CheckPointDelete();
+
+ if( pImpXPolygon->nSize < nPoints )
+ pImpXPolygon->Resize( nPoints );
+
+ if ( nPoints < pImpXPolygon->nPoints )
+ {
+ sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
+ std::fill(
+ pImpXPolygon->pPointAry.get() + nPoints, pImpXPolygon->pPointAry.get() + nPoints + nSize, Point());
+ memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
+ }
+ pImpXPolygon->nPoints = nPoints;
+}
+
+sal_uInt16 XPolygon::GetSize() const
+{
+ pImpXPolygon->CheckPointDelete();
+ return pImpXPolygon->nSize;
+}
+
+sal_uInt16 XPolygon::GetPointCount() const
+{
+ pImpXPolygon->CheckPointDelete();
+ return pImpXPolygon->nPoints;
+}
+
+void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags )
+{
+ if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
+ pImpXPolygon->InsertSpace( nPos, 1 );
+ pImpXPolygon->pPointAry[nPos] = rPt;
+ pImpXPolygon->pFlagAry[nPos] = eFlags;
+}
+
+void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
+{
+ if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
+
+ sal_uInt16 nPoints = rXPoly.GetPointCount();
+
+ pImpXPolygon->InsertSpace( nPos, nPoints );
+
+ memcpy( &(pImpXPolygon->pPointAry[nPos]),
+ rXPoly.pImpXPolygon->pPointAry.get(),
+ nPoints*sizeof( Point ) );
+ memcpy( &(pImpXPolygon->pFlagAry[nPos]),
+ rXPoly.pImpXPolygon->pFlagAry.get(),
+ nPoints );
+}
+
+void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
+{
+ pImpXPolygon->Remove( nPos, nCount );
+}
+
+void XPolygon::Move( long nHorzMove, long nVertMove )
+{
+ if ( !nHorzMove && !nVertMove )
+ return;
+
+ // move points
+ sal_uInt16 nCount = pImpXPolygon->nPoints;
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ {
+ Point* pPt = &(pImpXPolygon->pPointAry[i]);
+ pPt->AdjustX( nHorzMove );
+ pPt->AdjustY( nVertMove );
+ }
+}
+
+tools::Rectangle XPolygon::GetBoundRect() const
+{
+ pImpXPolygon->CheckPointDelete();
+ tools::Rectangle aRetval;
+
+ if(pImpXPolygon->nPoints)
+ {
+ // #i37709#
+ // For historical reasons the control points are not part of the
+ // BoundRect. This makes it necessary to subdivide the polygon to
+ // get a relatively correct BoundRect. Numerically, this is not
+ // correct and never was.
+
+ const basegfx::B2DRange aPolygonRange(basegfx::utils::getRange(getB2DPolygon()));
+ aRetval = tools::Rectangle(
+ FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
+ FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
+ }
+
+ return aRetval;
+}
+
+const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
+{
+ DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Invalid index at const array access to XPolygon");
+
+ pImpXPolygon->CheckPointDelete();
+ return pImpXPolygon->pPointAry[nPos];
+}
+
+Point& XPolygon::operator[]( sal_uInt16 nPos )
+{
+ pImpXPolygon->CheckPointDelete();
+
+ if( nPos >= pImpXPolygon->nSize )
+ {
+ DBG_ASSERT(pImpXPolygon->nResize, "Invalid index at array access to XPolygon");
+ pImpXPolygon->Resize(nPos + 1, false);
+ }
+ if( nPos >= pImpXPolygon->nPoints )
+ pImpXPolygon->nPoints = nPos + 1;
+
+ return pImpXPolygon->pPointAry[nPos];
+}
+
+XPolygon& XPolygon::operator=( const XPolygon& ) = default;
+
+XPolygon& XPolygon::operator=( XPolygon&& ) = default;
+
+bool XPolygon::operator==( const XPolygon& rXPoly ) const
+{
+ pImpXPolygon->CheckPointDelete();
+ return rXPoly.pImpXPolygon == pImpXPolygon;
+}
+
+/// get the flags for the point at the given position
+PolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
+{
+ pImpXPolygon->CheckPointDelete();
+ return pImpXPolygon->pFlagAry[nPos];
+}
+
+/// set the flags for the point at the given position
+void XPolygon::SetFlags( sal_uInt16 nPos, PolyFlags eFlags )
+{
+ pImpXPolygon->CheckPointDelete();
+ pImpXPolygon->pFlagAry[nPos] = eFlags;
+}
+
+/// short path to read the CONTROL flag directly (TODO: better explain what the sense behind this flag is!)
+bool XPolygon::IsControl(sal_uInt16 nPos) const
+{
+ return pImpXPolygon->pFlagAry[nPos] == PolyFlags::Control;
+}
+
+/// short path to read the SMOOTH and SYMMTR flag directly (TODO: better explain what the sense behind these flags is!)
+bool XPolygon::IsSmooth(sal_uInt16 nPos) const
+{
+ PolyFlags eFlag = pImpXPolygon->pFlagAry[nPos];
+ return ( eFlag == PolyFlags::Smooth || eFlag == PolyFlags::Symmetric );
+}
+
+/** calculate the euclidean distance between two points
+ *
+ * @param nP1 The first point
+ * @param nP2 The second point
+ */
+double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
+{
+ const Point& rP1 = pImpXPolygon->pPointAry[nP1];
+ const Point& rP2 = pImpXPolygon->pPointAry[nP2];
+ double fDx = rP2.X() - rP1.X();
+ double fDy = rP2.Y() - rP1.Y();
+ return sqrt(fDx * fDx + fDy * fDy);
+}
+
+void XPolygon::SubdivideBezier(sal_uInt16 nPos, bool bCalcFirst, double fT)
+{
+ Point* pPoints = pImpXPolygon->pPointAry.get();
+ double fT2 = fT * fT;
+ double fT3 = fT * fT2;
+ double fU = 1.0 - fT;
+ double fU2 = fU * fU;
+ double fU3 = fU * fU2;
+ sal_uInt16 nIdx = nPos;
+ short nPosInc, nIdxInc;
+
+ if ( bCalcFirst )
+ {
+ nPos += 3;
+ nPosInc = -1;
+ nIdxInc = 0;
+ }
+ else
+ {
+ nPosInc = 1;
+ nIdxInc = 1;
+ }
+ pPoints[nPos].setX( static_cast<long>(fU3 * pPoints[nIdx ].X() +
+ fT * fU2 * pPoints[nIdx+1].X() * 3 +
+ fT2 * fU * pPoints[nIdx+2].X() * 3 +
+ fT3 * pPoints[nIdx+3].X()) );
+ pPoints[nPos].setY( static_cast<long>(fU3 * pPoints[nIdx ].Y() +
+ fT * fU2 * pPoints[nIdx+1].Y() * 3 +
+ fT2 * fU * pPoints[nIdx+2].Y() * 3 +
+ fT3 * pPoints[nIdx+3].Y()) );
+ nPos = nPos + nPosInc;
+ nIdx = nIdx + nIdxInc;
+ pPoints[nPos].setX( static_cast<long>(fU2 * pPoints[nIdx ].X() +
+ fT * fU * pPoints[nIdx+1].X() * 2 +
+ fT2 * pPoints[nIdx+2].X()) );
+ pPoints[nPos].setY( static_cast<long>(fU2 * pPoints[nIdx ].Y() +
+ fT * fU * pPoints[nIdx+1].Y() * 2 +
+ fT2 * pPoints[nIdx+2].Y()) );
+ nPos = nPos + nPosInc;
+ nIdx = nIdx + nIdxInc;
+ pPoints[nPos].setX( static_cast<long>(fU * pPoints[nIdx ].X() +
+ fT * pPoints[nIdx+1].X()) );
+ pPoints[nPos].setY( static_cast<long>(fU * pPoints[nIdx ].Y() +
+ fT * pPoints[nIdx+1].Y()) );
+}
+
+/// Generate a Bézier arc
+void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
+ long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
+ sal_uInt16 nQuad, sal_uInt16 nFirst)
+{
+ Point* pPoints = pImpXPolygon->pPointAry.get();
+ pPoints[nFirst ] = rCenter;
+ pPoints[nFirst+3] = rCenter;
+
+ if ( nQuad == 1 || nQuad == 2 )
+ {
+ nRx = -nRx; nXHdl = -nXHdl;
+ }
+ if ( nQuad == 0 || nQuad == 1 )
+ {
+ nRy = -nRy; nYHdl = -nYHdl;
+ }
+
+ if ( nQuad == 0 || nQuad == 2 )
+ {
+ pPoints[nFirst].AdjustX( nRx );
+ pPoints[nFirst+3].AdjustY( nRy );
+ }
+ else
+ {
+ pPoints[nFirst].AdjustY( nRy );
+ pPoints[nFirst+3].AdjustX( nRx );
+ }
+ pPoints[nFirst+1] = pPoints[nFirst];
+ pPoints[nFirst+2] = pPoints[nFirst+3];
+
+ if ( nQuad == 0 || nQuad == 2 )
+ {
+ pPoints[nFirst+1].AdjustY( nYHdl );
+ pPoints[nFirst+2].AdjustX( nXHdl );
+ }
+ else
+ {
+ pPoints[nFirst+1].AdjustX( nXHdl );
+ pPoints[nFirst+2].AdjustY( nYHdl );
+ }
+ if ( nStart > 0 )
+ SubdivideBezier(nFirst, false, static_cast<double>(nStart) / 900);
+ if ( nEnd < 900 )
+ SubdivideBezier(nFirst, true, static_cast<double>(nEnd-nStart) / (900-nStart));
+ SetFlags(nFirst+1, PolyFlags::Control);
+ SetFlags(nFirst+2, PolyFlags::Control);
+}
+
+bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
+{
+ if ( nStart == 3600 ) nStart = 0;
+ if ( nEnd == 0 ) nEnd = 3600;
+ sal_uInt16 nStPrev = nStart;
+ sal_uInt16 nMax = (nStart / 900 + 1) * 900;
+ sal_uInt16 nMin = nMax - 900;
+
+ if ( nEnd >= nMax || nEnd <= nStart ) nA2 = 900;
+ else nA2 = nEnd - nMin;
+ nA1 = nStart - nMin;
+ nStart = nMax;
+
+ // returns true when the last segment was calculated
+ return (nStPrev < nEnd && nStart >= nEnd);
+}
+
+/** Calculate a smooth transition to connect two Bézier curves
+ *
+ * This is done by projecting the corresponding point onto a line between
+ * two other points.
+ *
+ * @param nCenter The point at the end or beginning of the curve.
+ * If nCenter is at the end of the polygon the point is moved
+ * to the opposite side.
+ * @param nDrag The moved point that specifies the relocation.
+ * @param nPnt The point to modify.
+ */
+void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
+{
+ // If nPoint is no control point, i.e. cannot be moved, then
+ // move nDrag instead on the line between nCenter and nPnt
+ if ( !IsControl(nPnt) )
+ {
+ sal_uInt16 nTmp = nDrag;
+ nDrag = nPnt;
+ nPnt = nTmp;
+ }
+ Point* pPoints = pImpXPolygon->pPointAry.get();
+ Point aDiff = pPoints[nDrag] - pPoints[nCenter];
+ double fDiv = CalcDistance(nCenter, nDrag);
+
+ if ( fDiv )
+ {
+ double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
+ // keep the length if SMOOTH
+ if ( GetFlags(nCenter) == PolyFlags::Smooth || !IsControl(nDrag) )
+ {
+ aDiff.setX( static_cast<long>(fRatio * aDiff.X()) );
+ aDiff.setY( static_cast<long>(fRatio * aDiff.Y()) );
+ }
+ pPoints[nPnt] = pPoints[nCenter] - aDiff;
+ }
+}
+
+/** Calculate tangent between two Bézier curves
+ *
+ * @param nCenter start or end point of the curves
+ * @param nPrev previous reference point
+ * @param nNext next reference point
+ */
+void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
+{
+ double fAbsLen = CalcDistance(nNext, nPrev);
+
+ if ( !fAbsLen )
+ return;
+
+ const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
+ Point& rNext = pImpXPolygon->pPointAry[nNext];
+ Point& rPrev = pImpXPolygon->pPointAry[nPrev];
+ Point aDiff = rNext - rPrev;
+ double fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
+ double fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
+
+ // same length for both sides if SYMMTR
+ if ( GetFlags(nCenter) == PolyFlags::Symmetric )
+ {
+ fPrevLen = (fNextLen + fPrevLen) / 2;
+ fNextLen = fPrevLen;
+ }
+ rNext.setX( rCenter.X() + static_cast<long>(fNextLen * aDiff.X()) );
+ rNext.setY( rCenter.Y() + static_cast<long>(fNextLen * aDiff.Y()) );
+ rPrev.setX( rCenter.X() - static_cast<long>(fPrevLen * aDiff.X()) );
+ rPrev.setY( rCenter.Y() - static_cast<long>(fPrevLen * aDiff.Y()) );
+}
+
+/// convert four polygon points into a Bézier curve
+void XPolygon::PointsToBezier(sal_uInt16 nFirst)
+{
+ double nFullLength, nPart1Length, nPart2Length;
+ double fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
+ double fTx1, fTx2, fTy1, fTy2;
+ double fT1, fU1, fT2, fU2, fV;
+ Point* pPoints = pImpXPolygon->pPointAry.get();
+
+ if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
+ IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
+ return;
+
+ fTx1 = pPoints[nFirst+1].X();
+ fTy1 = pPoints[nFirst+1].Y();
+ fTx2 = pPoints[nFirst+2].X();
+ fTy2 = pPoints[nFirst+2].Y();
+ fX0 = pPoints[nFirst ].X();
+ fY0 = pPoints[nFirst ].Y();
+ fX3 = pPoints[nFirst+3].X();
+ fY3 = pPoints[nFirst+3].Y();
+
+ nPart1Length = CalcDistance(nFirst, nFirst+1);
+ nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
+ nFullLength = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
+ if ( nFullLength < 20 )
+ return;
+
+ if ( nPart2Length == nFullLength )
+ nPart2Length -= 1;
+ if ( nPart1Length == nFullLength )
+ nPart1Length = nPart2Length - 1;
+ if ( nPart1Length <= 0 )
+ nPart1Length = 1;
+ if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
+ nPart2Length = nPart1Length + 1;
+
+ fT1 = nPart1Length / nFullLength;
+ fU1 = 1.0 - fT1;
+ fT2 = nPart2Length / nFullLength;
+ fU2 = 1.0 - fT2;
+ fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
+
+ fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
+ fX1 /= fV;
+ fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
+ fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
+
+ fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
+ fY1 /= fV;
+ fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
+ fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
+
+ fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
+ fX2 -= fX1 * fU2 / fT2;
+ fX2 -= fX3 * fT2 / (fU2 * 3);
+
+ fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
+ fY2 -= fY1 * fU2 / fT2;
+ fY2 -= fY3 * fT2 / (fU2 * 3);
+
+ pPoints[nFirst+1] = Point(static_cast<long>(fX1), static_cast<long>(fY1));
+ pPoints[nFirst+2] = Point(static_cast<long>(fX2), static_cast<long>(fY2));
+ SetFlags(nFirst+1, PolyFlags::Control);
+ SetFlags(nFirst+2, PolyFlags::Control);
+}
+
+/// scale in X- and/or Y-direction
+void XPolygon::Scale(double fSx, double fSy)
+{
+ pImpXPolygon->CheckPointDelete();
+
+ sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
+
+ for (sal_uInt16 i = 0; i < nPntCnt; i++)
+ {
+ Point& rPnt = pImpXPolygon->pPointAry[i];
+ rPnt.setX( static_cast<long>(fSx * rPnt.X()) );
+ rPnt.setY( static_cast<long>(fSy * rPnt.Y()) );
+ }
+}
+
+/**
+ * Distort a polygon by scaling its coordinates relative to a reference
+ * rectangle into an arbitrary rectangle.
+ *
+ * Mapping between polygon corners and reference rectangle:
+ * 0: top left 0----1
+ * 1: top right | |
+ * 2: bottom right 3----2
+ * 3: bottom left
+ */
+void XPolygon::Distort(const tools::Rectangle& rRefRect,
+ const XPolygon& rDistortedRect)
+{
+ pImpXPolygon->CheckPointDelete();
+
+ long Xr, Wr;
+ long Yr, Hr;
+
+ Xr = rRefRect.Left();
+ Yr = rRefRect.Top();
+ Wr = rRefRect.GetWidth();
+ Hr = rRefRect.GetHeight();
+
+ if ( !Wr || !Hr )
+ return;
+
+ long X1, X2, X3, X4;
+ long Y1, Y2, Y3, Y4;
+ DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
+ "Distort: rectangle too small");
+
+ X1 = rDistortedRect[0].X();
+ Y1 = rDistortedRect[0].Y();
+ X2 = rDistortedRect[1].X();
+ Y2 = rDistortedRect[1].Y();
+ X3 = rDistortedRect[3].X();
+ Y3 = rDistortedRect[3].Y();
+ X4 = rDistortedRect[2].X();
+ Y4 = rDistortedRect[2].Y();
+
+ sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
+
+ for (sal_uInt16 i = 0; i < nPntCnt; i++)
+ {
+ double fTx, fTy, fUx, fUy;
+ Point& rPnt = pImpXPolygon->pPointAry[i];
+
+ fTx = static_cast<double>(rPnt.X() - Xr) / Wr;
+ fTy = static_cast<double>(rPnt.Y() - Yr) / Hr;
+ fUx = 1.0 - fTx;
+ fUy = 1.0 - fTy;
+
+ rPnt.setX( static_cast<long>( fUy * (fUx * X1 + fTx * X2) +
+ fTy * (fUx * X3 + fTx * X4) ) );
+ rPnt.setY( static_cast<long>( fUx * (fUy * Y1 + fTy * Y3) +
+ fTx * (fUy * Y2 + fTy * Y4) ) );
+ }
+}
+
+basegfx::B2DPolygon XPolygon::getB2DPolygon() const
+{
+ // #i74631# use tools Polygon class for conversion to not have the code doubled
+ // here. This needs one more conversion but avoids different convertors in
+ // the long run
+ const tools::Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry.get(), pImpXPolygon->pFlagAry.get());
+
+ return aSource.getB2DPolygon();
+}
+
+XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
+ : pImpXPolygon( tools::Polygon( rPolygon ).GetSize() )
+{
+ // #i74631# use tools Polygon class for conversion to not have the code doubled
+ // here. This needs one more conversion but avoids different convertors in
+ // the long run
+
+ const tools::Polygon aSource(rPolygon);
+ sal_uInt16 nSize = aSource.GetSize();
+ pImpXPolygon->nPoints = nSize;
+
+ for( sal_uInt16 i = 0; i < nSize; i++ )
+ {
+ pImpXPolygon->pPointAry[i] = aSource[i];
+ pImpXPolygon->pFlagAry[i] = aSource.GetFlags( i );
+ }
+}
+
+// XPolyPolygon
+XPolyPolygon::XPolyPolygon() = default;
+
+XPolyPolygon::XPolyPolygon( const XPolyPolygon& ) = default;
+
+XPolyPolygon::XPolyPolygon( XPolyPolygon&& ) = default;
+
+XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
+ : pImpXPolyPolygon()
+{
+ for(auto const& rCandidate : rPolyPolygon)
+ {
+ Insert(XPolygon(rCandidate));
+ }
+}
+
+XPolyPolygon::~XPolyPolygon() = default;
+
+void XPolyPolygon::Insert( XPolygon&& rXPoly )
+{
+ pImpXPolyPolygon->aXPolyList.emplace_back( std::move(rXPoly) );
+}
+
+/// insert all XPolygons of a XPolyPolygon
+void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly )
+{
+ for ( size_t i = 0; i < rXPolyPoly.Count(); i++)
+ {
+ pImpXPolyPolygon->aXPolyList.emplace_back( rXPolyPoly[i] );
+ }
+}
+
+void XPolyPolygon::Remove( sal_uInt16 nPos )
+{
+ pImpXPolyPolygon->aXPolyList.erase( pImpXPolyPolygon->aXPolyList.begin() + nPos );
+}
+
+const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
+{
+ return pImpXPolyPolygon->aXPolyList[ nPos ];
+}
+
+void XPolyPolygon::Clear()
+{
+ pImpXPolyPolygon->aXPolyList.clear();
+}
+
+sal_uInt16 XPolyPolygon::Count() const
+{
+ return static_cast<sal_uInt16>(pImpXPolyPolygon->aXPolyList.size());
+}
+
+tools::Rectangle XPolyPolygon::GetBoundRect() const
+{
+ size_t nXPoly = pImpXPolyPolygon->aXPolyList.size();
+ tools::Rectangle aRect;
+
+ for ( size_t n = 0; n < nXPoly; n++ )
+ {
+ XPolygon const & rXPoly = pImpXPolyPolygon->aXPolyList[ n ];
+ aRect.Union( rXPoly.GetBoundRect() );
+ }
+
+ return aRect;
+}
+
+XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
+{
+ return pImpXPolyPolygon->aXPolyList[ nPos ];
+}
+
+XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& ) = default;
+
+XPolyPolygon& XPolyPolygon::operator=( XPolyPolygon&& ) = default;
+
+/**
+ * Distort a polygon by scaling its coordinates relative to a reference
+ * rectangle into an arbitrary rectangle.
+ *
+ * Mapping between polygon corners and reference rectangle:
+ * 0: top left 0----1
+ * 1: top right | |
+ * 2: bottom right 3----2
+ * 3: bottom left
+ */
+void XPolyPolygon::Distort(const tools::Rectangle& rRefRect,
+ const XPolygon& rDistortedRect)
+{
+ for (size_t i = 0; i < Count(); i++)
+ pImpXPolyPolygon->aXPolyList[ i ].Distort(rRefRect, rDistortedRect);
+}
+
+basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
+{
+ basegfx::B2DPolyPolygon aRetval;
+
+ for(sal_uInt16 a(0); a < Count(); a++)
+ {
+ const XPolygon& rPoly = (*this)[a];
+ aRetval.append(rPoly.getB2DPolygon());
+ }
+
+ return aRetval;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xattr.cxx b/svx/source/xoutdev/xattr.cxx
new file mode 100644
index 000000000..9ec7c22f6
--- /dev/null
+++ b/svx/source/xoutdev/xattr.cxx
@@ -0,0 +1,3037 @@
+/* -*- 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 <utility>
+
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/drawing/Hatch.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/DashStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <o3tl/any.hxx>
+#include <svl/itempool.hxx>
+#include <editeng/memberids.h>
+#include <tools/mapunit.hxx>
+#include <osl/diagnose.h>
+
+#include <svx/unoapi.hxx>
+#include <svl/style.hxx>
+
+#include <tools/bigint.hxx>
+#include <svl/itemset.hxx>
+#include <svx/strings.hrc>
+#include <svx/xfillit0.hxx>
+#include <svx/xflasit.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/xlnasit.hxx>
+#include <svx/xtextit0.hxx>
+#include <svx/xtable.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/xsflclit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xlnstwit.hxx>
+#include <svx/xlnedwit.hxx>
+#include <svx/xlnstcit.hxx>
+#include <svx/xlnedcit.hxx>
+#include <editeng/itemtype.hxx>
+#include <editeng/eerdll.hxx>
+#include <svx/xdef.hxx>
+#include <svx/unomid.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/xftdiit.hxx>
+#include <svx/xftstit.hxx>
+#include <svx/xftmrit.hxx>
+#include <svx/xftouit.hxx>
+#include <svx/xftshit.hxx>
+#include <svx/xftshcit.hxx>
+#include <svx/xftshxy.hxx>
+#include <svx/xftadit.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <string>
+
+#include <boost/property_tree/json_parser.hpp>
+#include <libxml/xmlwriter.h>
+
+using namespace ::com::sun::star;
+
+typedef std::map<OUString, OUString> StringMap;
+
+static long ScaleMetricValue( long nVal, long nMul, long nDiv )
+{
+ BigInt aVal( nVal );
+
+ aVal *= nMul;
+
+ if ( aVal.IsNeg() != ( nDiv < 0 ) )
+ aVal-=nDiv/2; // for correct rounding
+ else
+ aVal+=nDiv/2; // for correct rounding
+
+ aVal/=nDiv;
+
+ return long( aVal );
+}
+
+NameOrIndex::NameOrIndex(sal_uInt16 _nWhich, sal_Int32 nIndex) :
+ SfxStringItem(_nWhich, OUString()),
+ nPalIndex(nIndex)
+{
+}
+
+NameOrIndex::NameOrIndex(sal_uInt16 _nWhich, const OUString& rName) :
+ SfxStringItem(_nWhich, rName),
+ nPalIndex(-1)
+{
+}
+
+NameOrIndex::NameOrIndex(const NameOrIndex& rNameOrIndex) :
+ SfxStringItem(rNameOrIndex),
+ nPalIndex(rNameOrIndex.nPalIndex)
+{
+}
+
+bool NameOrIndex::operator==(const SfxPoolItem& rItem) const
+{
+ return ( SfxStringItem::operator==(rItem) &&
+ static_cast<const NameOrIndex&>(rItem).nPalIndex == nPalIndex );
+}
+
+NameOrIndex* NameOrIndex::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new NameOrIndex(*this);
+}
+
+/** this static checks if the given NameOrIndex item has a unique name for its value.
+ The returned String is a unique name for an item with this value in both given pools.
+ Argument pPool2 can be null.
+ If returned string equals NameOrIndex->GetName(), the name was already unique.
+*/
+OUString NameOrIndex::CheckNamedItem( const NameOrIndex* pCheckItem, const sal_uInt16 nWhich, const SfxItemPool* pPool1, SvxCompareValueFunc pCompareValueFunc, const char* pPrefixResId, const XPropertyListRef &pDefaults )
+{
+ bool bForceNew = false;
+
+ OUString aUniqueName = SvxUnogetInternalNameForItem(nWhich, pCheckItem->GetName());
+
+ // 2. if we have a name check if there is already an item with the
+ // same name in the documents pool with a different line end or start
+
+ if (!aUniqueName.isEmpty() && pPool1)
+ {
+ for (const SfxPoolItem* pItem : pPool1->GetItemSurrogates(nWhich))
+ {
+ const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
+
+ if( pNameOrIndex->GetName() == pCheckItem->GetName() )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( !pCompareValueFunc( pNameOrIndex, pCheckItem ) )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+ }
+
+ // if we have no name yet, find existing item with same content or
+ // create a unique name
+ if (aUniqueName.isEmpty())
+ {
+ sal_Int32 nUserIndex = 1;
+ const OUString aUser(SvxResId(pPrefixResId) + " ");
+
+ if( pDefaults )
+ {
+ const int nCount = pDefaults->Count();
+ int nIndex;
+ for( nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ const XPropertyEntry* pEntry = pDefaults->Get(nIndex);
+ if( pEntry )
+ {
+ bool bFound = false;
+
+ switch( nWhich )
+ {
+ case XATTR_FILLBITMAP:
+ {
+ const GraphicObject& rGraphicObjectA(static_cast<const XFillBitmapItem*>(pCheckItem)->GetGraphicObject());
+ const GraphicObject& rGraphicObjectB(static_cast<const XBitmapEntry*>(pEntry)->GetGraphicObject());
+
+ bFound = (rGraphicObjectA == rGraphicObjectB);
+ break;
+ }
+ case XATTR_LINEDASH:
+ bFound = static_cast<const XLineDashItem*>(pCheckItem)->GetDashValue() == static_cast<const XDashEntry*>(pEntry)->GetDash();
+ break;
+ case XATTR_LINESTART:
+ bFound = static_cast<const XLineStartItem*>(pCheckItem)->GetLineStartValue() == static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd();
+ break;
+ case XATTR_LINEEND:
+ bFound = static_cast<const XLineEndItem*>(pCheckItem)->GetLineEndValue() == static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd();
+ break;
+ case XATTR_FILLGRADIENT:
+ bFound = static_cast<const XFillGradientItem*>(pCheckItem)->GetGradientValue() == static_cast<const XGradientEntry*>(pEntry)->GetGradient();
+ break;
+ case XATTR_FILLHATCH:
+ bFound = static_cast<const XFillHatchItem*>(pCheckItem)->GetHatchValue() == static_cast<const XHatchEntry*>(pEntry)->GetHatch();
+ break;
+ }
+
+ if( bFound )
+ {
+ aUniqueName = pEntry->GetName();
+ break;
+ }
+ else
+ {
+ const OUString& aEntryName = pEntry->GetName();
+ if(aEntryName.getLength() >= aUser.getLength())
+ {
+ sal_Int32 nThisIndex = aEntryName.copy( aUser.getLength() ).toInt32();
+ if( nThisIndex >= nUserIndex )
+ nUserIndex = nThisIndex + 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (aUniqueName.isEmpty() && pPool1)
+ {
+ for (const SfxPoolItem* pItem : pPool1->GetItemSurrogates(nWhich))
+ {
+ const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
+
+ if( !pNameOrIndex->GetName().isEmpty() )
+ {
+ if( !bForceNew && pCompareValueFunc( pNameOrIndex, pCheckItem ) )
+ return pNameOrIndex->GetName();
+
+ if( pNameOrIndex->GetName().startsWith( aUser ) )
+ {
+ sal_Int32 nThisIndex = pNameOrIndex->GetName().copy( aUser.getLength() ).toInt32();
+ if( nThisIndex >= nUserIndex )
+ nUserIndex = nThisIndex + 1;
+ }
+ }
+ }
+ aUniqueName = aUser + OUString::number( nUserIndex );
+ }
+ }
+
+ return aUniqueName;
+}
+
+void NameOrIndex::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("NameOrIndex"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("isIndex"), BAD_CAST(OString::boolean(IsIndex()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("index"), BAD_CAST(OString::number(nPalIndex).getStr()));
+ xmlTextWriterEndElement(pWriter);
+}
+
+SfxPoolItem* XColorItem::CreateDefault() { return new XColorItem; }
+
+XColorItem::XColorItem(sal_uInt16 _nWhich, sal_Int32 nIndex, const Color& rTheColor) :
+ NameOrIndex(_nWhich, nIndex),
+ aColor(rTheColor)
+{
+}
+
+XColorItem::XColorItem(sal_uInt16 _nWhich, const OUString& rName, const Color& rTheColor) :
+ NameOrIndex(_nWhich, rName),
+ aColor(rTheColor)
+{
+}
+
+XColorItem::XColorItem(sal_uInt16 _nWhich, const Color& rTheColor)
+ : NameOrIndex(_nWhich, OUString())
+ , aColor(rTheColor)
+{
+}
+
+XColorItem::XColorItem(const XColorItem& rItem) :
+ NameOrIndex(rItem),
+ aColor(rItem.aColor)
+{
+}
+
+XColorItem* XColorItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XColorItem(*this);
+}
+
+bool XColorItem::operator==(const SfxPoolItem& rItem) const
+{
+ return ( NameOrIndex::operator==(rItem) &&
+ static_cast<const XColorItem&>(rItem).aColor == aColor );
+}
+
+const Color& XColorItem::GetColorValue() const
+{
+ assert(!IsIndex());
+ return aColor;
+
+}
+
+bool XColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= GetColorValue().GetRGBColor();
+ return true;
+}
+
+bool XColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ SetColorValue( Color(nValue) );
+
+ return true;
+}
+
+// --- line attributes ---
+
+
+SfxPoolItem* XLineStyleItem::CreateDefault() { return new XLineStyleItem; }
+
+XLineStyleItem::XLineStyleItem(css::drawing::LineStyle eTheLineStyle) :
+ SfxEnumItem(XATTR_LINESTYLE, eTheLineStyle)
+{
+}
+
+XLineStyleItem* XLineStyleItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineStyleItem( *this );
+}
+
+bool XLineStyleItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+
+ const char* pId = nullptr;
+
+ switch( GetValue() )
+ {
+ case css::drawing::LineStyle_NONE:
+ pId = RID_SVXSTR_INVISIBLE;
+ break;
+ case css::drawing::LineStyle_SOLID:
+ pId = RID_SVXSTR_SOLID;
+ break;
+ default: break;
+ }
+
+ if (pId)
+ rText = SvxResId(pId);
+ return true;
+}
+
+bool XLineStyleItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ css::drawing::LineStyle eLS = GetValue();
+ rVal <<= eLS;
+ return true;
+}
+
+bool XLineStyleItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ css::drawing::LineStyle eLS;
+ if(!(rVal >>= eLS ))
+ {
+ // also try an int (for Basic)
+ sal_Int32 nLS = 0;
+ if(!(rVal >>= nLS))
+ return false;
+ eLS = static_cast<css::drawing::LineStyle>(nLS);
+ }
+
+ SetValue( eLS );
+ return true;
+}
+
+sal_uInt16 XLineStyleItem::GetValueCount() const
+{
+ return 3;
+}
+
+XDash::XDash(css::drawing::DashStyle eTheDash, sal_uInt16 nTheDots, sal_uInt32 nTheDotLen,
+ sal_uInt16 nTheDashes, sal_uInt32 nTheDashLen, sal_uInt32 nTheDistance) :
+ eDash(eTheDash),
+ nDotLen(nTheDotLen),
+ nDots(nTheDots),
+ nDashes(nTheDashes),
+ nDashLen(nTheDashLen),
+ nDistance(nTheDistance)
+{
+}
+
+bool XDash::operator==(const XDash& rDash) const
+{
+ return ( eDash == rDash.eDash &&
+ nDots == rDash.nDots &&
+ nDotLen == rDash.nDotLen &&
+ nDashes == rDash.nDashes &&
+ nDashLen == rDash.nDashLen &&
+ nDistance == rDash.nDistance );
+}
+
+// XDash is translated into an array of doubles which describe the lengths of the
+// dashes, dots and empty passages. It returns the complete length of the full DashDot
+// sequence and fills the given vetor of doubles accordingly (also resizing, so deleting it).
+static const double SMALLEST_DASH_WIDTH(26.95);
+
+double XDash::CreateDotDashArray(::std::vector< double >& rDotDashArray, double fLineWidth) const
+{
+ double fFullDotDashLen(0.0);
+ const sal_uInt16 nNumDotDashArray = (GetDots() + GetDashes()) * 2;
+ rDotDashArray.resize( nNumDotDashArray, 0.0 );
+ sal_uInt16 a;
+ sal_uInt16 nIns(0);
+ double fDashDotDistance = static_cast<double>(GetDistance());
+ double fSingleDashLen = static_cast<double>(GetDashLen());
+ double fSingleDotLen = static_cast<double>(GetDotLen());
+
+ if (fLineWidth == 0.0)
+ fLineWidth = SMALLEST_DASH_WIDTH;
+
+ if(GetDashStyle() == css::drawing::DashStyle_RECTRELATIVE || GetDashStyle() == css::drawing::DashStyle_ROUNDRELATIVE)
+ {
+ double fFactor = fLineWidth / 100.0;
+
+ if(GetDashes())
+ {
+ if(GetDashLen())
+ {
+ // is a dash
+ fSingleDashLen *= fFactor;
+ }
+ else
+ {
+ // is a dot
+ fSingleDashLen = fLineWidth;
+ }
+ }
+
+ if(GetDots())
+ {
+ if(GetDotLen())
+ {
+ // is a dash
+ fSingleDotLen *= fFactor;
+ }
+ else
+ {
+ // is a dot
+ fSingleDotLen = fLineWidth;
+ }
+ }
+
+ if(GetDashes() || GetDots())
+ {
+ if(GetDistance())
+ {
+ // dash as distance
+ fDashDotDistance *= fFactor;
+ }
+ else
+ {
+ // dot as distance
+ fDashDotDistance = fLineWidth;
+ }
+ }
+ }
+ else
+ {
+ // absolute values
+ if(GetDashes())
+ {
+ if(GetDashLen())
+ {
+ // is a dash
+ if(fSingleDashLen < SMALLEST_DASH_WIDTH)
+ {
+ fSingleDashLen = SMALLEST_DASH_WIDTH;
+ }
+ }
+ else
+ {
+ // is a dot
+ if(fSingleDashLen < fLineWidth)
+ {
+ fSingleDashLen = fLineWidth;
+ }
+ }
+ }
+
+ if(GetDots())
+ {
+ if(GetDotLen())
+ {
+ // is a dash
+ if(fSingleDotLen < SMALLEST_DASH_WIDTH)
+ {
+ fSingleDotLen = SMALLEST_DASH_WIDTH;
+ }
+ }
+ else
+ {
+ // is a dot
+ if(fSingleDotLen < fLineWidth)
+ {
+ fSingleDotLen = fLineWidth;
+ }
+ }
+ }
+
+ if(GetDashes() || GetDots())
+ {
+ if(GetDistance())
+ {
+ // dash as distance
+ if(fDashDotDistance < SMALLEST_DASH_WIDTH)
+ {
+ fDashDotDistance = SMALLEST_DASH_WIDTH;
+ }
+ }
+ else
+ {
+ // dot as distance
+ if(fDashDotDistance < fLineWidth)
+ {
+ fDashDotDistance = fLineWidth;
+ }
+ }
+ }
+ }
+
+ for(a=0;a<GetDots();a++)
+ {
+ rDotDashArray[nIns++] = fSingleDotLen;
+ fFullDotDashLen += fSingleDotLen;
+ rDotDashArray[nIns++] = fDashDotDistance;
+ fFullDotDashLen += fDashDotDistance;
+ }
+
+ for(a=0;a<GetDashes();a++)
+ {
+ rDotDashArray[nIns++] = fSingleDashLen;
+ fFullDotDashLen += fSingleDashLen;
+ rDotDashArray[nIns++] = fDashDotDistance;
+ fFullDotDashLen += fDashDotDistance;
+ }
+
+ return fFullDotDashLen;
+}
+
+SfxPoolItem* XLineDashItem::CreateDefault() {return new XLineDashItem;}
+
+XLineDashItem::XLineDashItem(const OUString& rName, const XDash& rTheDash) :
+ NameOrIndex(XATTR_LINEDASH, rName),
+ aDash(rTheDash)
+{
+}
+
+XLineDashItem::XLineDashItem(const XLineDashItem& rItem) :
+ NameOrIndex(rItem),
+ aDash(rItem.aDash)
+{
+}
+
+XLineDashItem::XLineDashItem(const XDash& rTheDash)
+: NameOrIndex( XATTR_LINEDASH, -1 ),
+ aDash(rTheDash)
+{
+}
+
+XLineDashItem* XLineDashItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineDashItem(*this);
+}
+
+bool XLineDashItem::operator==(const SfxPoolItem& rItem) const
+{
+ return ( NameOrIndex::operator==(rItem) &&
+ aDash == static_cast<const XLineDashItem&>(rItem).aDash );
+}
+
+bool XLineDashItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XLineDashItem::HasMetrics() const
+{
+ return true;
+}
+
+void XLineDashItem::ScaleMetrics(long nMul, long nDiv)
+{
+ aDash.SetDotLen( ScaleMetricValue( aDash.GetDotLen(), nMul, nDiv ) );
+ aDash.SetDashLen( ScaleMetricValue( aDash.GetDashLen(), nMul, nDiv ) );
+ aDash.SetDistance( ScaleMetricValue( aDash.GetDistance(), nMul, nDiv ) );
+}
+
+bool XLineDashItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
+
+ css::drawing::LineDash aLineDash;
+
+ const XDash& rXD = GetDashValue();
+ 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();
+
+ aPropSeq[0].Name = "Name";
+ aPropSeq[0].Value <<= SvxUnogetApiNameForItem(Which(), GetName());
+ aPropSeq[1].Name = "LineDash";
+ aPropSeq[1].Value <<= aLineDash;
+ rVal <<= aPropSeq;
+ break;
+ }
+
+ case MID_NAME:
+ {
+ rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
+ break;
+ }
+
+ case MID_LINEDASH:
+ {
+ const XDash& rXD = GetDashValue();
+
+ css::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();
+
+ rVal <<= aLineDash;
+ break;
+ }
+
+ case MID_LINEDASH_STYLE:
+ {
+ const XDash& rXD = GetDashValue();
+ rVal <<= static_cast<css::drawing::DashStyle>(static_cast<sal_Int16>(rXD.GetDashStyle()));
+ break;
+ }
+
+ case MID_LINEDASH_DOTS:
+ {
+ const XDash& rXD = GetDashValue();
+ rVal <<= rXD.GetDots();
+ break;
+ }
+
+ case MID_LINEDASH_DOTLEN:
+ {
+ const XDash& rXD = GetDashValue();
+ rVal <<= rXD.GetDotLen();
+ break;
+ }
+
+ case MID_LINEDASH_DASHES:
+ {
+ const XDash& rXD = GetDashValue();
+ rVal <<= rXD.GetDashes();
+ break;
+ }
+
+ case MID_LINEDASH_DASHLEN:
+ {
+ const XDash& rXD = GetDashValue();
+ rVal <<= rXD.GetDashLen();
+ break;
+ }
+
+ case MID_LINEDASH_DISTANCE:
+ {
+ const XDash& rXD = GetDashValue();
+ rVal <<= rXD.GetDistance();
+ break;
+ }
+
+ default: OSL_FAIL("Wrong MemberId!"); return false;
+ }
+
+ return true;
+}
+
+bool XLineDashItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ uno::Sequence< beans::PropertyValue > aPropSeq;
+
+ if ( rVal >>= aPropSeq )
+ {
+ css::drawing::LineDash aLineDash;
+ OUString aName;
+ bool bLineDash( false );
+ for ( const auto& rProp : std::as_const(aPropSeq) )
+ {
+ if ( rProp.Name == "Name" )
+ rProp.Value >>= aName;
+ else if ( rProp.Name == "LineDash" )
+ {
+ if ( rProp.Value >>= aLineDash )
+ bLineDash = true;
+ }
+ }
+
+ SetName( aName );
+ if ( bLineDash )
+ {
+ 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);
+
+ if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
+ aXDash.SetDots(1);
+
+ SetDashValue( aXDash );
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ case MID_NAME:
+ {
+ OUString aName;
+ if (!(rVal >>= aName))
+ return false;
+ SetName( aName );
+ break;
+ }
+
+ case MID_LINEDASH:
+ {
+ css::drawing::LineDash aLineDash;
+ if(!(rVal >>= aLineDash))
+ return false;
+
+ 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);
+
+ if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
+ aXDash.SetDots(1);
+
+ SetDashValue( aXDash );
+ break;
+ }
+
+ case MID_LINEDASH_STYLE:
+ {
+ sal_Int16 nVal = sal_Int16();
+ if(!(rVal >>= nVal))
+ return false;
+
+ XDash aXDash = GetDashValue();
+ aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(nVal)));
+
+ if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
+ aXDash.SetDots(1);
+
+ SetDashValue( aXDash );
+
+ break;
+ }
+
+ case MID_LINEDASH_DOTS:
+ case MID_LINEDASH_DASHES:
+ {
+ sal_Int16 nVal = sal_Int16();
+ if(!(rVal >>= nVal))
+ return false;
+
+ XDash aXDash = GetDashValue();
+ if ( nMemberId == MID_LINEDASH_DOTS )
+ aXDash.SetDots( nVal );
+ else
+ aXDash.SetDashes( nVal );
+
+ if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
+ aXDash.SetDots(1);
+
+ SetDashValue( aXDash );
+ break;
+ }
+
+ case MID_LINEDASH_DOTLEN:
+ case MID_LINEDASH_DASHLEN:
+ case MID_LINEDASH_DISTANCE:
+ {
+ sal_uInt32 nVal = 0;
+ if(!(rVal >>= nVal))
+ return false;
+
+ XDash aXDash = GetDashValue();
+ if ( nMemberId == MID_LINEDASH_DOTLEN )
+ aXDash.SetDotLen( nVal );
+ else if ( nMemberId == MID_LINEDASH_DASHLEN )
+ aXDash.SetDashLen( nVal );
+ else
+ aXDash.SetDistance( nVal );
+
+ if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
+ aXDash.SetDots(1);
+
+ SetDashValue( aXDash );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool XLineDashItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
+{
+ return static_cast<const XLineDashItem*>(p1)->GetDashValue() == static_cast<const XLineDashItem*>(p2)->GetDashValue();
+}
+
+std::unique_ptr<XLineDashItem> XLineDashItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ if( pModel )
+ {
+ const OUString aUniqueName = NameOrIndex::CheckNamedItem(
+ this, XATTR_LINEDASH, &pModel->GetItemPool(),
+ XLineDashItem::CompareValueFunc, RID_SVXSTR_DASH20,
+ pModel->GetPropertyList( XPropertyListType::Dash ) );
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() )
+ return std::make_unique<XLineDashItem>( aUniqueName, aDash );
+ }
+
+ return nullptr;
+}
+
+SfxPoolItem* XLineWidthItem::CreateDefault() {return new XLineWidthItem;}
+
+XLineWidthItem::XLineWidthItem(long nWidth) :
+ SfxMetricItem(XATTR_LINEWIDTH, nWidth)
+{
+}
+
+XLineWidthItem* XLineWidthItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineWidthItem(*this);
+}
+
+bool XLineWidthItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText, const IntlWrapper& rIntl
+) const
+{
+ rText = GetMetricText( static_cast<long>(GetValue()),
+ eCoreUnit, ePresUnit, &rIntl) +
+ " " + EditResId( GetMetricId( ePresUnit) );
+ return true;
+}
+
+bool XLineWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ sal_Int32 nValue = GetValue();
+ if( 0 != (nMemberId&CONVERT_TWIPS) )
+ nValue = convertTwipToMm100(nValue);
+
+ rVal <<= nValue;
+ return true;
+}
+
+bool XLineWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ if( 0 != (nMemberId&CONVERT_TWIPS) )
+ nValue = convertMm100ToTwip(nValue);
+
+ SetValue( nValue );
+ return true;
+}
+
+SfxPoolItem* XLineColorItem::CreateDefault() { return new XLineColorItem; }
+
+XLineColorItem::XLineColorItem(sal_Int32 nIndex, const Color& rTheColor) :
+ XColorItem(XATTR_LINECOLOR, nIndex, rTheColor)
+{
+}
+
+XLineColorItem::XLineColorItem(const OUString& rName, const Color& rTheColor) :
+ XColorItem(XATTR_LINECOLOR, rName, rTheColor)
+{
+}
+
+XLineColorItem* XLineColorItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineColorItem(*this);
+}
+
+bool XLineColorItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XLineColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= GetColorValue().GetRGBColor();
+ return true;
+}
+
+bool XLineColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ if(!(rVal >>= nValue))
+ return false;
+
+ SetColorValue( Color(nValue) );
+ return true;
+}
+
+
+SfxPoolItem* XLineStartItem::CreateDefault() {return new XLineStartItem;}
+
+XLineStartItem::XLineStartItem(sal_Int32 nIndex)
+: NameOrIndex(XATTR_LINESTART, nIndex)
+{
+}
+
+XLineStartItem::XLineStartItem(const OUString& rName, const basegfx::B2DPolyPolygon& rPolyPolygon)
+: NameOrIndex(XATTR_LINESTART, rName),
+ maPolyPolygon(rPolyPolygon)
+{
+}
+
+XLineStartItem::XLineStartItem(const XLineStartItem& rItem)
+: NameOrIndex(rItem),
+ maPolyPolygon(rItem.maPolyPolygon)
+{
+}
+
+XLineStartItem::XLineStartItem(const basegfx::B2DPolyPolygon& rPolyPolygon)
+: NameOrIndex( XATTR_LINESTART, -1 ),
+ maPolyPolygon(rPolyPolygon)
+{
+}
+
+XLineStartItem* XLineStartItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineStartItem(*this);
+}
+
+bool XLineStartItem::operator==(const SfxPoolItem& rItem) const
+{
+ return ( NameOrIndex::operator==(rItem) && static_cast<const XLineStartItem&>(rItem).maPolyPolygon == maPolyPolygon );
+}
+
+bool XLineStartItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XLineStartItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ if( nMemberId == MID_NAME )
+ {
+ rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
+ }
+ else
+ {
+ css::drawing::PolyPolygonBezierCoords aBezier;
+ basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( maPolyPolygon, aBezier );
+ rVal <<= aBezier;
+ }
+
+ return true;
+}
+
+bool XLineStartItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ if( nMemberId == MID_NAME )
+ {
+ return false;
+ }
+ else
+ {
+ maPolyPolygon.clear();
+
+ if( rVal.hasValue() )
+ {
+ auto pCoords = o3tl::tryAccess<css::drawing::PolyPolygonBezierCoords>(
+ rVal);
+ if( !pCoords )
+ return false;
+
+ if( pCoords->Coordinates.getLength() > 0 )
+ {
+ maPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords );
+ // #i72807# close line start/end polygons hard
+ // maPolyPolygon.setClosed(true);
+ }
+ }
+ }
+
+ return true;
+}
+
+/** this function searches in both the models pool and the styles pool for XLineStartItem
+ and XLineEndItem with the same value or name and returns an item with the value of
+ this item and a unique name for an item with this value. */
+std::unique_ptr<XLineStartItem> XLineStartItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ if( pModel )
+ {
+ std::unique_ptr<XLineStartItem> pTempItem;
+ const XLineStartItem* pLineStartItem = this;
+
+ OUString aUniqueName( GetName() );
+
+ if( !maPolyPolygon.count() )
+ {
+ // if the polygon is empty, check if the name is empty
+ if( aUniqueName.isEmpty() )
+ return nullptr;
+
+ // force empty name for empty polygons
+ return std::make_unique<XLineStartItem>( "", maPolyPolygon );
+ }
+
+ if( maPolyPolygon.count() > 1 )
+ {
+ // check if the polygon is closed
+ if(!maPolyPolygon.isClosed())
+ {
+ // force a closed polygon
+ basegfx::B2DPolyPolygon aNew(maPolyPolygon);
+ aNew.setClosed(true);
+ pTempItem.reset(new XLineStartItem( aUniqueName, aNew ));
+ pLineStartItem = pTempItem.get();
+ }
+ }
+
+ bool bForceNew = false;
+
+ // 2. if we have a name check if there is already an item with the
+ // same name in the documents pool with a different line end or start
+
+ const SfxItemPool& rPool1 = pModel->GetItemPool();
+ if (!aUniqueName.isEmpty())
+ {
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINESTART))
+ {
+ auto pItem = dynamic_cast<const XLineStartItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineStartItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineStartValue() != pLineStartItem->GetLineStartValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+
+ if( !bForceNew )
+ {
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINEEND))
+ {
+ auto pItem = dynamic_cast<const XLineEndItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineStartItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineEndValue() != pLineStartItem->GetLineStartValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ const SfxItemPool* pPool2 = pModel->GetStyleSheetPool() ? &pModel->GetStyleSheetPool()->GetPool() : nullptr;
+ if( !aUniqueName.isEmpty() && pPool2)
+ {
+ for (const SfxPoolItem* p : pPool2->GetItemSurrogates(XATTR_LINESTART))
+ {
+ auto pItem = dynamic_cast<const XLineStartItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineStartItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineStartValue() != pLineStartItem->GetLineStartValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+
+ if( !bForceNew )
+ {
+ for (const SfxPoolItem* p : pPool2->GetItemSurrogates(XATTR_LINEEND))
+ {
+ auto pItem = dynamic_cast<const XLineEndItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineStartItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineEndValue() != pLineStartItem->GetLineStartValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // if we have no name yet, find existing item with same content or
+ // create a unique name
+ if( aUniqueName.isEmpty() )
+ {
+ bool bFoundExisting = false;
+
+ sal_Int32 nUserIndex = 1;
+ const OUString aUser(SvxResId(RID_SVXSTR_LINEEND));
+
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINESTART))
+ {
+ auto pItem = dynamic_cast<const XLineStartItem*>(p);
+
+ if (pItem && !pItem->GetName().isEmpty())
+ {
+ if (!bForceNew && pItem->GetLineStartValue() == pLineStartItem->GetLineStartValue())
+ {
+ aUniqueName = pItem->GetName();
+ bFoundExisting = true;
+ break;
+ }
+
+ if (pItem->GetName().startsWith(aUser))
+ {
+ sal_Int32 nThisIndex = pItem->GetName().copy(aUser.getLength()).toInt32();
+ if (nThisIndex >= nUserIndex)
+ nUserIndex = nThisIndex + 1;
+ }
+ }
+ }
+
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINEEND))
+ {
+ auto pItem = dynamic_cast<const XLineEndItem*>(p);
+
+ if (pItem && !pItem->GetName().isEmpty())
+ {
+ if (!bForceNew && pItem->GetLineEndValue() == pLineStartItem->GetLineStartValue())
+ {
+ aUniqueName = pItem->GetName();
+ bFoundExisting = true;
+ break;
+ }
+
+ if (pItem->GetName().startsWith(aUser))
+ {
+ sal_Int32 nThisIndex = pItem->GetName().copy(aUser.getLength()).toInt32();
+ if (nThisIndex >= nUserIndex)
+ nUserIndex = nThisIndex + 1;
+ }
+ }
+ }
+
+ if( !bFoundExisting )
+ {
+ aUniqueName = aUser + " " + OUString::number( nUserIndex );
+ }
+ }
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() || pTempItem )
+ {
+ if( pTempItem )
+ {
+ pTempItem->SetName( aUniqueName );
+ return pTempItem;
+ }
+ else
+ {
+ return std::make_unique<XLineStartItem>( aUniqueName, maPolyPolygon );
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+SfxPoolItem* XLineEndItem::CreateDefault() {return new XLineEndItem;}
+
+XLineEndItem::XLineEndItem(sal_Int32 nIndex)
+: NameOrIndex(XATTR_LINEEND, nIndex)
+{
+}
+
+XLineEndItem::XLineEndItem(const OUString& rName, const basegfx::B2DPolyPolygon& rPolyPolygon)
+: NameOrIndex(XATTR_LINEEND, rName),
+ maPolyPolygon(rPolyPolygon)
+{
+}
+
+XLineEndItem::XLineEndItem(const XLineEndItem& rItem)
+: NameOrIndex(rItem),
+ maPolyPolygon(rItem.maPolyPolygon)
+{
+}
+
+XLineEndItem::XLineEndItem(const basegfx::B2DPolyPolygon& rPolyPolygon)
+: NameOrIndex( XATTR_LINEEND, -1 ),
+ maPolyPolygon(rPolyPolygon)
+{
+}
+
+XLineEndItem* XLineEndItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineEndItem(*this);
+}
+
+bool XLineEndItem::operator==(const SfxPoolItem& rItem) const
+{
+ return ( NameOrIndex::operator==(rItem) && static_cast<const XLineEndItem&>(rItem).maPolyPolygon == maPolyPolygon );
+}
+
+
+/** this function searches in both the models pool and the styles pool for XLineStartItem
+ and XLineEndItem with the same value or name and returns an item with the value of
+ this item and a unique name for an item with this value. */
+std::unique_ptr<XLineEndItem> XLineEndItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ if( pModel )
+ {
+ std::unique_ptr<XLineEndItem> pTempItem;
+ const XLineEndItem* pLineEndItem = this;
+
+ OUString aUniqueName( GetName() );
+
+ if( !maPolyPolygon.count() )
+ {
+ // if the polygon is empty, check if the name is empty
+ if( aUniqueName.isEmpty() )
+ return nullptr;
+
+ // force empty name for empty polygons
+ return std::make_unique<XLineEndItem>( "", maPolyPolygon );
+ }
+
+ if( maPolyPolygon.count() > 1 )
+ {
+ // check if the polygon is closed
+ if(!maPolyPolygon.isClosed())
+ {
+ // force a closed polygon
+ basegfx::B2DPolyPolygon aNew(maPolyPolygon);
+ aNew.setClosed(true);
+ pTempItem.reset(new XLineEndItem( aUniqueName, aNew ));
+ pLineEndItem = pTempItem.get();
+ }
+ }
+
+ bool bForceNew = false;
+
+ // 2. if we have a name check if there is already an item with the
+ // same name in the documents pool with a different line end or start
+
+ const SfxItemPool& rPool1 = pModel->GetItemPool();
+ if (!aUniqueName.isEmpty())
+ {
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINESTART))
+ {
+ auto pItem = dynamic_cast<const XLineStartItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineEndItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineStartValue() != pLineEndItem->GetLineEndValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+
+ if( !bForceNew )
+ {
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINEEND))
+ {
+ auto pItem = dynamic_cast<const XLineEndItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineEndItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineEndValue() != pLineEndItem->GetLineEndValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ const SfxItemPool* pPool2 = pModel->GetStyleSheetPool() ? &pModel->GetStyleSheetPool()->GetPool() : nullptr;
+ if( !aUniqueName.isEmpty() && pPool2)
+ {
+ for (const SfxPoolItem* p : pPool2->GetItemSurrogates(XATTR_LINESTART))
+ {
+ auto pItem = dynamic_cast<const XLineStartItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineEndItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineStartValue() != pLineEndItem->GetLineEndValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+
+ if( !bForceNew )
+ {
+ for (const SfxPoolItem* p : pPool2->GetItemSurrogates(XATTR_LINEEND))
+ {
+ auto pItem = dynamic_cast<const XLineEndItem*>(p);
+
+ if( pItem && ( pItem->GetName() == pLineEndItem->GetName() ) )
+ {
+ // if there is already an item with the same name and the same
+ // value it's ok to set it
+ if( pItem->GetLineEndValue() != pLineEndItem->GetLineEndValue() )
+ {
+ // same name but different value, we need a new name for this item
+ aUniqueName.clear();
+ bForceNew = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // if we have no name yet, find existing item with same content or
+ // create a unique name
+ if( aUniqueName.isEmpty() )
+ {
+ bool bFoundExisting = false;
+
+ sal_Int32 nUserIndex = 1;
+ const OUString aUser(SvxResId(RID_SVXSTR_LINEEND));
+
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINESTART))
+ {
+ auto pItem = dynamic_cast<const XLineStartItem*>(p);
+
+ if (pItem && !pItem->GetName().isEmpty())
+ {
+ if (!bForceNew && pItem->GetLineStartValue() == pLineEndItem->GetLineEndValue())
+ {
+ aUniqueName = pItem->GetName();
+ bFoundExisting = true;
+ break;
+ }
+
+ if (pItem->GetName().startsWith(aUser))
+ {
+ sal_Int32 nThisIndex = pItem->GetName().copy(aUser.getLength()).toInt32();
+ if (nThisIndex >= nUserIndex)
+ nUserIndex = nThisIndex + 1;
+ }
+ }
+ }
+
+ for (const SfxPoolItem* p : rPool1.GetItemSurrogates(XATTR_LINEEND))
+ {
+ auto pItem = dynamic_cast<const XLineEndItem*>(p);
+
+ if (pItem && !pItem->GetName().isEmpty())
+ {
+ if (!bForceNew && pItem->GetLineEndValue() == pLineEndItem->GetLineEndValue())
+ {
+ aUniqueName = pItem->GetName();
+ bFoundExisting = true;
+ break;
+ }
+
+ if (pItem->GetName().startsWith(aUser))
+ {
+ sal_Int32 nThisIndex = pItem->GetName().copy(aUser.getLength()).toInt32();
+ if (nThisIndex >= nUserIndex)
+ nUserIndex = nThisIndex + 1;
+ }
+ }
+ }
+
+ if( !bFoundExisting )
+ {
+ aUniqueName = aUser + " " + OUString::number( nUserIndex );
+ }
+ }
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() || pTempItem )
+ {
+ if( pTempItem )
+ {
+ pTempItem->SetName( aUniqueName );
+ return pTempItem;
+ }
+ else
+ {
+ return std::make_unique<XLineEndItem>( aUniqueName, maPolyPolygon );
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+bool XLineEndItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XLineEndItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ if( nMemberId == MID_NAME )
+ {
+ rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
+ }
+ else
+ {
+ css::drawing::PolyPolygonBezierCoords aBezier;
+ basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( maPolyPolygon, aBezier );
+ rVal <<= aBezier;
+ }
+ return true;
+}
+
+bool XLineEndItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ if( nMemberId == MID_NAME )
+ {
+ return false;
+ }
+ else
+ {
+ maPolyPolygon.clear();
+
+ if( rVal.hasValue() )
+ {
+ auto pCoords = o3tl::tryAccess<css::drawing::PolyPolygonBezierCoords>(
+ rVal);
+ if( !pCoords )
+ return false;
+
+ if( pCoords->Coordinates.getLength() > 0 )
+ {
+ maPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords );
+ // #i72807# close line start/end polygons hard
+ // maPolyPolygon.setClosed(true);
+ }
+ }
+ }
+
+ return true;
+}
+
+XLineStartWidthItem::XLineStartWidthItem(long nWidth) :
+ SfxMetricItem(XATTR_LINESTARTWIDTH, nWidth)
+{
+}
+
+XLineStartWidthItem* XLineStartWidthItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineStartWidthItem(*this);
+}
+
+bool XLineStartWidthItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText, const IntlWrapper& rIntl
+) const
+{
+ rText = GetMetricText( static_cast<long>(GetValue()),
+ eCoreUnit, ePresUnit, &rIntl) +
+ " " + EditResId( GetMetricId( ePresUnit) );
+ return true;
+}
+
+bool XLineStartWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= GetValue();
+ return true;
+}
+
+bool XLineStartWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ SetValue( nValue );
+ return true;
+}
+
+XLineEndWidthItem::XLineEndWidthItem(long nWidth) :
+ SfxMetricItem(XATTR_LINEENDWIDTH, nWidth)
+{
+}
+
+XLineEndWidthItem* XLineEndWidthItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineEndWidthItem(*this);
+}
+
+bool XLineEndWidthItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText, const IntlWrapper& rIntl
+) const
+{
+ rText = GetMetricText( static_cast<long>(GetValue()),
+ eCoreUnit, ePresUnit, &rIntl) +
+ " " + EditResId( GetMetricId( ePresUnit) );
+ return true;
+}
+
+bool XLineEndWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= GetValue();
+ return true;
+}
+
+bool XLineEndWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ SetValue( nValue );
+ return true;
+}
+
+XLineStartCenterItem::XLineStartCenterItem(bool bStartCenter) :
+ SfxBoolItem(XATTR_LINESTARTCENTER, bStartCenter)
+{
+}
+
+XLineStartCenterItem* XLineStartCenterItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineStartCenterItem(*this);
+}
+
+bool XLineStartCenterItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = SvxResId(GetValue() ? RID_SVXSTR_CENTERED : RID_SVXSTR_NOTCENTERED);
+ return true;
+}
+
+bool XLineStartCenterItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ bool bValue = GetValue();
+ rVal <<= bValue;
+ return true;
+}
+
+bool XLineStartCenterItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ auto b = o3tl::tryAccess<bool>(rVal);
+ if( !b )
+ return false;
+
+ SetValue( *b );
+ return true;
+}
+
+XLineEndCenterItem::XLineEndCenterItem(bool bEndCenter) :
+ SfxBoolItem(XATTR_LINEENDCENTER, bEndCenter)
+{
+}
+
+XLineEndCenterItem* XLineEndCenterItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineEndCenterItem(*this);
+}
+
+bool XLineEndCenterItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = SvxResId(GetValue() ? RID_SVXSTR_CENTERED : RID_SVXSTR_NOTCENTERED);
+ return true;
+}
+
+bool XLineEndCenterItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ bool bValue = GetValue();
+ rVal <<= bValue;
+ return true;
+}
+
+bool XLineEndCenterItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ auto b = o3tl::tryAccess<bool>(rVal);
+ if( !b )
+ return false;
+
+ SetValue( *b );
+ return true;
+}
+
+// --- fill attributes ---
+
+
+SfxPoolItem* XFillStyleItem::CreateDefault() { return new XFillStyleItem; }
+
+XFillStyleItem::XFillStyleItem(drawing::FillStyle eFillStyle) :
+ SfxEnumItem(XATTR_FILLSTYLE, eFillStyle)
+{
+}
+
+XFillStyleItem* XFillStyleItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFillStyleItem( *this );
+}
+
+bool XFillStyleItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+
+ const char* pId = nullptr;
+
+ switch( GetValue() )
+ {
+ case drawing::FillStyle_NONE:
+ pId = RID_SVXSTR_INVISIBLE;
+ break;
+ case drawing::FillStyle_SOLID:
+ pId = RID_SVXSTR_SOLID;
+ break;
+ case drawing::FillStyle_GRADIENT:
+ pId = RID_SVXSTR_GRADIENT;
+ break;
+ case drawing::FillStyle_HATCH:
+ pId = RID_SVXSTR_HATCH;
+ break;
+ case drawing::FillStyle_BITMAP:
+ pId = RID_SVXSTR_BITMAP;
+ break;
+ default: break;
+ }
+
+ if (pId)
+ rText = SvxResId(pId);
+ return true;
+}
+
+sal_uInt16 XFillStyleItem::GetValueCount() const
+{
+ return 5;
+}
+
+bool XFillStyleItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ css::drawing::FillStyle eFS = GetValue();
+
+ rVal <<= eFS;
+
+ return true;
+}
+
+bool XFillStyleItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ css::drawing::FillStyle eFS;
+ if(!(rVal >>= eFS))
+ {
+ // also try an int (for Basic)
+ sal_Int32 nFS = 0;
+ if(!(rVal >>= nFS))
+ return false;
+ eFS = static_cast<css::drawing::FillStyle>(nFS);
+ }
+
+ SetValue( eFS );
+
+ return true;
+}
+
+void XFillStyleItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillStyleItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(static_cast<sal_Int16>(GetValue())).getStr()));
+
+ OUString aPresentation;
+ IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+ GetPresentation(SfxItemPresentation::Nameless, MapUnit::Map100thMM, MapUnit::Map100thMM, aPresentation, aIntlWrapper);
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"), BAD_CAST(aPresentation.toUtf8().getStr()));
+
+ xmlTextWriterEndElement(pWriter);
+}
+
+boost::property_tree::ptree XFillStyleItem::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+
+ if (Which() == XATTR_FILLSTYLE)
+ aTree.put("commandName", ".uno:FillStyle");
+
+ OUString sValue;
+
+ switch( GetValue() )
+ {
+ case drawing::FillStyle_NONE:
+ sValue = "NONE";
+ break;
+ case drawing::FillStyle_SOLID:
+ sValue = "SOLID";
+ break;
+ case drawing::FillStyle_GRADIENT:
+ sValue = "GRADIENT";
+ break;
+ case drawing::FillStyle_HATCH:
+ sValue = "HATCH";
+ break;
+ case drawing::FillStyle_BITMAP:
+ sValue = "BITMAP";
+ break;
+ default: break;
+ }
+
+ aTree.put("state", sValue);
+
+ return aTree;
+}
+
+
+SfxPoolItem* XFillColorItem::CreateDefault() { return new XFillColorItem; }
+
+XFillColorItem::XFillColorItem(sal_Int32 nIndex, const Color& rTheColor) :
+ XColorItem(XATTR_FILLCOLOR, nIndex, rTheColor)
+{
+}
+
+XFillColorItem::XFillColorItem(const OUString& rName, const Color& rTheColor) :
+ XColorItem(XATTR_FILLCOLOR, rName, rTheColor)
+{
+}
+
+XFillColorItem* XFillColorItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFillColorItem(*this);
+}
+
+bool XFillColorItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XFillColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= GetColorValue().GetRGBColor();
+
+ return true;
+}
+
+bool XFillColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ if(!(rVal >>= nValue ))
+ return false;
+
+ SetColorValue( Color(nValue) );
+ return true;
+}
+
+void XFillColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillColorItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(GetColorValue().AsRGBHexString().toUtf8().getStr()));
+ xmlTextWriterEndElement(pWriter);
+}
+
+boost::property_tree::ptree XFillColorItem::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+
+ if (Which() == XATTR_FILLCOLOR)
+ aTree.put("commandName", ".uno:FillPageColor");
+
+ aTree.put("state", GetColorValue().AsRGBHexString());
+
+ return aTree;
+}
+
+XSecondaryFillColorItem::XSecondaryFillColorItem(const OUString& rName, const Color& rTheColor) :
+ XColorItem(XATTR_SECONDARYFILLCOLOR, rName, rTheColor)
+{
+}
+
+XSecondaryFillColorItem* XSecondaryFillColorItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XSecondaryFillColorItem(*this);
+}
+
+bool XSecondaryFillColorItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+std::string XGradient::GradientStyleToString(css::awt::GradientStyle eStyle)
+{
+ switch (eStyle)
+ {
+ case css::awt::GradientStyle::GradientStyle_LINEAR:
+ return "LINEAR";
+
+ case css::awt::GradientStyle::GradientStyle_AXIAL:
+ return "AXIAL";
+
+ case css::awt::GradientStyle::GradientStyle_RADIAL:
+ return "RADIAL";
+
+ case css::awt::GradientStyle::GradientStyle_ELLIPTICAL:
+ return "ELLIPTICAL";
+
+ case css::awt::GradientStyle::GradientStyle_SQUARE:
+ return "SQUARE";
+
+ case css::awt::GradientStyle::GradientStyle_RECT:
+ return "RECT";
+
+ case css::awt::GradientStyle::GradientStyle_MAKE_FIXED_SIZE:
+ return "MAKE_FIXED_SIZE";
+ }
+
+ return "";
+}
+
+namespace
+{
+ css::awt::GradientStyle lcl_getStyleFromString(const OUString& rStyle)
+ {
+ if (rStyle == "LINEAR")
+ return css::awt::GradientStyle_LINEAR;
+ else if (rStyle == "AXIAL")
+ return css::awt::GradientStyle_AXIAL;
+ else if (rStyle == "RADIAL")
+ return css::awt::GradientStyle_RADIAL;
+ else if (rStyle == "ELLIPTICAL")
+ return css::awt::GradientStyle_ELLIPTICAL;
+ else if (rStyle == "SQUARE")
+ return css::awt::GradientStyle_SQUARE;
+ else if (rStyle == "RECT")
+ return css::awt::GradientStyle_RECT;
+
+ return css::awt::GradientStyle_LINEAR;
+ }
+
+ StringMap lcl_jsonToStringMap(const OUString& rJSON)
+ {
+ StringMap aArgs;
+ if (rJSON.getLength() && rJSON[0] != '\0')
+ {
+ std::stringstream aStream(OUStringToOString(rJSON, RTL_TEXTENCODING_ASCII_US).getStr());
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+
+ for (const auto& rPair : aTree)
+ {
+ aArgs[OUString::fromUtf8(rPair.first.c_str())] = OUString::fromUtf8(rPair.second.get_value<std::string>(".").c_str());
+ }
+ }
+ return aArgs;
+ }
+
+ XGradient lcl_buildGradientFromStringMap(StringMap& rMap)
+ {
+ XGradient aGradient;
+
+ aGradient.SetStartColor(rMap["startcolor"].toInt32(16));
+ aGradient.SetEndColor(rMap["endcolor"].toInt32(16));
+ aGradient.SetGradientStyle(lcl_getStyleFromString(rMap["style"]));
+ aGradient.SetAngle(rMap["angle"].toInt32());
+
+ return aGradient;
+ }
+}
+
+XGradient XGradient::fromJSON(const OUString& rJSON)
+{
+ StringMap aMap(lcl_jsonToStringMap(rJSON));
+ return lcl_buildGradientFromStringMap(aMap);
+}
+
+XGradient::XGradient() :
+ eStyle( css::awt::GradientStyle_LINEAR ),
+ aStartColor( COL_BLACK ),
+ aEndColor( COL_WHITE ),
+ nAngle( 0 ),
+ nBorder( 0 ),
+ nOfsX( 50 ),
+ nOfsY( 50 ),
+ nIntensStart( 100 ),
+ nIntensEnd( 100 ),
+ nStepCount( 0 )
+{
+}
+
+XGradient::XGradient(const Color& rStart, const Color& rEnd,
+ css::awt::GradientStyle eTheStyle, long nTheAngle, sal_uInt16 nXOfs,
+ sal_uInt16 nYOfs, sal_uInt16 nTheBorder,
+ sal_uInt16 nStartIntens, sal_uInt16 nEndIntens,
+ sal_uInt16 nSteps) :
+ eStyle(eTheStyle),
+ aStartColor(rStart),
+ aEndColor(rEnd),
+ nAngle(nTheAngle),
+ nBorder(nTheBorder),
+ nOfsX(nXOfs),
+ nOfsY(nYOfs),
+ nIntensStart(nStartIntens),
+ nIntensEnd(nEndIntens),
+ nStepCount(nSteps)
+{
+}
+
+bool XGradient::operator==(const XGradient& rGradient) const
+{
+ return ( eStyle == rGradient.eStyle &&
+ aStartColor == rGradient.aStartColor &&
+ aEndColor == rGradient.aEndColor &&
+ nAngle == rGradient.nAngle &&
+ nBorder == rGradient.nBorder &&
+ nOfsX == rGradient.nOfsX &&
+ nOfsY == rGradient.nOfsY &&
+ nIntensStart == rGradient.nIntensStart &&
+ nIntensEnd == rGradient.nIntensEnd &&
+ nStepCount == rGradient.nStepCount );
+}
+
+boost::property_tree::ptree XGradient::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree;
+
+ aTree.put("style", XGradient::GradientStyleToString(eStyle));
+ aTree.put("startcolor",aStartColor.AsRGBHexString());
+ aTree.put("endcolor", aEndColor.AsRGBHexString());
+ aTree.put("angle", std::to_string(nAngle));
+ aTree.put("border", std::to_string(nBorder));
+ aTree.put("x", std::to_string(nOfsX));
+ aTree.put("y", std::to_string(nOfsY));
+ aTree.put("intensstart", std::to_string(nIntensStart));
+ aTree.put("intensend", std::to_string(nIntensEnd));
+ aTree.put("stepcount", std::to_string(nStepCount));
+
+ return aTree;
+}
+
+SfxPoolItem* XFillGradientItem::CreateDefault() { return new XFillGradientItem; }
+
+XFillGradientItem::XFillGradientItem(sal_Int32 nIndex,
+ const XGradient& rTheGradient) :
+ NameOrIndex(XATTR_FILLGRADIENT, nIndex),
+ aGradient(rTheGradient)
+{
+}
+
+XFillGradientItem::XFillGradientItem(const OUString& rName,
+ const XGradient& rTheGradient, sal_uInt16 nWhich)
+ : NameOrIndex(nWhich, rName)
+ , aGradient(rTheGradient)
+{
+}
+
+XFillGradientItem::XFillGradientItem(const XFillGradientItem& rItem) :
+ NameOrIndex(rItem),
+ aGradient(rItem.aGradient)
+{
+}
+
+XFillGradientItem::XFillGradientItem( const XGradient& rTheGradient )
+: NameOrIndex( XATTR_FILLGRADIENT, -1 ),
+ aGradient(rTheGradient)
+{
+}
+
+XFillGradientItem* XFillGradientItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFillGradientItem(*this);
+}
+
+bool XFillGradientItem::operator==(const SfxPoolItem& rItem) const
+{
+ return ( NameOrIndex::operator==(rItem) &&
+ aGradient == static_cast<const XFillGradientItem&>(rItem).aGradient );
+}
+
+const XGradient& XFillGradientItem::GetGradientValue() const // GetValue -> GetGradientValue
+{
+ if (!IsIndex())
+ return aGradient;
+ // ToDo: This should fail. We never called this code with a table so this should always
+ // have failed. Thus, I'm thinking that XFillGradientItem can't be an Index.
+ return aGradient;
+}
+
+bool XFillGradientItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XFillGradientItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
+
+ css::awt::Gradient aGradient2;
+
+ const XGradient& aXGradient = GetGradientValue();
+ aGradient2.Style = aXGradient.GetGradientStyle();
+ aGradient2.StartColor = static_cast<sal_Int32>(aXGradient.GetStartColor());
+ aGradient2.EndColor = static_cast<sal_Int32>(aXGradient.GetEndColor());
+ aGradient2.Angle = static_cast<short>(aXGradient.GetAngle());
+ aGradient2.Border = aXGradient.GetBorder();
+ aGradient2.XOffset = aXGradient.GetXOffset();
+ aGradient2.YOffset = aXGradient.GetYOffset();
+ aGradient2.StartIntensity = aXGradient.GetStartIntens();
+ aGradient2.EndIntensity = aXGradient.GetEndIntens();
+ aGradient2.StepCount = aXGradient.GetSteps();
+
+ aPropSeq[0].Name = "Name";
+ aPropSeq[0].Value <<= SvxUnogetApiNameForItem(Which(), GetName());
+ aPropSeq[1].Name = "FillGradient";
+ aPropSeq[1].Value <<= aGradient2;
+ rVal <<= aPropSeq;
+ break;
+ }
+
+ case MID_FILLGRADIENT:
+ {
+ const XGradient& aXGradient = GetGradientValue();
+ css::awt::Gradient aGradient2;
+
+ aGradient2.Style = aXGradient.GetGradientStyle();
+ aGradient2.StartColor = static_cast<sal_Int32>(aXGradient.GetStartColor());
+ aGradient2.EndColor = static_cast<sal_Int32>(aXGradient.GetEndColor());
+ aGradient2.Angle = static_cast<short>(aXGradient.GetAngle());
+ aGradient2.Border = aXGradient.GetBorder();
+ aGradient2.XOffset = aXGradient.GetXOffset();
+ aGradient2.YOffset = aXGradient.GetYOffset();
+ aGradient2.StartIntensity = aXGradient.GetStartIntens();
+ aGradient2.EndIntensity = aXGradient.GetEndIntens();
+ aGradient2.StepCount = aXGradient.GetSteps();
+
+ rVal <<= aGradient2;
+ break;
+ }
+
+ case MID_NAME:
+ {
+ rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
+ break;
+ }
+
+ case MID_GRADIENT_STYLE: rVal <<= static_cast<sal_Int16>(GetGradientValue().GetGradientStyle()); break;
+ case MID_GRADIENT_STARTCOLOR: rVal <<= GetGradientValue().GetStartColor(); break;
+ case MID_GRADIENT_ENDCOLOR: rVal <<= GetGradientValue().GetEndColor(); break;
+ case MID_GRADIENT_ANGLE: rVal <<= static_cast<sal_Int16>(GetGradientValue().GetAngle()); break;
+ case MID_GRADIENT_BORDER: rVal <<= GetGradientValue().GetBorder(); break;
+ case MID_GRADIENT_XOFFSET: rVal <<= GetGradientValue().GetXOffset(); break;
+ case MID_GRADIENT_YOFFSET: rVal <<= GetGradientValue().GetYOffset(); break;
+ case MID_GRADIENT_STARTINTENSITY: rVal <<= GetGradientValue().GetStartIntens(); break;
+ case MID_GRADIENT_ENDINTENSITY: rVal <<= GetGradientValue().GetEndIntens(); break;
+ case MID_GRADIENT_STEPCOUNT: rVal <<= GetGradientValue().GetSteps(); break;
+
+ default: OSL_FAIL("Wrong MemberId!"); return false;
+ }
+
+ return true;
+}
+
+bool XFillGradientItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ uno::Sequence< beans::PropertyValue > aPropSeq;
+
+ if ( rVal >>= aPropSeq )
+ {
+ css::awt::Gradient aGradient2;
+ OUString aName;
+ bool bGradient( false );
+ for ( const auto& rProp : std::as_const(aPropSeq) )
+ {
+ if ( rProp.Name == "Name" )
+ rProp.Value >>= aName;
+ else if ( rProp.Name == "FillGradient" )
+ {
+ if ( rProp.Value >>= aGradient2 )
+ bGradient = true;
+ }
+ }
+
+ SetName( aName );
+ if ( bGradient )
+ {
+ XGradient aXGradient;
+
+ aXGradient.SetGradientStyle( aGradient2.Style );
+ aXGradient.SetStartColor( Color(aGradient2.StartColor) );
+ aXGradient.SetEndColor( Color(aGradient2.EndColor) );
+ aXGradient.SetAngle( aGradient2.Angle );
+ aXGradient.SetBorder( aGradient2.Border );
+ aXGradient.SetXOffset( aGradient2.XOffset );
+ aXGradient.SetYOffset( aGradient2.YOffset );
+ aXGradient.SetStartIntens( aGradient2.StartIntensity );
+ aXGradient.SetEndIntens( aGradient2.EndIntensity );
+ aXGradient.SetSteps( aGradient2.StepCount );
+
+ SetGradientValue( aXGradient );
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ case MID_NAME:
+ {
+ OUString aName;
+ if (!(rVal >>= aName ))
+ return false;
+ SetName( aName );
+ break;
+ }
+
+ case MID_FILLGRADIENT:
+ {
+ css::awt::Gradient aGradient2;
+ if(!(rVal >>= aGradient2))
+ return false;
+
+ XGradient aXGradient;
+
+ aXGradient.SetGradientStyle( aGradient2.Style );
+ aXGradient.SetStartColor( Color(aGradient2.StartColor) );
+ aXGradient.SetEndColor( Color(aGradient2.EndColor) );
+ aXGradient.SetAngle( aGradient2.Angle );
+ aXGradient.SetBorder( aGradient2.Border );
+ aXGradient.SetXOffset( aGradient2.XOffset );
+ aXGradient.SetYOffset( aGradient2.YOffset );
+ aXGradient.SetStartIntens( aGradient2.StartIntensity );
+ aXGradient.SetEndIntens( aGradient2.EndIntensity );
+ aXGradient.SetSteps( aGradient2.StepCount );
+
+ SetGradientValue( aXGradient );
+ break;
+ }
+
+ case MID_GRADIENT_STARTCOLOR:
+ case MID_GRADIENT_ENDCOLOR:
+ {
+ sal_Int32 nVal = 0;
+ if(!(rVal >>= nVal ))
+ return false;
+
+ XGradient aXGradient = GetGradientValue();
+
+ if ( nMemberId == MID_GRADIENT_STARTCOLOR )
+ aXGradient.SetStartColor( Color(nVal) );
+ else
+ aXGradient.SetEndColor( Color(nVal) );
+ SetGradientValue( aXGradient );
+ break;
+ }
+
+ case MID_GRADIENT_STYLE:
+ case MID_GRADIENT_ANGLE:
+ case MID_GRADIENT_BORDER:
+ case MID_GRADIENT_STARTINTENSITY:
+ case MID_GRADIENT_ENDINTENSITY:
+ case MID_GRADIENT_STEPCOUNT:
+ case MID_GRADIENT_XOFFSET:
+ case MID_GRADIENT_YOFFSET:
+ {
+ sal_Int16 nVal = sal_Int16();
+ if(!(rVal >>= nVal ))
+ return false;
+
+ XGradient aXGradient = GetGradientValue();
+
+ switch ( nMemberId )
+ {
+ case MID_GRADIENT_STYLE:
+ aXGradient.SetGradientStyle( static_cast<css::awt::GradientStyle>(nVal) ); break;
+ case MID_GRADIENT_ANGLE:
+ aXGradient.SetAngle( nVal ); break;
+ case MID_GRADIENT_BORDER:
+ aXGradient.SetBorder( nVal ); break;
+ case MID_GRADIENT_STARTINTENSITY:
+ aXGradient.SetStartIntens( nVal ); break;
+ case MID_GRADIENT_ENDINTENSITY:
+ aXGradient.SetEndIntens( nVal ); break;
+ case MID_GRADIENT_STEPCOUNT:
+ aXGradient.SetSteps( nVal ); break;
+ case MID_GRADIENT_XOFFSET:
+ aXGradient.SetXOffset( nVal ); break;
+ case MID_GRADIENT_YOFFSET:
+ aXGradient.SetYOffset( nVal ); break;
+ }
+
+ SetGradientValue( aXGradient );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool XFillGradientItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
+{
+ return static_cast<const XFillGradientItem*>(p1)->GetGradientValue() == static_cast<const XFillGradientItem*>(p2)->GetGradientValue();
+}
+
+std::unique_ptr<XFillGradientItem> XFillGradientItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ if( pModel )
+ {
+ const OUString aUniqueName = NameOrIndex::CheckNamedItem(
+ this, Which(), &pModel->GetItemPool(),
+ XFillGradientItem::CompareValueFunc, RID_SVXSTR_GRADIENT,
+ pModel->GetPropertyList( XPropertyListType::Gradient ) );
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() )
+ return std::make_unique<XFillGradientItem>( aUniqueName, aGradient, Which() );
+ }
+
+ return nullptr;
+}
+
+boost::property_tree::ptree XFillGradientItem::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
+
+ if (Which() == XATTR_FILLGRADIENT)
+ aTree.put("commandName", ".uno:FillGradient");
+
+ aTree.push_back(std::make_pair("state", GetGradientValue().dumpAsJSON()));
+
+ return aTree;
+}
+
+
+SfxPoolItem* XFillFloatTransparenceItem::CreateDefault() { return new XFillFloatTransparenceItem; }
+
+XFillFloatTransparenceItem::XFillFloatTransparenceItem() :
+ bEnabled( false )
+{
+ SetWhich( XATTR_FILLFLOATTRANSPARENCE );
+}
+
+XFillFloatTransparenceItem::XFillFloatTransparenceItem(const OUString& rName, const XGradient& rGradient, bool bEnable ) :
+ XFillGradientItem ( rName, rGradient ),
+ bEnabled ( bEnable )
+{
+ SetWhich( XATTR_FILLFLOATTRANSPARENCE );
+}
+
+XFillFloatTransparenceItem::XFillFloatTransparenceItem( const XFillFloatTransparenceItem& rItem ) :
+ XFillGradientItem ( rItem ),
+ bEnabled ( rItem.bEnabled )
+{
+ SetWhich( XATTR_FILLFLOATTRANSPARENCE );
+}
+
+XFillFloatTransparenceItem::XFillFloatTransparenceItem(const XGradient& rTheGradient, bool bEnable )
+: XFillGradientItem ( -1, rTheGradient ),
+ bEnabled ( bEnable )
+{
+ SetWhich( XATTR_FILLFLOATTRANSPARENCE );
+}
+
+bool XFillFloatTransparenceItem::operator==( const SfxPoolItem& rItem ) const
+{
+ return ( NameOrIndex::operator==(rItem) ) &&
+ ( GetGradientValue() == static_cast<const XFillGradientItem&>(rItem).GetGradientValue() ) &&
+ ( bEnabled == static_cast<const XFillFloatTransparenceItem&>(rItem).bEnabled );
+}
+
+XFillFloatTransparenceItem* XFillFloatTransparenceItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillFloatTransparenceItem( *this );
+}
+
+bool XFillFloatTransparenceItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ return XFillGradientItem::QueryValue( rVal, nMemberId );
+}
+
+bool XFillFloatTransparenceItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ return XFillGradientItem::PutValue( rVal, nMemberId );
+}
+
+bool XFillFloatTransparenceItem::GetPresentation( SfxItemPresentation ePres,
+ MapUnit eCoreUnit, MapUnit ePresUnit,
+ OUString& rText,
+ const IntlWrapper& rIntlWrapper ) const
+{
+ return XFillGradientItem::GetPresentation( ePres, eCoreUnit, ePresUnit, rText, rIntlWrapper );
+}
+
+bool XFillFloatTransparenceItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
+{
+ return static_cast<const XFillFloatTransparenceItem*>(p1)->IsEnabled() == static_cast<const XFillFloatTransparenceItem*>(p2)->IsEnabled() &&
+ static_cast<const XFillFloatTransparenceItem*>(p1)->GetGradientValue() == static_cast<const XFillFloatTransparenceItem*>(p2)->GetGradientValue();
+}
+
+std::unique_ptr<XFillFloatTransparenceItem> XFillFloatTransparenceItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ // #85953# unique name only necessary when enabled
+ if(IsEnabled())
+ {
+ if( pModel )
+ {
+ const OUString aUniqueName = NameOrIndex::CheckNamedItem( this,
+ XATTR_FILLFLOATTRANSPARENCE,
+ &pModel->GetItemPool(),
+ XFillFloatTransparenceItem::CompareValueFunc,
+ RID_SVXSTR_TRASNGR0,
+ XPropertyListRef() );
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() )
+ {
+ return std::make_unique<XFillFloatTransparenceItem>( aUniqueName, GetGradientValue(), true );
+ }
+ }
+ }
+ else
+ {
+ // #85953# if disabled, force name to empty string
+ if( !GetName().isEmpty() )
+ {
+ return std::make_unique<XFillFloatTransparenceItem>(OUString(), GetGradientValue(), false);
+ }
+ }
+
+ return nullptr;
+}
+
+boost::property_tree::ptree XFillFloatTransparenceItem::dumpAsJSON() const
+{
+ boost::property_tree::ptree aTree = XFillGradientItem::dumpAsJSON();
+ aTree.put("commandName", ".uno:FillFloatTransparence");
+
+ if (!bEnabled)
+ {
+ boost::property_tree::ptree& rState = aTree.get_child("state");
+ // When gradient fill is disabled, the intensity fields contain the
+ // constant encoded percent-transparency. However we use that here to just
+ // distinguish between 'None' and 'Solid' types and correct the 'style'
+ // property appropriately.
+ if (GetGradientValue().GetStartIntens() == 100)
+ rState.put("style", "NONE");
+ else
+ rState.put("style", "SOLID");
+ }
+
+ return aTree;
+}
+
+XHatch::XHatch(const Color& rCol, css::drawing::HatchStyle eTheStyle, long nTheDistance,
+ long nTheAngle) :
+ eStyle(eTheStyle),
+ aColor(rCol),
+ nDistance(nTheDistance),
+ nAngle(nTheAngle)
+{
+}
+
+bool XHatch::operator==(const XHatch& rHatch) const
+{
+ return ( eStyle == rHatch.eStyle &&
+ aColor == rHatch.aColor &&
+ nDistance == rHatch.nDistance &&
+ nAngle == rHatch.nAngle );
+}
+
+
+SfxPoolItem* XFillHatchItem::CreateDefault() { return new XFillHatchItem; }
+
+XFillHatchItem::XFillHatchItem(const OUString& rName,
+ const XHatch& rTheHatch) :
+ NameOrIndex(XATTR_FILLHATCH, rName),
+ aHatch(rTheHatch)
+{
+}
+
+XFillHatchItem::XFillHatchItem(const XFillHatchItem& rItem) :
+ NameOrIndex(rItem),
+ aHatch(rItem.aHatch)
+{
+}
+
+XFillHatchItem::XFillHatchItem(const XHatch& rTheHatch)
+: NameOrIndex( XATTR_FILLHATCH, -1 ),
+ aHatch(rTheHatch)
+{
+}
+
+XFillHatchItem* XFillHatchItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFillHatchItem(*this);
+}
+
+bool XFillHatchItem::operator==(const SfxPoolItem& rItem) const
+{
+ return ( NameOrIndex::operator==(rItem) &&
+ aHatch == static_cast<const XFillHatchItem&>(rItem).aHatch );
+}
+
+bool XFillHatchItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText = GetName();
+ return true;
+}
+
+bool XFillHatchItem::HasMetrics() const
+{
+ return true;
+}
+
+void XFillHatchItem::ScaleMetrics(long nMul, long nDiv)
+{
+ aHatch.SetDistance( ScaleMetricValue( aHatch.GetDistance(), nMul, nDiv ) );
+}
+
+bool XFillHatchItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
+
+ css::drawing::Hatch aUnoHatch;
+
+ aUnoHatch.Style = aHatch.GetHatchStyle();
+ aUnoHatch.Color = sal_Int32(aHatch.GetColor());
+ aUnoHatch.Distance = aHatch.GetDistance();
+ aUnoHatch.Angle = aHatch.GetAngle();
+
+ aPropSeq[0].Name = "Name";
+ aPropSeq[0].Value <<= SvxUnogetApiNameForItem(Which(), GetName());
+ aPropSeq[1].Name = "FillHatch";
+ aPropSeq[1].Value <<= aUnoHatch;
+ rVal <<= aPropSeq;
+ break;
+ }
+
+ case MID_FILLHATCH:
+ {
+ css::drawing::Hatch aUnoHatch;
+
+ aUnoHatch.Style = aHatch.GetHatchStyle();
+ aUnoHatch.Color = sal_Int32(aHatch.GetColor());
+ aUnoHatch.Distance = aHatch.GetDistance();
+ aUnoHatch.Angle = aHatch.GetAngle();
+ rVal <<= aUnoHatch;
+ break;
+ }
+
+ case MID_NAME:
+ {
+ rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
+ break;
+ }
+
+ case MID_HATCH_STYLE:
+ rVal <<= aHatch.GetHatchStyle(); break;
+ case MID_HATCH_COLOR:
+ rVal <<= aHatch.GetColor(); break;
+ case MID_HATCH_DISTANCE:
+ rVal <<= aHatch.GetDistance(); break;
+ case MID_HATCH_ANGLE:
+ rVal <<= aHatch.GetAngle(); break;
+
+ default: OSL_FAIL("Wrong MemberId!"); return false;
+ }
+
+ return true;
+}
+
+bool XFillHatchItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ switch ( nMemberId )
+ {
+ case 0:
+ {
+ uno::Sequence< beans::PropertyValue > aPropSeq;
+ if ( rVal >>= aPropSeq )
+ {
+ css::drawing::Hatch aUnoHatch;
+ OUString aName;
+ bool bHatch( false );
+ for ( const auto& rProp : std::as_const(aPropSeq) )
+ {
+ if ( rProp.Name == "Name" )
+ rProp.Value >>= aName;
+ else if ( rProp.Name == "FillHatch" )
+ {
+ if ( rProp.Value >>= aUnoHatch )
+ bHatch = true;
+ }
+ }
+
+ SetName( aName );
+ if ( bHatch )
+ {
+ aHatch.SetHatchStyle( aUnoHatch.Style );
+ aHatch.SetColor( Color(aUnoHatch.Color) );
+ aHatch.SetDistance( aUnoHatch.Distance );
+ aHatch.SetAngle( aUnoHatch.Angle );
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ case MID_FILLHATCH:
+ {
+ css::drawing::Hatch aUnoHatch;
+ if(!(rVal >>= aUnoHatch))
+ return false;
+
+ aHatch.SetHatchStyle( aUnoHatch.Style );
+ aHatch.SetColor( Color(aUnoHatch.Color) );
+ aHatch.SetDistance( aUnoHatch.Distance );
+ aHatch.SetAngle( aUnoHatch.Angle );
+ break;
+ }
+
+ case MID_NAME:
+ {
+ OUString aName;
+ if (!(rVal >>= aName ))
+ return false;
+ SetName( aName );
+ break;
+ }
+
+ case MID_HATCH_STYLE:
+ {
+ sal_Int16 nVal = sal_Int16();
+ if (!(rVal >>= nVal ))
+ return false;
+ aHatch.SetHatchStyle( static_cast<css::drawing::HatchStyle>(nVal) );
+ break;
+ }
+
+ case MID_HATCH_COLOR:
+ case MID_HATCH_DISTANCE:
+ case MID_HATCH_ANGLE:
+ {
+ sal_Int32 nVal = 0;
+ if (!(rVal >>= nVal ))
+ return false;
+
+ if ( nMemberId == MID_HATCH_COLOR )
+ aHatch.SetColor( Color(nVal) );
+ else if ( nMemberId == MID_HATCH_DISTANCE )
+ aHatch.SetDistance( nVal );
+ else
+ aHatch.SetAngle( nVal );
+ break;
+ }
+
+ default: OSL_FAIL("Wrong MemberId!"); return false;
+ }
+
+ return true;
+}
+
+bool XFillHatchItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
+{
+ return static_cast<const XFillHatchItem*>(p1)->GetHatchValue() == static_cast<const XFillHatchItem*>(p2)->GetHatchValue();
+}
+
+std::unique_ptr<XFillHatchItem> XFillHatchItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ if( pModel )
+ {
+ const OUString aUniqueName = NameOrIndex::CheckNamedItem(
+ this, XATTR_FILLHATCH, &pModel->GetItemPool(),
+ XFillHatchItem::CompareValueFunc, RID_SVXSTR_HATCH10,
+ pModel->GetPropertyList( XPropertyListType::Hatch ) );
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() )
+ return std::make_unique<XFillHatchItem>( aUniqueName, aHatch );
+ }
+
+ return nullptr;
+}
+
+// --- form text attributes ---
+
+
+SfxPoolItem* XFormTextStyleItem::CreateDefault() { return new XFormTextStyleItem; }
+
+XFormTextStyleItem::XFormTextStyleItem(XFormTextStyle eTheStyle) :
+ SfxEnumItem(XATTR_FORMTXTSTYLE, eTheStyle)
+{
+}
+
+XFormTextStyleItem* XFormTextStyleItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextStyleItem( *this );
+}
+
+sal_uInt16 XFormTextStyleItem::GetValueCount() const
+{
+ return 5;
+}
+
+bool XFormTextStyleItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= static_cast<sal_Int32>(GetValue());
+ return true;
+}
+
+bool XFormTextStyleItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ SetValue(static_cast<XFormTextStyle>(nValue));
+
+ return true;
+}
+
+
+SfxPoolItem* XFormTextAdjustItem::CreateDefault() { return new XFormTextAdjustItem; }
+
+XFormTextAdjustItem::XFormTextAdjustItem(XFormTextAdjust eTheAdjust) :
+ SfxEnumItem(XATTR_FORMTXTADJUST, eTheAdjust)
+{
+}
+
+XFormTextAdjustItem* XFormTextAdjustItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextAdjustItem( *this );
+}
+
+sal_uInt16 XFormTextAdjustItem::GetValueCount() const
+{
+ return 4;
+}
+
+bool XFormTextAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= static_cast<sal_Int32>(GetValue());
+ return true;
+}
+
+bool XFormTextAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ SetValue(static_cast<XFormTextAdjust>(nValue));
+
+ return true;
+}
+
+
+SfxPoolItem* XFormTextDistanceItem::CreateDefault() { return new XFormTextDistanceItem; }
+
+XFormTextDistanceItem::XFormTextDistanceItem(long nDist) :
+ SfxMetricItem(XATTR_FORMTXTDISTANCE, nDist)
+{
+}
+
+XFormTextDistanceItem* XFormTextDistanceItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextDistanceItem(*this);
+}
+
+SfxPoolItem* XFormTextStartItem::CreateDefault() { return new XFormTextStartItem; }
+
+XFormTextStartItem::XFormTextStartItem(long nStart) :
+ SfxMetricItem(XATTR_FORMTXTSTART, nStart)
+{
+}
+
+XFormTextStartItem* XFormTextStartItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextStartItem(*this);
+}
+
+SfxPoolItem* XFormTextMirrorItem::CreateDefault() { return new XFormTextMirrorItem; }
+
+XFormTextMirrorItem::XFormTextMirrorItem(bool bMirror) :
+ SfxBoolItem(XATTR_FORMTXTMIRROR, bMirror)
+{
+}
+
+XFormTextMirrorItem* XFormTextMirrorItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextMirrorItem(*this);
+}
+
+SfxPoolItem* XFormTextOutlineItem::CreateDefault() { return new XFormTextOutlineItem; }
+
+XFormTextOutlineItem::XFormTextOutlineItem(bool bOutline) :
+ SfxBoolItem(XATTR_FORMTXTOUTLINE, bOutline)
+{
+}
+
+XFormTextOutlineItem* XFormTextOutlineItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextOutlineItem(*this);
+}
+
+SfxPoolItem* XFormTextShadowItem::CreateDefault() { return new XFormTextShadowItem; }
+
+XFormTextShadowItem::XFormTextShadowItem(XFormTextShadow eFormTextShadow) :
+ SfxEnumItem(XATTR_FORMTXTSHADOW, eFormTextShadow)
+{
+}
+
+XFormTextShadowItem* XFormTextShadowItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextShadowItem( *this );
+}
+
+sal_uInt16 XFormTextShadowItem::GetValueCount() const
+{
+ return 3;
+}
+
+bool XFormTextShadowItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ rVal <<= static_cast<sal_Int32>(GetValue());
+ return true;
+}
+
+bool XFormTextShadowItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ sal_Int32 nValue = 0;
+ rVal >>= nValue;
+ SetValue(static_cast<XFormTextShadow>(nValue));
+
+ return true;
+}
+
+
+SfxPoolItem* XFormTextShadowColorItem::CreateDefault() { return new XFormTextShadowColorItem; }
+
+XFormTextShadowColorItem::XFormTextShadowColorItem(const OUString& rName,
+ const Color& rTheColor) :
+ XColorItem(XATTR_FORMTXTSHDWCOLOR, rName, rTheColor)
+{
+}
+
+XFormTextShadowColorItem* XFormTextShadowColorItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextShadowColorItem(*this);
+}
+
+SfxPoolItem* XFormTextShadowXValItem::CreateDefault() { return new XFormTextShadowXValItem; }
+
+XFormTextShadowXValItem::XFormTextShadowXValItem(long nVal) :
+ SfxMetricItem(XATTR_FORMTXTSHDWXVAL, nVal)
+{
+}
+
+XFormTextShadowXValItem* XFormTextShadowXValItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextShadowXValItem(*this);
+}
+
+SfxPoolItem* XFormTextShadowYValItem::CreateDefault() { return new XFormTextShadowYValItem; }
+
+XFormTextShadowYValItem::XFormTextShadowYValItem(long nVal) :
+ SfxMetricItem(XATTR_FORMTXTSHDWYVAL, nVal)
+{
+}
+
+XFormTextShadowYValItem* XFormTextShadowYValItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextShadowYValItem(*this);
+}
+
+SfxPoolItem* XFormTextHideFormItem::CreateDefault() { return new XFormTextHideFormItem; }
+
+XFormTextHideFormItem::XFormTextHideFormItem(bool bHide) :
+ SfxBoolItem(XATTR_FORMTXTHIDEFORM, bHide)
+{
+}
+
+XFormTextHideFormItem* XFormTextHideFormItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextHideFormItem(*this);
+}
+
+// --- SetItems ---
+
+
+/// a line attribute set item
+XLineAttrSetItem::XLineAttrSetItem( std::unique_ptr<SfxItemSet>&& pItemSet ) :
+ SfxSetItem( XATTRSET_LINE, std::move(pItemSet))
+{
+}
+
+XLineAttrSetItem::XLineAttrSetItem( SfxItemPool* pItemPool ) :
+ SfxSetItem( XATTRSET_LINE,
+ std::make_unique<SfxItemSet>( *pItemPool, svl::Items<XATTR_LINE_FIRST, XATTR_LINE_LAST>{}))
+{
+}
+
+XLineAttrSetItem::XLineAttrSetItem( const XLineAttrSetItem& rLineAttr ) :
+ SfxSetItem( rLineAttr )
+{
+}
+
+XLineAttrSetItem::XLineAttrSetItem( const XLineAttrSetItem& rLineAttr,
+ SfxItemPool* pItemPool) :
+ SfxSetItem( rLineAttr, pItemPool )
+{
+}
+
+XLineAttrSetItem* XLineAttrSetItem::Clone( SfxItemPool* pPool ) const
+{
+ return new XLineAttrSetItem( *this, pPool );
+}
+
+/// fill attribute set item
+XFillAttrSetItem::XFillAttrSetItem( std::unique_ptr<SfxItemSet>&& pItemSet ) :
+ SfxSetItem( XATTRSET_FILL, std::move(pItemSet))
+{
+}
+
+XFillAttrSetItem::XFillAttrSetItem( SfxItemPool* pItemPool ) :
+ SfxSetItem( XATTRSET_FILL,
+ std::make_unique<SfxItemSet>( *pItemPool, svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{}))
+{
+}
+
+XFillAttrSetItem::XFillAttrSetItem( const XFillAttrSetItem& rFillAttr ) :
+ SfxSetItem( rFillAttr )
+{
+}
+
+XFillAttrSetItem::XFillAttrSetItem( const XFillAttrSetItem& rFillAttr,
+ SfxItemPool* pItemPool ) :
+ SfxSetItem( rFillAttr, pItemPool )
+{
+}
+
+XFillAttrSetItem* XFillAttrSetItem::Clone( SfxItemPool* pPool ) const
+{
+ return new XFillAttrSetItem( *this, pPool );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xattr2.cxx b/svx/source/xoutdev/xattr2.cxx
new file mode 100644
index 000000000..f3d57a06d
--- /dev/null
+++ b/svx/source/xoutdev/xattr2.cxx
@@ -0,0 +1,696 @@
+/* -*- 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/LineJoint.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+#include <osl/diagnose.h>
+#include <i18nutil/unicode.hxx>
+#include <svx/strings.hrc>
+#include <svx/svxids.hrc>
+#include <svx/xlinjoit.hxx>
+#include <svx/xlncapit.hxx>
+#include <svx/xlntrit.hxx>
+#include <svx/xfltrit.hxx>
+#include <xftshtit.hxx>
+#include <svx/xgrscit.hxx>
+#include <svx/xflbmtit.hxx>
+#include <svx/xflbmpit.hxx>
+#include <svx/xflbmsxy.hxx>
+#include <svx/xflbmsli.hxx>
+#include <svx/xflbtoxy.hxx>
+#include <svx/xflbstit.hxx>
+#include <svx/xflboxy.hxx>
+#include <svx/xflbckit.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/xdef.hxx>
+#include <AffineMatrixItem.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <comphelper/lok.hxx>
+
+#include <libxml/xmlwriter.h>
+
+XLineTransparenceItem::XLineTransparenceItem(sal_uInt16 nLineTransparence) :
+ SfxUInt16Item(XATTR_LINETRANSPARENCE, nLineTransparence)
+{
+}
+
+XLineTransparenceItem* XLineTransparenceItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineTransparenceItem(*this);
+}
+
+bool XLineTransparenceItem::GetPresentation
+(
+ SfxItemPresentation ePres,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+
+ switch ( ePres )
+ {
+ case SfxItemPresentation::Complete:
+ rText = SvxResId(RID_SVXSTR_TRANSPARENCE) + ": ";
+ [[fallthrough]];
+ case SfxItemPresentation::Nameless:
+ rText += unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag());
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+SfxPoolItem* XLineJointItem::CreateDefault() { return new XLineJointItem; }
+
+XLineJointItem::XLineJointItem( css::drawing::LineJoint eLineJoint ) :
+ SfxEnumItem(XATTR_LINEJOINT, eLineJoint)
+{
+}
+
+XLineJointItem* XLineJointItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineJointItem( *this );
+}
+
+bool XLineJointItem::GetPresentation( SfxItemPresentation /*ePres*/, MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/, OUString& rText, const IntlWrapper&) const
+{
+ rText.clear();
+
+ const char* pId = nullptr;
+
+ switch( GetValue() )
+ {
+ case css::drawing::LineJoint::LineJoint_MAKE_FIXED_SIZE:
+ case css::drawing::LineJoint_NONE:
+ pId = comphelper::LibreOfficeKit::isActive() ? RID_SVXSTR_INVISIBLE : RID_SVXSTR_NONE;
+ break;
+
+ case css::drawing::LineJoint_MIDDLE:
+ pId = RID_SVXSTR_LINEJOINT_MIDDLE;
+ break;
+
+
+ case css::drawing::LineJoint_BEVEL:
+ pId = RID_SVXSTR_LINEJOINT_BEVEL;
+ break;
+
+
+ case css::drawing::LineJoint_MITER:
+ pId = RID_SVXSTR_LINEJOINT_MITER;
+ break;
+
+
+ case css::drawing::LineJoint_ROUND:
+ pId = RID_SVXSTR_LINEJOINT_ROUND;
+ break;
+ }
+
+ if (pId)
+ rText = SvxResId(pId);
+
+ return true;
+}
+
+bool XLineJointItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ const css::drawing::LineJoint eJoint = GetValue();
+ rVal <<= eJoint;
+ return true;
+}
+
+bool XLineJointItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ css::drawing::LineJoint eUnoJoint;
+
+ if(!(rVal >>= eUnoJoint))
+ {
+ // also try an int (for Basic)
+ sal_Int32 nLJ = 0;
+ if(!(rVal >>= nLJ))
+ return false;
+ eUnoJoint = static_cast<css::drawing::LineJoint>(nLJ);
+ }
+
+ SetValue( eUnoJoint );
+
+ return true;
+}
+
+sal_uInt16 XLineJointItem::GetValueCount() const
+{
+ // don't forget to update the api interface also
+ return 5;
+}
+
+
+AffineMatrixItem::AffineMatrixItem(const css::geometry::AffineMatrix2D* pMatrix)
+: SfxPoolItem(SID_ATTR_TRANSFORM_MATRIX)
+{
+ if(pMatrix)
+ {
+ maMatrix = *pMatrix;
+ }
+ else
+ {
+ maMatrix.m00 = 1.0;
+ maMatrix.m01 = 0.0;
+ maMatrix.m02 = 0.0;
+ maMatrix.m10 = 0.0;
+ maMatrix.m11 = 1.0;
+ maMatrix.m12 = 0.0;
+ }
+}
+
+AffineMatrixItem::AffineMatrixItem(const AffineMatrixItem& rRef)
+: SfxPoolItem(rRef)
+{
+ maMatrix = rRef.maMatrix;
+}
+
+AffineMatrixItem::~AffineMatrixItem()
+{
+}
+
+bool AffineMatrixItem::operator==(const SfxPoolItem& rRef) const
+{
+ if(!SfxPoolItem::operator==(rRef))
+ {
+ return false;
+ }
+
+ const AffineMatrixItem* pRef = static_cast< const AffineMatrixItem* >(&rRef);
+
+ if(!pRef)
+ {
+ return false;
+ }
+
+ return (maMatrix.m00 == pRef->maMatrix.m00
+ && maMatrix.m01 == pRef->maMatrix.m01
+ && maMatrix.m02 == pRef->maMatrix.m02
+ && maMatrix.m10 == pRef->maMatrix.m10
+ && maMatrix.m11 == pRef->maMatrix.m11
+ && maMatrix.m12 == pRef->maMatrix.m12);
+}
+
+AffineMatrixItem* AffineMatrixItem::Clone( SfxItemPool* /*pPool*/ ) const
+{
+ return new AffineMatrixItem(*this);
+}
+
+bool AffineMatrixItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
+{
+ rVal <<= maMatrix;
+ return true;
+}
+
+bool AffineMatrixItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
+{
+ if (rVal >>= maMatrix)
+ {
+ return true;
+ }
+
+ OSL_ENSURE(false, "AffineMatrixItem::PutValue - Wrong type!");
+ return false;
+}
+
+
+SfxPoolItem* XLineCapItem::CreateDefault() { return new XLineCapItem; }
+
+XLineCapItem::XLineCapItem(css::drawing::LineCap eLineCap)
+: SfxEnumItem(XATTR_LINECAP, eLineCap)
+{
+}
+
+XLineCapItem* XLineCapItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XLineCapItem( *this );
+}
+
+bool XLineCapItem::GetPresentation( SfxItemPresentation /*ePres*/, MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/, OUString& rText, const IntlWrapper&) const
+{
+ const char* pId;
+
+ switch( GetValue() )
+ {
+ default: /*css::drawing::LineCap_BUTT*/
+ pId = RID_SVXSTR_LINECAP_BUTT;
+ break;
+
+ case css::drawing::LineCap_ROUND:
+ pId = RID_SVXSTR_LINECAP_ROUND;
+ break;
+
+ case css::drawing::LineCap_SQUARE:
+ pId = RID_SVXSTR_LINECAP_SQUARE;
+ break;
+ }
+
+ rText = SvxResId(pId);
+
+ return true;
+}
+
+bool XLineCapItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
+{
+ const css::drawing::LineCap eCap(GetValue());
+ rVal <<= eCap;
+ return true;
+}
+
+bool XLineCapItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
+{
+ css::drawing::LineCap eUnoCap;
+
+ if(!(rVal >>= eUnoCap))
+ {
+ // also try an int (for Basic)
+ sal_Int32 nLJ(0);
+
+ if(!(rVal >>= nLJ))
+ {
+ return false;
+ }
+
+ eUnoCap = static_cast<css::drawing::LineCap>(nLJ);
+ }
+
+ OSL_ENSURE(css::drawing::LineCap_BUTT == eUnoCap
+ || css::drawing::LineCap_ROUND == eUnoCap
+ || css::drawing::LineCap_SQUARE == eUnoCap, "Unknown enum value in XATTR_LINECAP (!)");
+
+ SetValue(eUnoCap);
+
+ return true;
+}
+
+sal_uInt16 XLineCapItem::GetValueCount() const
+{
+ // don't forget to update the api interface also
+ return 3;
+}
+
+css::drawing::LineCap XLineCapItem::GetValue() const
+{
+ const css::drawing::LineCap eRetval(SfxEnumItem::GetValue());
+ OSL_ENSURE(css::drawing::LineCap_BUTT == eRetval
+ || css::drawing::LineCap_ROUND == eRetval
+ || css::drawing::LineCap_SQUARE == eRetval, "Unknown enum value in XATTR_LINECAP (!)");
+
+ return eRetval;
+}
+
+XFillTransparenceItem::XFillTransparenceItem(sal_uInt16 nFillTransparence) :
+ SfxUInt16Item(XATTR_FILLTRANSPARENCE, nFillTransparence)
+{
+}
+
+XFillTransparenceItem* XFillTransparenceItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFillTransparenceItem(*this);
+}
+
+bool XFillTransparenceItem::GetPresentation
+(
+ SfxItemPresentation ePres,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+
+ switch ( ePres )
+ {
+ case SfxItemPresentation::Complete:
+ rText = SvxResId(RID_SVXSTR_TRANSPARENCE) + ": ";
+ [[fallthrough]];
+ case SfxItemPresentation::Nameless:
+ rText += unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag());
+ return true;
+ default:
+ return false;
+ }
+}
+
+void XFillTransparenceItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillTransparenceItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr()));
+ xmlTextWriterEndElement(pWriter);
+}
+
+
+XFormTextShadowTranspItem::XFormTextShadowTranspItem(sal_uInt16 nShdwTransparence) :
+ SfxUInt16Item(XATTR_FORMTXTSHDWTRANSP, nShdwTransparence)
+{
+}
+
+XFormTextShadowTranspItem* XFormTextShadowTranspItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFormTextShadowTranspItem(*this);
+}
+
+
+XGradientStepCountItem::XGradientStepCountItem( sal_uInt16 nStepCount ) :
+ SfxUInt16Item( XATTR_GRADIENTSTEPCOUNT, nStepCount )
+{
+}
+
+XGradientStepCountItem* XGradientStepCountItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XGradientStepCountItem( *this );
+}
+
+bool XGradientStepCountItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+
+ rText += OUString::number(GetValue());
+ return true;
+}
+
+
+XFillBmpTileItem::XFillBmpTileItem( bool bTile ) :
+ SfxBoolItem( XATTR_FILLBMP_TILE, bTile )
+{
+}
+
+XFillBmpTileItem* XFillBmpTileItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpTileItem( *this );
+}
+
+bool XFillBmpTileItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+void XFillBmpTileItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillBmpTileItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(GetValue()).getStr()));
+ xmlTextWriterEndElement(pWriter);
+}
+
+
+
+XFillBmpPosItem::XFillBmpPosItem( RectPoint eRP ) :
+ SfxEnumItem( XATTR_FILLBMP_POS, eRP )
+{
+}
+
+XFillBmpPosItem* XFillBmpPosItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpPosItem( *this );
+}
+
+bool XFillBmpPosItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+sal_uInt16 XFillBmpPosItem::GetValueCount() const
+{
+ return 9;
+}
+
+void XFillBmpPosItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillBmpPosItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(static_cast<int>(GetValue())).getStr()));
+ xmlTextWriterEndElement(pWriter);
+}
+
+
+XFillBmpSizeXItem::XFillBmpSizeXItem( long nSizeX ) :
+ SfxMetricItem( XATTR_FILLBMP_SIZEX, nSizeX )
+{
+}
+
+XFillBmpSizeXItem* XFillBmpSizeXItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpSizeXItem( *this );
+}
+
+bool XFillBmpSizeXItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+bool XFillBmpSizeXItem::HasMetrics() const
+{
+ return GetValue() > 0;
+}
+
+
+
+XFillBmpSizeYItem::XFillBmpSizeYItem( long nSizeY ) :
+ SfxMetricItem( XATTR_FILLBMP_SIZEY, nSizeY )
+{
+}
+
+XFillBmpSizeYItem* XFillBmpSizeYItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpSizeYItem( *this );
+}
+
+bool XFillBmpSizeYItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+bool XFillBmpSizeYItem::HasMetrics() const
+{
+ return GetValue() > 0;
+}
+
+
+XFillBmpSizeLogItem::XFillBmpSizeLogItem( bool bLog ) :
+ SfxBoolItem( XATTR_FILLBMP_SIZELOG, bLog )
+{
+}
+
+XFillBmpSizeLogItem* XFillBmpSizeLogItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpSizeLogItem( *this );
+}
+
+bool XFillBmpSizeLogItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+
+
+XFillBmpTileOffsetXItem::XFillBmpTileOffsetXItem( sal_uInt16 nOffX ) :
+ SfxUInt16Item( XATTR_FILLBMP_TILEOFFSETX, nOffX )
+{
+}
+
+XFillBmpTileOffsetXItem* XFillBmpTileOffsetXItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpTileOffsetXItem( *this );
+}
+
+bool XFillBmpTileOffsetXItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+
+XFillBmpTileOffsetYItem::XFillBmpTileOffsetYItem( sal_uInt16 nOffY ) :
+ SfxUInt16Item( XATTR_FILLBMP_TILEOFFSETY, nOffY )
+{
+}
+
+XFillBmpTileOffsetYItem* XFillBmpTileOffsetYItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpTileOffsetYItem( *this );
+}
+
+bool XFillBmpTileOffsetYItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+XFillBmpStretchItem::XFillBmpStretchItem( bool bStretch ) :
+ SfxBoolItem( XATTR_FILLBMP_STRETCH, bStretch )
+{
+}
+
+XFillBmpStretchItem* XFillBmpStretchItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpStretchItem( *this );
+}
+
+bool XFillBmpStretchItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+void XFillBmpStretchItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillBmpStretchItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(GetValue()).getStr()));
+ xmlTextWriterEndElement(pWriter);
+}
+
+
+XFillBmpPosOffsetXItem::XFillBmpPosOffsetXItem( sal_uInt16 nOffPosX ) :
+ SfxUInt16Item( XATTR_FILLBMP_POSOFFSETX, nOffPosX )
+{
+}
+
+XFillBmpPosOffsetXItem* XFillBmpPosOffsetXItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpPosOffsetXItem( *this );
+}
+
+bool XFillBmpPosOffsetXItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+
+XFillBmpPosOffsetYItem::XFillBmpPosOffsetYItem( sal_uInt16 nOffPosY ) :
+ SfxUInt16Item( XATTR_FILLBMP_POSOFFSETY, nOffPosY )
+{
+}
+
+XFillBmpPosOffsetYItem* XFillBmpPosOffsetYItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBmpPosOffsetYItem( *this );
+}
+
+bool XFillBmpPosOffsetYItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper&
+) const
+{
+ rText.clear();
+ return true;
+}
+
+XFillBackgroundItem::XFillBackgroundItem( bool bFill ) :
+ SfxBoolItem( XATTR_FILLBACKGROUND, bFill )
+{
+}
+
+XFillBackgroundItem* XFillBackgroundItem::Clone( SfxItemPool* /*pPool*/) const
+{
+ return new XFillBackgroundItem( *this );
+}
+
+bool XFillBackgroundItem::GetPresentation( SfxItemPresentation /*ePres*/, MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/, OUString& rText, const IntlWrapper&) const
+{
+ rText.clear();
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xattrbmp.cxx b/svx/source/xoutdev/xattrbmp.cxx
new file mode 100644
index 000000000..4288c9607
--- /dev/null
+++ b/svx/source/xoutdev/xattrbmp.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 <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <tools/debug.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <svl/style.hxx>
+#include <editeng/memberids.h>
+#include <svx/strings.hrc>
+#include <svx/xtable.hxx>
+#include <svx/xdef.hxx>
+#include <svx/unomid.hxx>
+#include <svx/unoapi.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/xbitmap.hxx>
+#include <svx/xbtmpit.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <vcl/BitmapTools.hxx>
+#include <vcl/GraphicLoader.hxx>
+
+#include <libxml/xmlwriter.h>
+
+using namespace ::com::sun::star;
+
+XOBitmap::XOBitmap( const BitmapEx& rBmp ) :
+ xGraphicObject (new GraphicObject(rBmp)),
+ bGraphicDirty ( false )
+{
+}
+
+XOBitmap::~XOBitmap()
+{
+}
+
+BitmapEx XOBitmap::GetBitmap() const
+{
+ return GetGraphicObject().GetGraphic().GetBitmapEx();
+}
+
+const GraphicObject& XOBitmap::GetGraphicObject() const
+{
+ if( bGraphicDirty )
+ const_cast<XOBitmap*>(this)->Array2Bitmap();
+
+ return *xGraphicObject;
+}
+
+void XOBitmap::Bitmap2Array()
+{
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ bool bPixelColor = false;
+ const BitmapEx aBitmap( GetBitmap() );
+ const sal_Int32 nLines = 8; // type dependent
+
+ if( !pPixelArray )
+ pPixelArray.reset( new sal_uInt16[ nLines * nLines ] );
+
+ pVDev->SetOutputSizePixel( aBitmap.GetSizePixel() );
+ pVDev->DrawBitmapEx( Point(), aBitmap );
+ aPixelColor = aBckgrColor = pVDev->GetPixel( Point() );
+
+ // create array and determine foreground and background color
+ for (sal_Int32 i = 0; i < nLines; ++i)
+ {
+ for (sal_Int32 j = 0; j < nLines; ++j)
+ {
+ if ( pVDev->GetPixel( Point( j, i ) ) == aBckgrColor )
+ pPixelArray[ j + i * nLines ] = 0;
+ else
+ {
+ pPixelArray[ j + i * nLines ] = 1;
+ if( !bPixelColor )
+ {
+ aPixelColor = pVDev->GetPixel( Point( j, i ) );
+ bPixelColor = true;
+ }
+ }
+ }
+ }
+}
+
+/// convert array, fore- and background color into a bitmap
+void XOBitmap::Array2Bitmap()
+{
+ if (!pPixelArray)
+ return;
+
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ const sal_Int32 nLines = 8; // type dependent
+
+ pVDev->SetOutputSizePixel( Size( nLines, nLines ) );
+
+ // create bitmap
+ for (sal_Int32 i = 0; i < nLines; ++i)
+ {
+ for (sal_Int32 j = 0; j < nLines; ++j)
+ {
+ if( pPixelArray[ j + i * nLines ] == 0 )
+ pVDev->DrawPixel( Point( j, i ), aBckgrColor );
+ else
+ pVDev->DrawPixel( Point( j, i ), aPixelColor );
+ }
+ }
+
+ xGraphicObject.reset(new GraphicObject(pVDev->GetBitmapEx(Point(), Size(nLines, nLines))));
+ bGraphicDirty = false;
+}
+
+
+SfxPoolItem* XFillBitmapItem::CreateDefault() { return new XFillBitmapItem; }
+
+XFillBitmapItem::XFillBitmapItem(const OUString& rName, const GraphicObject& rGraphicObject)
+: NameOrIndex(XATTR_FILLBITMAP, rName),
+ maGraphicObject(rGraphicObject)
+{
+}
+
+XFillBitmapItem::XFillBitmapItem(const XFillBitmapItem& rItem)
+: NameOrIndex(rItem),
+ maGraphicObject(rItem.maGraphicObject)
+{
+}
+
+XFillBitmapItem::XFillBitmapItem(const GraphicObject& rGraphicObject)
+ : NameOrIndex(XATTR_FILLBITMAP, -1)
+ , maGraphicObject(rGraphicObject)
+{
+}
+
+XFillBitmapItem* XFillBitmapItem::Clone(SfxItemPool* /*pPool*/) const
+{
+ return new XFillBitmapItem(*this);
+}
+
+bool XFillBitmapItem::operator==(const SfxPoolItem& rItem) const
+{
+ return (NameOrIndex::operator==(rItem)
+ && maGraphicObject == static_cast<const XFillBitmapItem&>(rItem).maGraphicObject);
+}
+
+
+bool XFillBitmapItem::isPattern() const
+{
+ Color aBack, aFront;
+ return vcl::bitmap::isHistorical8x8(GetGraphicObject().GetGraphic().GetBitmapEx(), aBack, aFront);
+}
+
+bool XFillBitmapItem::GetPresentation(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper&) const
+{
+ rText += GetName();
+ return true;
+}
+
+bool XFillBitmapItem::QueryValue(css::uno::Any& rVal, sal_uInt8 nMemberId) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ // needed for MID_NAME
+ OUString aApiName;
+ // needed for complete item (MID 0)
+ OUString aInternalName;
+
+ css::uno::Reference< css::awt::XBitmap > xBmp;
+
+ if( nMemberId == MID_NAME )
+ {
+ aApiName = SvxUnogetApiNameForItem(Which(), GetName());
+ }
+ else if( nMemberId == 0 )
+ {
+ aInternalName = GetName();
+ }
+
+ if (nMemberId == MID_BITMAP ||
+ nMemberId == 0)
+ {
+ xBmp.set(GetGraphicObject().GetGraphic().GetXGraphic(), uno::UNO_QUERY);
+ }
+
+ if( nMemberId == MID_NAME )
+ rVal <<= aApiName;
+ else if( nMemberId == MID_BITMAP )
+ rVal <<= xBmp;
+ else
+ {
+ // member-id 0 => complete item (e.g. for toolbars)
+ DBG_ASSERT( nMemberId == 0, "invalid member-id" );
+ uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
+
+ aPropSeq[0].Name = "Name";
+ aPropSeq[0].Value <<= aInternalName;
+ aPropSeq[1].Name = "Bitmap";
+ aPropSeq[1].Value <<= xBmp;
+
+ rVal <<= aPropSeq;
+ }
+
+ return true;
+}
+
+bool XFillBitmapItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+
+ OUString aName;
+ OUString aURL;
+ css::uno::Reference< css::awt::XBitmap > xBmp;
+ css::uno::Reference< css::graphic::XGraphic > xGraphic;
+
+ bool bSetURL = false;
+ bool bSetName = false;
+ bool bSetBitmap = false;
+
+ if( nMemberId == MID_NAME )
+ bSetName = (rVal >>= aName);
+ else if( nMemberId == MID_BITMAP )
+ {
+ if (rVal.has<OUString>())
+ {
+ bSetURL = true;
+ aURL = rVal.get<OUString>();
+ }
+ else if (rVal.has<uno::Reference<awt::XBitmap>>())
+ {
+ bSetBitmap = true;
+ xBmp = rVal.get<uno::Reference<awt::XBitmap>>();
+ }
+ else if (rVal.has<uno::Reference<graphic::XGraphic>>())
+ {
+ bSetBitmap = true;
+ xGraphic = rVal.get<uno::Reference<graphic::XGraphic>>();
+ }
+ }
+ else
+ {
+ DBG_ASSERT( nMemberId == 0, "invalid member-id" );
+ uno::Sequence< beans::PropertyValue > aPropSeq;
+ if( rVal >>= aPropSeq )
+ {
+ for ( const auto& rProp : std::as_const(aPropSeq) )
+ {
+ if ( rProp.Name == "Name" )
+ bSetName = (rProp.Value >>= aName);
+ else if ( rProp.Name == "Bitmap" )
+ bSetBitmap = (rProp.Value >>= xBmp);
+ else if ( rProp.Name == "FillBitmapURL" )
+ bSetURL = (rProp.Value >>= aURL);
+ }
+ }
+ }
+
+ if( bSetName )
+ {
+ SetName( aName );
+ }
+ if (bSetURL && !aURL.isEmpty())
+ {
+ Graphic aGraphic = vcl::graphic::loadFromURL(aURL);
+ if (!aGraphic.IsNone())
+ {
+ maGraphicObject.SetGraphic(aGraphic.GetXGraphic());
+ }
+ }
+ else if( bSetBitmap )
+ {
+ if (xBmp.is())
+ {
+ xGraphic.set(xBmp, uno::UNO_QUERY);
+ }
+ if (xGraphic.is())
+ {
+ maGraphicObject.SetGraphic(xGraphic);
+ }
+ }
+
+ return (bSetURL || bSetName || bSetBitmap);
+}
+
+bool XFillBitmapItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
+{
+ const GraphicObject& aGraphicObjectA(static_cast<const XFillBitmapItem*>(p1)->GetGraphicObject());
+ const GraphicObject& aGraphicObjectB(static_cast<const XFillBitmapItem*>(p2)->GetGraphicObject());
+
+ return aGraphicObjectA == aGraphicObjectB;
+}
+
+std::unique_ptr<XFillBitmapItem> XFillBitmapItem::checkForUniqueItem( SdrModel* pModel ) const
+{
+ if( pModel )
+ {
+ XPropertyListType aListType = XPropertyListType::Bitmap;
+ if(isPattern())
+ aListType = XPropertyListType::Pattern;
+ const OUString aUniqueName = NameOrIndex::CheckNamedItem(
+ this, XATTR_FILLBITMAP, &pModel->GetItemPool(),
+ XFillBitmapItem::CompareValueFunc, RID_SVXSTR_BMP21,
+ pModel->GetPropertyList( aListType ) );
+
+ // if the given name is not valid, replace it!
+ if( aUniqueName != GetName() )
+ {
+ return std::make_unique<XFillBitmapItem>(aUniqueName, maGraphicObject);
+ }
+ }
+
+ return nullptr;
+}
+
+void XFillBitmapItem::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ xmlTextWriterStartElement(pWriter, BAD_CAST("XFillBitmapItem"));
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+
+ NameOrIndex::dumpAsXml(pWriter);
+
+ xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xpool.cxx b/svx/source/xoutdev/xpool.cxx
new file mode 100644
index 000000000..997c6b576
--- /dev/null
+++ b/svx/source/xoutdev/xpool.cxx
@@ -0,0 +1,225 @@
+/* -*- 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 <svx/xflbckit.hxx>
+#include <xftshtit.hxx>
+#include <svx/xflboxy.hxx>
+#include <svx/xflbstit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/xsflclit.hxx>
+#include <svx/xlntrit.hxx>
+#include <svx/xfltrit.hxx>
+#include <svx/xgrscit.hxx>
+#include <svx/xflasit.hxx>
+#include <svx/xflbmtit.hxx>
+#include <svx/xflbmpit.hxx>
+#include <svx/xflbmsxy.hxx>
+#include <svx/xflbmsli.hxx>
+#include <svx/xflbtoxy.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/xlinjoit.hxx>
+#include <svx/xlncapit.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xtextit0.hxx>
+#include <svx/xlnasit.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xlnstwit.hxx>
+#include <svx/xlnedwit.hxx>
+#include <svx/xlnstcit.hxx>
+#include <svx/xlnedcit.hxx>
+#include <svx/xpool.hxx>
+#include <svx/svddef.hxx>
+#include <svx/svxids.hrc>
+#include <svl/itemset.hxx>
+#include <svx/xftadit.hxx>
+#include <svx/xftdiit.hxx>
+#include <svx/xftstit.hxx>
+#include <svx/xftmrit.hxx>
+#include <svx/xftouit.hxx>
+#include <svx/xftshit.hxx>
+#include <svx/xftshcit.hxx>
+#include <svx/xftshxy.hxx>
+
+XOutdevItemPool::XOutdevItemPool(SfxItemPool* _pMaster)
+ : SfxItemPool("XOutdevItemPool", SDRATTR_START, SDRATTR_END, nullptr, nullptr)
+ , mpLocalPoolDefaults(new std::vector<SfxPoolItem*>(SDRATTR_END - SDRATTR_START + 1))
+ , mpLocalItemInfos(new SfxItemInfo[SDRATTR_END - SDRATTR_START + 1])
+{
+ // prepare some defaults
+ const OUString aNullStr;
+ const Graphic aNullGraphic;
+ const basegfx::B2DPolyPolygon aNullPol;
+ const Color aNullLineCol(COL_DEFAULT_SHAPE_STROKE); // #i121448# Use defined default color
+ const Color aNullFillCol(COL_DEFAULT_SHAPE_FILLING); // #i121448# Use defined default color
+ const Color aNullShadowCol(COL_LIGHTGRAY);
+ const XDash aNullDash;
+ const XHatch aNullHatch(aNullLineCol);
+
+ // get master pointer, evtl. add myself to the end of the pools
+ if(!_pMaster)
+ {
+ _pMaster = this;
+ }
+ else
+ {
+ SfxItemPool* pParent = _pMaster;
+
+ while(pParent->GetSecondaryPool())
+ {
+ pParent = pParent->GetSecondaryPool();
+ }
+
+ pParent->SetSecondaryPool(this);
+ }
+
+ // prepare PoolDefaults
+ std::vector<SfxPoolItem*>& rPoolDefaults = *mpLocalPoolDefaults;
+ rPoolDefaults[XATTR_LINESTYLE -XATTR_START] = new XLineStyleItem;
+ rPoolDefaults[XATTR_LINEDASH -XATTR_START] = new XLineDashItem(aNullDash);
+ rPoolDefaults[XATTR_LINEWIDTH -XATTR_START] = new XLineWidthItem;
+ rPoolDefaults[XATTR_LINECOLOR -XATTR_START] = new XLineColorItem(aNullStr,aNullLineCol);
+ rPoolDefaults[XATTR_LINESTART -XATTR_START] = new XLineStartItem(aNullPol);
+ rPoolDefaults[XATTR_LINEEND -XATTR_START] = new XLineEndItem (aNullPol);
+ rPoolDefaults[XATTR_LINESTARTWIDTH -XATTR_START] = new XLineStartWidthItem;
+ rPoolDefaults[XATTR_LINEENDWIDTH -XATTR_START] = new XLineEndWidthItem;
+ rPoolDefaults[XATTR_LINESTARTCENTER -XATTR_START] = new XLineStartCenterItem;
+ rPoolDefaults[XATTR_LINEENDCENTER -XATTR_START] = new XLineEndCenterItem;
+ rPoolDefaults[XATTR_LINETRANSPARENCE -XATTR_START] = new XLineTransparenceItem;
+ rPoolDefaults[XATTR_LINEJOINT -XATTR_START] = new XLineJointItem;
+ rPoolDefaults[XATTR_LINECAP -XATTR_START] = new XLineCapItem;
+ rPoolDefaults[XATTR_FILLSTYLE -XATTR_START] = new XFillStyleItem;
+ rPoolDefaults[XATTR_FILLCOLOR -XATTR_START] = new XFillColorItem (aNullStr,aNullFillCol);
+ rPoolDefaults[XATTR_FILLGRADIENT -XATTR_START] = new XFillGradientItem(XGradient(COL_BLACK, COL_WHITE));
+ rPoolDefaults[XATTR_FILLHATCH -XATTR_START] = new XFillHatchItem (aNullHatch);
+ rPoolDefaults[XATTR_FILLBITMAP -XATTR_START] = new XFillBitmapItem (aNullGraphic);
+ rPoolDefaults[XATTR_FILLTRANSPARENCE -XATTR_START] = new XFillTransparenceItem;
+ rPoolDefaults[XATTR_GRADIENTSTEPCOUNT -XATTR_START] = new XGradientStepCountItem;
+ rPoolDefaults[XATTR_FILLBMP_TILE -XATTR_START] = new XFillBmpTileItem;
+ rPoolDefaults[XATTR_FILLBMP_POS -XATTR_START] = new XFillBmpPosItem;
+ rPoolDefaults[XATTR_FILLBMP_SIZEX -XATTR_START] = new XFillBmpSizeXItem;
+ rPoolDefaults[XATTR_FILLBMP_SIZEY -XATTR_START] = new XFillBmpSizeYItem;
+ rPoolDefaults[XATTR_FILLBMP_SIZELOG -XATTR_START] = new XFillBmpSizeLogItem;
+ rPoolDefaults[XATTR_FILLBMP_TILEOFFSETX -XATTR_START] = new XFillBmpTileOffsetXItem;
+ rPoolDefaults[XATTR_FILLBMP_TILEOFFSETY -XATTR_START] = new XFillBmpTileOffsetYItem;
+ rPoolDefaults[XATTR_FILLBMP_STRETCH -XATTR_START] = new XFillBmpStretchItem;
+ rPoolDefaults[XATTR_FILLBMP_POSOFFSETX -XATTR_START] = new XFillBmpPosOffsetXItem;
+ rPoolDefaults[XATTR_FILLBMP_POSOFFSETY -XATTR_START] = new XFillBmpPosOffsetYItem;
+ rPoolDefaults[XATTR_FILLFLOATTRANSPARENCE -XATTR_START] = new XFillFloatTransparenceItem( XGradient(COL_BLACK, COL_BLACK), false );
+ rPoolDefaults[XATTR_SECONDARYFILLCOLOR -XATTR_START] = new XSecondaryFillColorItem(aNullStr, aNullFillCol);
+ rPoolDefaults[XATTR_FILLBACKGROUND -XATTR_START] = new XFillBackgroundItem;
+ rPoolDefaults[XATTR_FORMTXTSTYLE -XATTR_START] = new XFormTextStyleItem;
+ rPoolDefaults[XATTR_FORMTXTADJUST -XATTR_START] = new XFormTextAdjustItem;
+ rPoolDefaults[XATTR_FORMTXTDISTANCE -XATTR_START] = new XFormTextDistanceItem;
+ rPoolDefaults[XATTR_FORMTXTSTART -XATTR_START] = new XFormTextStartItem;
+ rPoolDefaults[XATTR_FORMTXTMIRROR -XATTR_START] = new XFormTextMirrorItem;
+ rPoolDefaults[XATTR_FORMTXTOUTLINE -XATTR_START] = new XFormTextOutlineItem;
+ rPoolDefaults[XATTR_FORMTXTSHADOW -XATTR_START] = new XFormTextShadowItem;
+ rPoolDefaults[XATTR_FORMTXTSHDWCOLOR -XATTR_START] = new XFormTextShadowColorItem(aNullStr,aNullShadowCol);
+ rPoolDefaults[XATTR_FORMTXTSHDWXVAL -XATTR_START] = new XFormTextShadowXValItem;
+ rPoolDefaults[XATTR_FORMTXTSHDWYVAL -XATTR_START] = new XFormTextShadowYValItem;
+ rPoolDefaults[XATTR_FORMTXTHIDEFORM -XATTR_START] = new XFormTextHideFormItem;
+ rPoolDefaults[XATTR_FORMTXTSHDWTRANSP -XATTR_START] = new XFormTextShadowTranspItem;
+
+ // create SetItems
+ rPoolDefaults[XATTRSET_LINE - XATTR_START] = new XLineAttrSetItem(
+ std::make_unique<SfxItemSet>(
+ *_pMaster, svl::Items<XATTR_LINE_FIRST, XATTR_LINE_LAST>{}));
+ rPoolDefaults[XATTRSET_FILL - XATTR_START] = new XFillAttrSetItem(
+ std::make_unique<SfxItemSet>(
+ *_pMaster, svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{}));
+
+ // create ItemInfos
+ for(sal_uInt16 i(GetFirstWhich()); i <= GetLastWhich(); i++)
+ {
+ mpLocalItemInfos[i - XATTR_START]._nSID = 0;
+ mpLocalItemInfos[i - XATTR_START]._bPoolable = true;
+ }
+
+ mpLocalItemInfos[XATTR_LINESTYLE -XATTR_START]._nSID = SID_ATTR_LINE_STYLE;
+ mpLocalItemInfos[XATTR_LINEDASH -XATTR_START]._nSID = SID_ATTR_LINE_DASH;
+ mpLocalItemInfos[XATTR_LINEWIDTH -XATTR_START]._nSID = SID_ATTR_LINE_WIDTH;
+ mpLocalItemInfos[XATTR_LINECOLOR -XATTR_START]._nSID = SID_ATTR_LINE_COLOR;
+ mpLocalItemInfos[XATTR_LINESTART -XATTR_START]._nSID = SID_ATTR_LINE_START;
+ mpLocalItemInfos[XATTR_LINEEND -XATTR_START]._nSID = SID_ATTR_LINE_END;
+ mpLocalItemInfos[XATTR_LINESTARTWIDTH -XATTR_START]._nSID = SID_ATTR_LINE_STARTWIDTH;
+ mpLocalItemInfos[XATTR_LINEENDWIDTH -XATTR_START]._nSID = SID_ATTR_LINE_ENDWIDTH;
+ mpLocalItemInfos[XATTR_LINESTARTCENTER -XATTR_START]._nSID = SID_ATTR_LINE_STARTCENTER;
+ mpLocalItemInfos[XATTR_LINEENDCENTER -XATTR_START]._nSID = SID_ATTR_LINE_ENDCENTER;
+ mpLocalItemInfos[XATTR_FILLSTYLE -XATTR_START]._nSID = SID_ATTR_FILL_STYLE;
+ mpLocalItemInfos[XATTR_FILLCOLOR -XATTR_START]._nSID = SID_ATTR_FILL_COLOR;
+ mpLocalItemInfos[XATTR_FILLGRADIENT -XATTR_START]._nSID = SID_ATTR_FILL_GRADIENT;
+ mpLocalItemInfos[XATTR_FILLHATCH -XATTR_START]._nSID = SID_ATTR_FILL_HATCH;
+ mpLocalItemInfos[XATTR_FILLBITMAP -XATTR_START]._nSID = SID_ATTR_FILL_BITMAP;
+ mpLocalItemInfos[XATTR_FORMTXTSTYLE -XATTR_START]._nSID = SID_FORMTEXT_STYLE;
+ mpLocalItemInfos[XATTR_FORMTXTADJUST -XATTR_START]._nSID = SID_FORMTEXT_ADJUST;
+ mpLocalItemInfos[XATTR_FORMTXTDISTANCE -XATTR_START]._nSID = SID_FORMTEXT_DISTANCE;
+ mpLocalItemInfos[XATTR_FORMTXTSTART -XATTR_START]._nSID = SID_FORMTEXT_START;
+ mpLocalItemInfos[XATTR_FORMTXTMIRROR -XATTR_START]._nSID = SID_FORMTEXT_MIRROR;
+ mpLocalItemInfos[XATTR_FORMTXTOUTLINE -XATTR_START]._nSID = SID_FORMTEXT_OUTLINE;
+ mpLocalItemInfos[XATTR_FORMTXTSHADOW -XATTR_START]._nSID = SID_FORMTEXT_SHADOW;
+ mpLocalItemInfos[XATTR_FORMTXTSHDWCOLOR -XATTR_START]._nSID = SID_FORMTEXT_SHDWCOLOR;
+ mpLocalItemInfos[XATTR_FORMTXTSHDWXVAL -XATTR_START]._nSID = SID_FORMTEXT_SHDWXVAL;
+ mpLocalItemInfos[XATTR_FORMTXTSHDWYVAL -XATTR_START]._nSID = SID_FORMTEXT_SHDWYVAL;
+ mpLocalItemInfos[XATTR_FORMTXTHIDEFORM -XATTR_START]._nSID = SID_FORMTEXT_HIDEFORM;
+
+ // associate new slots for panels with known items
+ mpLocalItemInfos[XATTR_FILLTRANSPARENCE - XATTR_START]._nSID = SID_ATTR_FILL_TRANSPARENCE;
+ mpLocalItemInfos[XATTR_FILLFLOATTRANSPARENCE - XATTR_START]._nSID = SID_ATTR_FILL_FLOATTRANSPARENCE;
+ mpLocalItemInfos[XATTR_LINETRANSPARENCE - XATTR_START]._nSID = SID_ATTR_LINE_TRANSPARENCE;
+ mpLocalItemInfos[XATTR_LINEJOINT - XATTR_START]._nSID = SID_ATTR_LINE_JOINT;
+ mpLocalItemInfos[XATTR_LINECAP - XATTR_START]._nSID = SID_ATTR_LINE_CAP;
+
+ // if it's my own creation level, set Defaults and ItemInfos
+ if(XATTR_START == GetFirstWhich() && XATTR_END == GetLastWhich())
+ {
+ SetDefaults(mpLocalPoolDefaults);
+ SetItemInfos(mpLocalItemInfos.get());
+ }
+}
+
+// copy ctor, clones all static defaults
+XOutdevItemPool::XOutdevItemPool(const XOutdevItemPool& rPool)
+: SfxItemPool(rPool, true),
+ mpLocalPoolDefaults(nullptr)
+{
+}
+
+SfxItemPool* XOutdevItemPool::Clone() const
+{
+ return new XOutdevItemPool(*this);
+}
+
+XOutdevItemPool::~XOutdevItemPool()
+{
+ Delete();
+ // release and delete static pool default items
+ ReleaseDefaults(true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtabbtmp.cxx b/svx/source/xoutdev/xtabbtmp.cxx
new file mode 100644
index 000000000..ec12ab073
--- /dev/null
+++ b/svx/source/xoutdev/xtabbtmp.cxx
@@ -0,0 +1,115 @@
+/* -*- 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 <XPropertyTable.hxx>
+
+#include <osl/diagnose.h>
+#include <vcl/virdev.hxx>
+#include <svx/xtable.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace com::sun::star;
+
+XBitmapEntry* XBitmapList::GetBitmap(long nIndex) const
+{
+ return static_cast<XBitmapEntry*>( XPropertyList::Get(nIndex) );
+}
+
+uno::Reference< container::XNameContainer > XBitmapList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXBitmapTable_createInstance( this ), uno::UNO_QUERY );
+}
+
+bool XBitmapList::Create()
+{
+ return true;
+}
+
+BitmapEx XBitmapList::CreateBitmap( long nIndex, const Size& rSize ) const
+{
+ OSL_ENSURE( nIndex < Count(), "Access out of range" );
+
+ if(nIndex < Count())
+ {
+ BitmapEx rBitmapEx = GetBitmap( nIndex )->GetGraphicObject().GetGraphic().GetBitmapEx();
+ ScopedVclPtrInstance< VirtualDevice > pVirtualDevice;
+ pVirtualDevice->SetOutputSizePixel(rSize);
+
+ if(rBitmapEx.IsTransparent())
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+ if(rStyleSettings.GetPreviewUsesCheckeredBackground())
+ {
+ const Point aNull(0, 0);
+ static const sal_uInt32 nLen(8);
+ static const Color aW(COL_WHITE);
+ static const Color aG(0xef, 0xef, 0xef);
+
+ pVirtualDevice->DrawCheckered(aNull, rSize, nLen, aW, aG);
+ }
+ else
+ {
+ pVirtualDevice->SetBackground(rStyleSettings.GetFieldColor());
+ pVirtualDevice->Erase();
+ }
+ }
+
+ if(rBitmapEx.GetSizePixel().Width() >= rSize.Width() && rBitmapEx.GetSizePixel().Height() >= rSize.Height())
+ {
+ rBitmapEx.Scale(rSize);
+ pVirtualDevice->DrawBitmapEx(Point(0, 0), rBitmapEx);
+ }
+ else
+ {
+ const Size aBitmapSize(rBitmapEx.GetSizePixel());
+
+ for(long y(0); y < rSize.Height(); y += aBitmapSize.Height())
+ {
+ for(long x(0); x < rSize.Width(); x += aBitmapSize.Width())
+ {
+ pVirtualDevice->DrawBitmapEx(
+ Point(x, y),
+ rBitmapEx);
+ }
+ }
+ }
+ rBitmapEx = pVirtualDevice->GetBitmapEx(Point(0, 0), rSize);
+ return rBitmapEx;
+ }
+ else
+ return BitmapEx();
+}
+
+BitmapEx XBitmapList::CreateBitmapForUI( long nIndex )
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size& rSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
+ return CreateBitmap(nIndex, rSize);
+}
+
+BitmapEx XBitmapList::GetBitmapForPreview( long nIndex, const Size& rSize )
+{
+ return CreateBitmap(nIndex, rSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtabcolr.cxx b/svx/source/xoutdev/xtabcolr.cxx
new file mode 100644
index 000000000..4fbd331e4
--- /dev/null
+++ b/svx/source/xoutdev/xtabcolr.cxx
@@ -0,0 +1,174 @@
+/* -*- 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 <unotools/configmgr.hxx>
+#include <unotools/pathoptions.hxx>
+
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svx/xtable.hxx>
+
+using namespace com::sun::star;
+
+XColorListRef XColorList::CreateStdColorList()
+{
+ return XPropertyList::AsColorList(
+ XPropertyList::CreatePropertyList(
+ XPropertyListType::Color, !utl::ConfigManager::IsFuzzing() ?
+ SvtPathOptions().GetPalettePath() :
+ "", ""));
+}
+
+XColorListRef XColorList::GetStdColorList()
+{
+ XColorListRef aTable( CreateStdColorList() );
+ return aTable;
+}
+
+void XColorList::Replace(long nIndex, std::unique_ptr<XColorEntry> pEntry)
+{
+ XPropertyList::Replace(std::move(pEntry), nIndex);
+}
+XColorEntry* XColorList::GetColor(long nIndex) const
+{
+ return static_cast<XColorEntry*>( XPropertyList::Get(nIndex) );
+}
+
+uno::Reference< container::XNameContainer > XColorList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXColorTable_createInstance( this ),
+ uno::UNO_QUERY );
+}
+
+bool XColorList::Create()
+{
+ sal_uInt32 a(0);
+ sal_uInt32 b(0);
+
+ // <!-- Gray palette from white to black -->
+ const OUString aStrGrey( SvxResId( RID_SVXSTR_COLOR_GREY ) );
+
+ Insert( std::make_unique<XColorEntry>( Color( 0xff, 0xff, 0xff ), SvxResId( RID_SVXSTR_COLOR_WHITE ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xee, 0xee, 0xee ), aStrGrey + " 1" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xdd, 0xdd, 0xdd ), aStrGrey + " 2" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xcc, 0xcc, 0xcc ), aStrGrey + " 3" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xb2, 0xb2, 0xb2 ), aStrGrey + " 4" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x99, 0x99, 0x99 ), aStrGrey + " 5" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x80, 0x80, 0x80 ), aStrGrey + " 6" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x66, 0x66, 0x66 ), aStrGrey + " 7" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x33, 0x33, 0x33 ), aStrGrey + " 8" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x1c, 0x1c, 0x1c ), aStrGrey + " 9" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x11, 0x11, 0x11 ), aStrGrey + " 10") );
+ Insert( std::make_unique<XColorEntry>( Color( 0x00, 0x00, 0x00 ), SvxResId( RID_SVXSTR_COLOR_BLACK ) ) );
+
+ // <!-- Base colors step 0 to 10 -->
+ const sal_uInt32 nNumColorsInGroup(12);
+ const sal_uInt32 nNumGroups(11);
+ const OUString aStrCol[nNumColorsInGroup] = {
+ SvxResId(RID_SVXSTR_COLOR_YELLOW),
+ SvxResId(RID_SVXSTR_COLOR_ORANGE),
+ SvxResId(RID_SVXSTR_COLOR_RED),
+ SvxResId(RID_SVXSTR_COLOR_PINK),
+ SvxResId(RID_SVXSTR_COLOR_MAGENTA),
+ SvxResId(RID_SVXSTR_COLOR_PURPLE),
+ SvxResId(RID_SVXSTR_COLOR_BLUE),
+ SvxResId(RID_SVXSTR_COLOR_SKYBLUE),
+ SvxResId(RID_SVXSTR_COLOR_CYAN),
+ SvxResId(RID_SVXSTR_COLOR_TURQUOISE),
+ SvxResId(RID_SVXSTR_COLOR_GREEN),
+ SvxResId(RID_SVXSTR_COLOR_YELLOWGREEN) };
+ static const sal_uInt32 aStdCol[nNumColorsInGroup * nNumGroups] = {
+ 0xffff99, 0xff6600, 0xff3333, 0xff00cc, 0xff33ff, 0x9900ff, 0x6666ff, 0x00ccff, 0x66ffff, 0x33ff99, 0x99ff66, 0xccff00,
+ 0xffff66, 0xffcc00, 0xff9999, 0xff66cc, 0xff99ff, 0xcc66ff, 0x9999ff, 0x9999ff, 0x99ffff, 0x66ff99, 0x99ff99, 0xccff66,
+ 0xffff00, 0xff9900, 0xff6666, 0xff3399, 0xff66ff, 0x9933ff, 0x3333ff, 0x3399ff, 0x00ffff, 0x00ff66, 0x66ff66, 0x99ff33,
+ 0xcc9900, 0xff3300, 0xff0000, 0xff0066, 0xff00ff, 0x6600ff, 0x0000ff, 0x0066ff, 0x00cccc, 0x00cc33, 0x00cc00, 0x66ff00,
+ 0x996600, 0xcc3300, 0xcc0000, 0xcc0066, 0xcc00cc, 0x6600cc, 0x0000cc, 0x0066cc, 0x009999, 0x009933, 0x009900, 0x66cc00,
+ 0x663300, 0x801900, 0x990000, 0x990066, 0x990099, 0x330099, 0x000099, 0x006699, 0x006666, 0x007826, 0x006600, 0x669900,
+ 0x333300, 0x461900, 0x330000, 0x330033, 0x660066, 0x000033, 0x000066, 0x000080, 0x003333, 0x00331a, 0x003300, 0x193300,
+ 0x666633, 0x661900, 0x663333, 0x660033, 0x663366, 0x330066, 0x333366, 0x003366, 0x336666, 0x006633, 0x336633, 0x336600,
+ 0x999966, 0x996633, 0x996666, 0x993366, 0x996699, 0x663399, 0x666699, 0x336699, 0x669999, 0x339966, 0x669966, 0x669933,
+ 0xcccc99, 0xcc9966, 0xcc9999, 0xcc6699, 0xcc99cc, 0x9966cc, 0x9999cc, 0x6699cc, 0x99cccc, 0x66cc99, 0x99cc99, 0x99cc66,
+ 0xffffcc, 0xffcc99, 0xffcccc, 0xff99cc, 0xffccff, 0xcc99ff, 0xccccff, 0x99ccff, 0xccffff, 0x99ffcc, 0xccffcc, 0xccff99 };
+
+ for(a = 0; a < nNumGroups; a++)
+ {
+ OUString aSuffix;
+ if (a > 0) aSuffix = OUString::number(a);
+
+ const sal_uInt32 nOffset(a * nNumColorsInGroup);
+
+ for(b = 0; b < nNumColorsInGroup; b++)
+ {
+ Insert( std::make_unique<XColorEntry>( Color(aStdCol[nOffset + b]), aStrCol[b] + aSuffix ) );
+ }
+ }
+
+ // <!-- use some 'nice' colors from original palette -->
+ Insert( std::make_unique<XColorEntry>( Color( 0xe6, 0xe6, 0xff ), SvxResId( RID_SVXSTR_COLOR_BLUEGREY) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xCF, 0xE7, 0xF5 ), SvxResId( RID_SVXSTR_COLOR_BLUE_CLASSIC ) ) );
+
+ // <!-- add 'pale' colors from original palette -->
+ Insert( std::make_unique<XColorEntry>( Color( 0x99, 0x99, 0xff ), SvxResId( RID_SVXSTR_COLOR_VIOLET ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x99, 0x33, 0x66 ), SvxResId( RID_SVXSTR_COLOR_BORDEAUX ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xff, 0xff, 0xcc ), SvxResId( RID_SVXSTR_COLOR_PALE_YELLOW ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xcc, 0xff, 0xff ), SvxResId( RID_SVXSTR_COLOR_PALE_GREEN ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x66, 0x00, 0x66 ), SvxResId( RID_SVXSTR_COLOR_DARKVIOLET ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xff, 0x80, 0x80 ), SvxResId( RID_SVXSTR_COLOR_SALMON ) ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x00, 0x66, 0xcc ), SvxResId( RID_SVXSTR_COLOR_SEABLUE ) ) );
+
+ // <!-- add Chart colors from original palette (also 12, coincidence?) -->
+ const OUString aStrChart( SvxResId( RID_SVXSTR_COLOR_CHART ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x00, 0x45, 0x86 ), aStrChart + " 1" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xff, 0x42, 0x0e ), aStrChart + " 2" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xff, 0xd3, 0x20 ), aStrChart + " 3" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x57, 0x9d, 0x1c ), aStrChart + " 4" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x7e, 0x00, 0x21 ), aStrChart + " 5" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x83, 0xca, 0xff ), aStrChart + " 6" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x31, 0x40, 0x04 ), aStrChart + " 7" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xae, 0xcf, 0x00 ), aStrChart + " 8" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x4b, 0x1f, 0x6f ), aStrChart + " 9" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xff, 0x95, 0x0e ), aStrChart + " 10" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0xc5, 0x00, 0x0b ), aStrChart + " 11" ) );
+ Insert( std::make_unique<XColorEntry>( Color( 0x00, 0x84, 0xd1 ), aStrChart + " 12" ) );
+
+ return(165 == Count());
+}
+
+BitmapEx XColorList::CreateBitmapForUI( long /*nIndex*/ )
+{
+ return BitmapEx();
+}
+
+long XColorList::GetIndexOfColor( const Color& rColor ) const
+{
+ for( long i = 0, n = maList.size(); i < n; ++i )
+ {
+ const Color aColor = static_cast<XColorEntry*>( maList[i].get() )->GetColor();
+
+ if (aColor == rColor )
+ return i;
+ }
+
+ return -1;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtabdash.cxx b/svx/source/xoutdev/xtabdash.cxx
new file mode 100644
index 000000000..896b3cbb4
--- /dev/null
+++ b/svx/source/xoutdev/xtabdash.cxx
@@ -0,0 +1,223 @@
+/* -*- 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 <XPropertyTable.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <vcl/virdev.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svx/xtable.hxx>
+
+#include <comphelper/lok.hxx>
+
+#include <drawinglayer/attribute/lineattribute.hxx>
+#include <drawinglayer/attribute/strokeattribute.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <memory>
+
+using namespace com::sun::star;
+
+XDashList::XDashList(const OUString& rPath, const OUString& rReferer)
+ : XPropertyList(XPropertyListType::Dash, rPath, rReferer)
+ , maBitmapSolidLine()
+ , maStringSolidLine()
+ , maStringNoLine()
+{
+}
+
+XDashList::~XDashList()
+{
+}
+
+void XDashList::Replace(std::unique_ptr<XDashEntry> pEntry, long nIndex)
+{
+ XPropertyList::Replace(std::move(pEntry), nIndex);
+}
+
+XDashEntry* XDashList::GetDash(long nIndex) const
+{
+ return static_cast<XDashEntry*>( XPropertyList::Get(nIndex) );
+}
+
+uno::Reference< container::XNameContainer > XDashList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXDashTable_createInstance( this ), uno::UNO_QUERY );
+}
+
+bool XDashList::Create()
+{
+ const OUString aStr(SvxResId(RID_SVXSTR_LINESTYLE));
+
+ Insert(std::make_unique<XDashEntry>(XDash(css::drawing::DashStyle_RECT,1, 50,1, 50, 50),aStr + " 1"));
+ Insert(std::make_unique<XDashEntry>(XDash(css::drawing::DashStyle_RECT,1,500,1,500,500),aStr + " 2"));
+ Insert(std::make_unique<XDashEntry>(XDash(css::drawing::DashStyle_RECT,2, 50,3,250,120),aStr + " 3"));
+
+ return true;
+}
+
+BitmapEx XDashList::ImpCreateBitmapForXDash(const XDash* pDash)
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size& rSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
+ const sal_uInt32 nFactor(2);
+ const Size aSize((rSize.Width() * 5 * 2) / 2, rSize.Height() * nFactor);
+
+ // prepare polygon geometry for line
+ basegfx::B2DPolygon aLine;
+
+ aLine.append(basegfx::B2DPoint(0.0, aSize.Height() / 2.0));
+ aLine.append(basegfx::B2DPoint(aSize.Width(), aSize.Height() / 2.0));
+
+ // prepare LineAttribute
+ const basegfx::BColor aLineColor(rStyleSettings.GetFieldTextColor().getBColor());
+ const double fLineWidth(StyleSettings::GetListBoxPreviewDefaultLineWidth() * (nFactor * 1.1));
+ const drawinglayer::attribute::LineAttribute aLineAttribute(
+ aLineColor,
+ fLineWidth);
+
+ // prepare StrokeAttribute
+ ::std::vector< double > aDotDashArray;
+ double fFullDotDashLen(0.0);
+
+ if(pDash && (pDash->GetDots() || pDash->GetDashes()))
+ {
+ const basegfx::B2DHomMatrix aScaleMatrix(OutputDevice::LogicToLogic(MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapPixel)));
+ const basegfx::B2DVector aScaleVector(aScaleMatrix * basegfx::B2DVector(1.0, 0.0));
+ const double fScaleValue(aScaleVector.getLength() * (nFactor * (1.4 / 2.0)));
+ const double fLineWidthInUnits(fLineWidth / fScaleValue);
+
+ fFullDotDashLen = pDash->CreateDotDashArray(aDotDashArray, fLineWidthInUnits);
+
+ if(!aDotDashArray.empty())
+ {
+ for(double & a : aDotDashArray)
+ {
+ a *= fScaleValue;
+ }
+
+ fFullDotDashLen *= fScaleValue;
+ }
+ }
+
+ const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
+ aDotDashArray,
+ fFullDotDashLen);
+
+ // create LinePrimitive
+ const drawinglayer::primitive2d::Primitive2DReference aLinePrimitive(
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ aLine,
+ aLineAttribute,
+ aStrokeAttribute));
+
+ // prepare VirtualDevice
+ ScopedVclPtrInstance< VirtualDevice > pVirtualDevice;
+ const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
+
+ pVirtualDevice->SetOutputSizePixel(aSize);
+ pVirtualDevice->SetDrawMode(rStyleSettings.GetHighContrastMode()
+ ? DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient
+ : DrawModeFlags::Default);
+
+ if(rStyleSettings.GetPreviewUsesCheckeredBackground())
+ {
+ const Point aNull(0, 0);
+ static const sal_uInt32 nLen(8 * nFactor);
+ static const Color aW(COL_WHITE);
+ static const Color aG(0xef, 0xef, 0xef);
+
+ pVirtualDevice->DrawCheckered(aNull, aSize, nLen, aW, aG);
+ }
+ else
+ {
+ pVirtualDevice->SetBackground(rStyleSettings.GetFieldColor());
+ pVirtualDevice->Erase();
+ }
+
+ // create processor and draw primitives
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
+ *pVirtualDevice,
+ aNewViewInformation2D));
+
+ if(pProcessor2D)
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer aSequence { aLinePrimitive };
+
+ pProcessor2D->process(aSequence);
+ pProcessor2D.reset();
+ }
+
+ // get result bitmap and scale
+ BitmapEx aRetval(pVirtualDevice->GetBitmapEx(Point(0, 0), pVirtualDevice->GetOutputSizePixel()));
+
+ if(1 != nFactor)
+ {
+ aRetval.Scale(Size((rSize.Width() * 5) / 2, rSize.Height()));
+ }
+
+ return aRetval;
+}
+
+BitmapEx XDashList::CreateBitmapForUI( long nIndex )
+{
+ const XDash& rDash = GetDash(nIndex)->GetDash();
+
+ return ImpCreateBitmapForXDash(&rDash);
+}
+
+BitmapEx const & XDashList::GetBitmapForUISolidLine() const
+{
+ if(maBitmapSolidLine.IsEmpty())
+ {
+ const_cast< XDashList* >(this)->maBitmapSolidLine = XDashList::ImpCreateBitmapForXDash(nullptr);
+ }
+
+ return maBitmapSolidLine;
+}
+
+OUString const & XDashList::GetStringForUiSolidLine() const
+{
+ if(maStringSolidLine.isEmpty())
+ {
+ const_cast< XDashList* >(this)->maStringSolidLine = SvxResId(RID_SVXSTR_SOLID);
+ }
+
+ return maStringSolidLine;
+}
+
+OUString const & XDashList::GetStringForUiNoLine() const
+{
+ if(maStringNoLine.isEmpty())
+ {
+ // formerly was RID_SVXSTR_INVISIBLE, but to make equal
+ // everywhere, use RID_SVXSTR_NONE
+ const_cast< XDashList* >(this)->maStringNoLine = comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) :
+ SvxResId(RID_SVXSTR_NONE);
+ }
+
+ return maStringNoLine;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtabgrdt.cxx b/svx/source/xoutdev/xtabgrdt.cxx
new file mode 100644
index 000000000..1a29fbcac
--- /dev/null
+++ b/svx/source/xoutdev/xtabgrdt.cxx
@@ -0,0 +1,222 @@
+/* -*- 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 <XPropertyTable.hxx>
+
+#include <vcl/virdev.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svx/xtable.hxx>
+
+#include <rtl/ustrbuf.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <drawinglayer/attribute/fillgradientattribute.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <memory>
+
+using namespace com::sun::star;
+
+XGradientList::XGradientList( const OUString& rPath, const OUString& rReferer )
+: XPropertyList( XPropertyListType::Gradient, rPath, rReferer )
+{
+}
+
+XGradientList::~XGradientList()
+{
+}
+
+void XGradientList::Replace(std::unique_ptr<XGradientEntry> pEntry, long nIndex)
+{
+ XPropertyList::Replace(std::move(pEntry), nIndex);
+}
+
+XGradientEntry* XGradientList::GetGradient(long nIndex) const
+{
+ return static_cast<XGradientEntry*>( XPropertyList::Get( nIndex ) );
+}
+
+uno::Reference< container::XNameContainer > XGradientList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXGradientTable_createInstance( this ),
+ uno::UNO_QUERY );
+}
+
+bool XGradientList::Create()
+{
+ OUStringBuffer aStr(SvxResId(RID_SVXSTR_GRADIENT));
+ aStr.append(" 1");
+ sal_Int32 nLen = aStr.getLength() - 1;
+ Insert(std::make_unique<XGradientEntry>(XGradient(COL_BLACK, COL_WHITE, css::awt::GradientStyle_LINEAR , 0,10,10, 0,100,100),aStr.toString()));
+ aStr[nLen] = '2';
+ Insert(std::make_unique<XGradientEntry>(XGradient(COL_BLUE, COL_RED, css::awt::GradientStyle_AXIAL , 300,20,20,10,100,100),aStr.toString()));
+ aStr[nLen] = '3';
+ Insert(std::make_unique<XGradientEntry>(XGradient(COL_RED, COL_YELLOW,css::awt::GradientStyle_RADIAL , 600,30,30,20,100,100),aStr.toString()));
+ aStr[nLen] = '4';
+ Insert(std::make_unique<XGradientEntry>(XGradient(COL_YELLOW , COL_GREEN, css::awt::GradientStyle_ELLIPTICAL, 900,40,40,30,100,100),aStr.toString()));
+ aStr[nLen] = '5';
+ Insert(std::make_unique<XGradientEntry>(XGradient(COL_GREEN , COL_MAGENTA,css::awt::GradientStyle_SQUARE , 1200,50,50,40,100,100),aStr.toString()));
+ aStr[nLen] = '6';
+ Insert(std::make_unique<XGradientEntry>(XGradient(COL_MAGENTA, COL_YELLOW ,css::awt::GradientStyle_RECT , 1900,60,60,50,100,100),aStr.toString()));
+
+ return true;
+}
+
+BitmapEx XGradientList::CreateBitmap( long nIndex, const Size& rSize ) const
+{
+ BitmapEx aRetval;
+
+ OSL_ENSURE(nIndex < Count(), "OOps, access out of range (!)");
+
+ if(nIndex < Count())
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ // prepare polygon geometry for rectangle
+ const basegfx::B2DPolygon aRectangle(
+ basegfx::utils::createPolygonFromRect(
+ basegfx::B2DRange(0.0, 0.0, rSize.Width(), rSize.Height())));
+
+ const XGradient& rGradient = GetGradient(nIndex)->GetGradient();
+ const sal_uInt16 nStartIntens(rGradient.GetStartIntens());
+ basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
+
+ if(nStartIntens != 100)
+ {
+ const basegfx::BColor aBlack;
+ aStart = interpolate(aBlack, aStart, static_cast<double>(nStartIntens) * 0.01);
+ }
+
+ const sal_uInt16 nEndIntens(rGradient.GetEndIntens());
+ basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
+
+ if(nEndIntens != 100)
+ {
+ const basegfx::BColor aBlack;
+ aEnd = interpolate(aBlack, aEnd, static_cast<double>(nEndIntens) * 0.01);
+ }
+
+ drawinglayer::attribute::GradientStyle aGradientStyle(drawinglayer::attribute::GradientStyle::Rect);
+
+ switch(rGradient.GetGradientStyle())
+ {
+ case css::awt::GradientStyle_LINEAR :
+ {
+ aGradientStyle = drawinglayer::attribute::GradientStyle::Linear;
+ break;
+ }
+ case css::awt::GradientStyle_AXIAL :
+ {
+ aGradientStyle = drawinglayer::attribute::GradientStyle::Axial;
+ break;
+ }
+ case css::awt::GradientStyle_RADIAL :
+ {
+ aGradientStyle = drawinglayer::attribute::GradientStyle::Radial;
+ break;
+ }
+ case css::awt::GradientStyle_ELLIPTICAL :
+ {
+ aGradientStyle = drawinglayer::attribute::GradientStyle::Elliptical;
+ break;
+ }
+ case css::awt::GradientStyle_SQUARE :
+ {
+ aGradientStyle = drawinglayer::attribute::GradientStyle::Square;
+ break;
+ }
+ default :
+ {
+ aGradientStyle = drawinglayer::attribute::GradientStyle::Rect; // css::awt::GradientStyle_RECT
+ break;
+ }
+ }
+
+ const sal_uInt16 nSteps((rSize.Width() + rSize.Height()) / 3);
+ const drawinglayer::attribute::FillGradientAttribute aFillGradient(
+ aGradientStyle,
+ static_cast<double>(rGradient.GetBorder()) * 0.01,
+ static_cast<double>(rGradient.GetXOffset()) * 0.01,
+ static_cast<double>(rGradient.GetYOffset()) * 0.01,
+ static_cast<double>(rGradient.GetAngle()) * F_PI1800,
+ aStart,
+ aEnd,
+ nSteps);
+
+ const drawinglayer::primitive2d::Primitive2DReference aGradientPrimitive(
+ new drawinglayer::primitive2d::PolyPolygonGradientPrimitive2D(
+ basegfx::B2DPolyPolygon(aRectangle),
+ aFillGradient));
+
+ const basegfx::BColor aBlack(0.0, 0.0, 0.0);
+ const drawinglayer::primitive2d::Primitive2DReference aBlackRectanglePrimitive(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ aRectangle,
+ aBlack));
+
+ // prepare VirtualDevice
+ ScopedVclPtrInstance< VirtualDevice > pVirtualDevice;
+ const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
+
+ pVirtualDevice->SetOutputSizePixel(rSize);
+ pVirtualDevice->SetDrawMode(rStyleSettings.GetHighContrastMode()
+ ? DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient
+ : DrawModeFlags::Default);
+
+ // create processor and draw primitives
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
+ *pVirtualDevice,
+ aNewViewInformation2D));
+
+ if(pProcessor2D)
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aSequence(2);
+
+ aSequence[0] = aGradientPrimitive;
+ aSequence[1] = aBlackRectanglePrimitive;
+
+ pProcessor2D->process(aSequence);
+ pProcessor2D.reset();
+ }
+
+ // get result bitmap and scale
+ aRetval = pVirtualDevice->GetBitmapEx(Point(0, 0), pVirtualDevice->GetOutputSizePixel());
+ }
+
+ return aRetval;
+}
+
+BitmapEx XGradientList::CreateBitmapForUI(long nIndex)
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size& rSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
+ return CreateBitmap(nIndex, rSize);
+}
+
+BitmapEx XGradientList::GetBitmapForPreview(long nIndex, const Size& rSize)
+{
+ return CreateBitmap(nIndex, rSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtabhtch.cxx b/svx/source/xoutdev/xtabhtch.cxx
new file mode 100644
index 000000000..3b84601fa
--- /dev/null
+++ b/svx/source/xoutdev/xtabhtch.cxx
@@ -0,0 +1,197 @@
+/* -*- 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 <XPropertyTable.hxx>
+#include <vcl/svapp.hxx>
+
+#include <vcl/virdev.hxx>
+#include <vcl/settings.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+
+#include <drawinglayer/attribute/fillhatchattribute.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <memory>
+
+using namespace ::com::sun::star;
+
+XHatchList::XHatchList(const OUString& rPath, const OUString& rReferer)
+ : XPropertyList( XPropertyListType::Hatch, rPath, rReferer )
+{
+}
+
+XHatchList::~XHatchList()
+{
+}
+
+void XHatchList::Replace(std::unique_ptr<XHatchEntry> pEntry, long nIndex)
+{
+ XPropertyList::Replace(std::move(pEntry), nIndex);
+}
+
+XHatchEntry* XHatchList::GetHatch(long nIndex) const
+{
+ return static_cast<XHatchEntry*>( XPropertyList::Get(nIndex) );
+}
+
+uno::Reference< container::XNameContainer > XHatchList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXHatchTable_createInstance( this ), uno::UNO_QUERY );
+}
+
+bool XHatchList::Create()
+{
+ OUStringBuffer aStr(SvxResId(RID_SVXSTR_HATCH));
+ aStr.append(" 1");
+
+ sal_Int32 nLen = aStr.getLength() - 1;
+ Insert(std::make_unique<XHatchEntry>(XHatch(COL_BLACK,css::drawing::HatchStyle_SINGLE,100, 0),aStr.toString()));
+ aStr[nLen] = '2';
+ Insert(std::make_unique<XHatchEntry>(XHatch(COL_RED ,css::drawing::HatchStyle_DOUBLE, 80,450),aStr.toString()));
+ aStr[nLen] = '3';
+ Insert(std::make_unique<XHatchEntry>(XHatch(COL_BLUE ,css::drawing::HatchStyle_TRIPLE,120, 0),aStr.toString()));
+
+ return true;
+}
+
+BitmapEx XHatchList::CreateBitmap( long nIndex, const Size& rSize) const
+{
+ BitmapEx aRetval;
+ OSL_ENSURE(nIndex < Count(), "OOps, access out of range (!)");
+
+ if(nIndex < Count())
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+ // prepare polygon geometry for rectangle
+ const basegfx::B2DPolygon aRectangle(
+ basegfx::utils::createPolygonFromRect(
+ basegfx::B2DRange(0.0, 0.0, rSize.Width(), rSize.Height())));
+
+ const XHatch& rHatch = GetHatch(nIndex)->GetHatch();
+ drawinglayer::attribute::HatchStyle aHatchStyle(drawinglayer::attribute::HatchStyle::Triple);
+
+ switch(rHatch.GetHatchStyle())
+ {
+ case css::drawing::HatchStyle_SINGLE :
+ {
+ aHatchStyle = drawinglayer::attribute::HatchStyle::Single;
+ break;
+ }
+ case css::drawing::HatchStyle_DOUBLE :
+ {
+ aHatchStyle = drawinglayer::attribute::HatchStyle::Double;
+ break;
+ }
+ default :
+ {
+ aHatchStyle = drawinglayer::attribute::HatchStyle::Triple; // css::drawing::HatchStyle_TRIPLE
+ break;
+ }
+ }
+
+ const basegfx::B2DHomMatrix aScaleMatrix(OutputDevice::LogicToLogic(MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapPixel)));
+ const basegfx::B2DVector aScaleVector(aScaleMatrix * basegfx::B2DVector(1.0, 0.0));
+ const double fScaleValue(aScaleVector.getLength());
+
+ const drawinglayer::attribute::FillHatchAttribute aFillHatch(
+ aHatchStyle,
+ static_cast<double>(rHatch.GetDistance()) * fScaleValue,
+ static_cast<double>(rHatch.GetAngle()) * F_PI1800,
+ rHatch.GetColor().getBColor(),
+ 3, // same default as VCL, a minimum of three discrete units (pixels) offset
+ false);
+
+ const basegfx::BColor aBlack(0.0, 0.0, 0.0);
+ const drawinglayer::primitive2d::Primitive2DReference aHatchPrimitive(
+ new drawinglayer::primitive2d::PolyPolygonHatchPrimitive2D(
+ basegfx::B2DPolyPolygon(aRectangle),
+ aBlack,
+ aFillHatch));
+
+ const drawinglayer::primitive2d::Primitive2DReference aBlackRectanglePrimitive(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ aRectangle,
+ aBlack));
+
+ // prepare VirtualDevice
+ ScopedVclPtrInstance< VirtualDevice > pVirtualDevice;
+ const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
+
+ pVirtualDevice->SetOutputSizePixel(rSize);
+ pVirtualDevice->SetDrawMode(rStyleSettings.GetHighContrastMode()
+ ? DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient
+ : DrawModeFlags::Default);
+
+ if(rStyleSettings.GetPreviewUsesCheckeredBackground())
+ {
+ const Point aNull(0, 0);
+ static const sal_uInt32 nLen(8);
+ static const Color aW(COL_WHITE);
+ static const Color aG(0xef, 0xef, 0xef);
+ pVirtualDevice->DrawCheckered(aNull, rSize, nLen, aW, aG);
+ }
+ else
+ {
+ pVirtualDevice->SetBackground(rStyleSettings.GetFieldColor());
+ pVirtualDevice->Erase();
+ }
+
+ // create processor and draw primitives
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
+ *pVirtualDevice,
+ aNewViewInformation2D));
+
+ if(pProcessor2D)
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aSequence(2);
+
+ aSequence[0] = aHatchPrimitive;
+ aSequence[1] = aBlackRectanglePrimitive;
+ pProcessor2D->process(aSequence);
+ pProcessor2D.reset();
+ }
+
+ // get result bitmap and scale
+ aRetval = pVirtualDevice->GetBitmapEx(Point(0, 0), pVirtualDevice->GetOutputSizePixel());
+ }
+
+ return aRetval;
+}
+
+BitmapEx XHatchList::CreateBitmapForUI(long nIndex)
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size& rSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
+ BitmapEx aRetVal = CreateBitmap(nIndex, rSize);
+ return aRetVal;
+}
+
+BitmapEx XHatchList::GetBitmapForPreview(long nIndex, const Size& rSize)
+{
+ return CreateBitmap(nIndex, rSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtable.cxx b/svx/source/xoutdev/xtable.cxx
new file mode 100644
index 000000000..7ca5e98bc
--- /dev/null
+++ b/svx/source/xoutdev/xtable.cxx
@@ -0,0 +1,392 @@
+/* -*- 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 <xmlxtexp.hxx>
+#include <xmlxtimp.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <tools/urlobj.hxx>
+#include <svx/xtable.hxx>
+#include <tools/debug.hxx>
+#include <stack>
+
+using namespace com::sun::star;
+
+XColorEntry::XColorEntry(const Color& rColor, const OUString& rName)
+: XPropertyEntry(rName),
+ aColor(rColor)
+{
+}
+
+XLineEndEntry::XLineEndEntry(const basegfx::B2DPolyPolygon& rB2DPolyPolygon, const OUString& rName)
+: XPropertyEntry(rName),
+ aB2DPolyPolygon(rB2DPolyPolygon)
+{
+}
+
+XLineEndEntry::XLineEndEntry(const XLineEndEntry& rOther)
+: XPropertyEntry(rOther),
+ aB2DPolyPolygon(rOther.aB2DPolyPolygon)
+{
+}
+
+XDashEntry::XDashEntry(const XDash& rDash, const OUString& rName)
+: XPropertyEntry(rName),
+ aDash(rDash)
+{
+}
+
+XDashEntry::XDashEntry(const XDashEntry& rOther)
+: XPropertyEntry(rOther),
+aDash(rOther.aDash)
+{
+}
+
+XHatchEntry::XHatchEntry(const XHatch& rHatch, const OUString& rName)
+: XPropertyEntry(rName),
+ aHatch(rHatch)
+{
+}
+
+XHatchEntry::XHatchEntry(const XHatchEntry& rOther)
+: XPropertyEntry(rOther),
+ aHatch(rOther.aHatch)
+{
+}
+
+XGradientEntry::XGradientEntry(const XGradient& rGradient, const OUString& rName)
+: XPropertyEntry(rName),
+ aGradient(rGradient)
+{
+}
+
+XGradientEntry::XGradientEntry(const XGradientEntry& rOther)
+: XPropertyEntry(rOther),
+ aGradient(rOther.aGradient)
+{
+}
+
+XBitmapEntry::XBitmapEntry(const GraphicObject& rGraphicObject, const OUString& rName)
+: XPropertyEntry(rName),
+ maGraphicObject(rGraphicObject)
+{
+}
+
+XBitmapEntry::XBitmapEntry(const XBitmapEntry& rOther)
+: XPropertyEntry(rOther),
+ maGraphicObject(rOther.maGraphicObject)
+{
+}
+
+XPropertyList::XPropertyList(
+ XPropertyListType type,
+ const OUString& rPath, const OUString& rReferer
+) : meType ( type ),
+ maName ( "standard" ),
+ maPath ( rPath ),
+ maReferer ( rReferer ),
+ mbListDirty ( true ),
+ mbEmbedInDocument( false )
+{
+// fprintf (stderr, "Create type %d count %d\n", (int)meType, count++);
+}
+
+bool XPropertyList::isValidIdx(long nIndex) const
+{
+ return (nIndex >= 0 && o3tl::make_unsigned(nIndex) < maList.size());
+}
+
+
+XPropertyList::~XPropertyList()
+{
+}
+
+long XPropertyList::Count() const
+{
+ if( mbListDirty )
+ {
+ if( !const_cast<XPropertyList*>(this)->Load() )
+ const_cast<XPropertyList*>(this)->Create();
+ }
+ return maList.size();
+}
+
+XPropertyEntry* XPropertyList::Get( long nIndex ) const
+{
+ if( mbListDirty )
+ {
+ if( !const_cast<XPropertyList*>(this)->Load() )
+ const_cast<XPropertyList*>(this)->Create();
+ }
+ if (!isValidIdx(nIndex))
+ return nullptr;
+
+ return maList[nIndex].get();
+}
+
+long XPropertyList::GetIndex(const OUString& rName) const
+{
+ if( mbListDirty )
+ {
+ if( !const_cast<XPropertyList*>(this)->Load() )
+ const_cast<XPropertyList*>(this)->Create();
+ }
+
+ for( long i = 0, n = maList.size(); i < n; ++i ) {
+ if (rName == maList[ i ]->GetName()) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+BitmapEx XPropertyList::GetUiBitmap( long nIndex ) const
+{
+ BitmapEx aRetval;
+ if (!isValidIdx(nIndex))
+ return aRetval;
+
+ XPropertyEntry* pEntry = maList[nIndex].get();
+ aRetval = pEntry->GetUiBitmap();
+
+ if(aRetval.IsEmpty())
+ {
+ aRetval = const_cast< XPropertyList* >(this)->CreateBitmapForUI(nIndex);
+ pEntry->SetUiBitmap(aRetval);
+ }
+ return aRetval;
+}
+
+void XPropertyList::Insert(std::unique_ptr<XPropertyEntry> pEntry, long nIndex)
+{
+ if (!pEntry)
+ {
+ assert(!"empty XPropertyEntry not allowed in XPropertyList");
+ return;
+ }
+
+ if (isValidIdx(nIndex)) {
+ maList.insert( maList.begin()+nIndex, std::move(pEntry) );
+ } else {
+ maList.push_back( std::move(pEntry) );
+ }
+}
+
+void XPropertyList::Replace(std::unique_ptr<XPropertyEntry> pEntry, long nIndex)
+{
+ if (!pEntry)
+ {
+ assert(!"empty XPropertyEntry not allowed in XPropertyList");
+ return;
+ }
+ if (!isValidIdx(nIndex))
+ {
+ assert(!"trying to replace invalid entry in XPropertyList");
+ return;
+ }
+
+ maList[nIndex] = std::move(pEntry);
+}
+
+void XPropertyList::Remove(long nIndex)
+{
+ if (!isValidIdx(nIndex))
+ {
+ assert(!"trying to remove invalid entry in XPropertyList");
+ return;
+ }
+
+ maList.erase(maList.begin() + nIndex);
+}
+
+void XPropertyList::SetName( const OUString& rString )
+{
+ if(!rString.isEmpty())
+ {
+ maName = rString;
+ }
+}
+
+bool XPropertyList::Load()
+{
+ if( mbListDirty )
+ {
+ mbListDirty = false;
+ std::stack<OUString> aDirs;
+
+ sal_Int32 nIndex = 0;
+ do
+ {
+ aDirs.push(maPath.getToken(0, ';', nIndex));
+ }
+ while (nIndex >= 0);
+
+ //try all entries palette path list working back to front until one
+ //succeeds
+ while (!aDirs.empty())
+ {
+ OUString aPath(aDirs.top());
+ aDirs.pop();
+
+ INetURLObject aURL(aPath);
+
+ if( INetProtocol::NotValid == aURL.GetProtocol() )
+ {
+ DBG_ASSERT( aPath.isEmpty(), "invalid URL" );
+ return false;
+ }
+
+ aURL.Append( maName );
+
+ if( aURL.getExtension().isEmpty() )
+ aURL.setExtension( GetDefaultExt() );
+
+ bool bRet = SvxXMLXTableImport::load(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
+ maReferer, uno::Reference < embed::XStorage >(),
+ createInstance(), nullptr );
+ if (bRet)
+ return bRet;
+ }
+ }
+ return false;
+}
+
+bool XPropertyList::LoadFrom( const uno::Reference < embed::XStorage > &xStorage,
+ const OUString &rURL, const OUString &rReferer )
+{
+ if( !mbListDirty )
+ return false;
+ mbListDirty = false;
+ return SvxXMLXTableImport::load( rURL, rReferer, xStorage, createInstance(), &mbEmbedInDocument );
+}
+
+bool XPropertyList::Save()
+{
+ //save to the last path in the palette path list
+ OUString aLastDir;
+ sal_Int32 nIndex = 0;
+ do
+ {
+ aLastDir = maPath.getToken(0, ';', nIndex);
+ }
+ while (nIndex >= 0);
+
+ INetURLObject aURL(aLastDir);
+
+ if( INetProtocol::NotValid == aURL.GetProtocol() )
+ {
+ DBG_ASSERT( aLastDir.isEmpty(), "invalid URL" );
+ return false;
+ }
+
+ aURL.Append( maName );
+
+ if( aURL.getExtension().isEmpty() )
+ aURL.setExtension( GetDefaultExt() );
+
+ return SvxXMLXTableExportComponent::save( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
+ createInstance(),
+ uno::Reference< embed::XStorage >(), nullptr );
+}
+
+bool XPropertyList::SaveTo( const uno::Reference< embed::XStorage > &xStorage,
+ const OUString &rURL, OUString *pOptName )
+{
+ return SvxXMLXTableExportComponent::save( rURL, createInstance(), xStorage, pOptName );
+}
+
+XPropertyListRef XPropertyList::CreatePropertyList( XPropertyListType aType,
+ const OUString& rPath,
+ const OUString& rReferer )
+{
+ XPropertyListRef pRet;
+
+ switch (aType) {
+ case XPropertyListType::Color:
+ pRet = XPropertyListRef(new XColorList(rPath, rReferer));
+ break;
+ case XPropertyListType::LineEnd:
+ pRet = XPropertyListRef(new XLineEndList(rPath, rReferer));
+ break;
+ case XPropertyListType::Dash:
+ pRet = XPropertyListRef(new XDashList(rPath, rReferer));
+ break;
+ case XPropertyListType::Hatch:
+ pRet = XPropertyListRef(new XHatchList(rPath, rReferer));
+ break;
+ case XPropertyListType::Gradient:
+ pRet = XPropertyListRef(new XGradientList(rPath, rReferer));
+ break;
+ case XPropertyListType::Bitmap:
+ pRet = XPropertyListRef(new XBitmapList(rPath, rReferer));
+ break;
+ case XPropertyListType::Pattern:
+ pRet = XPropertyListRef(new XPatternList(rPath, rReferer));
+ break;
+ default:
+ OSL_FAIL("unknown xproperty type");
+ break;
+ }
+ OSL_ASSERT( !pRet.is() || pRet->meType == aType );
+
+ return pRet;
+}
+
+XPropertyListRef
+XPropertyList::CreatePropertyListFromURL( XPropertyListType t,
+ const OUString & rURLStr )
+{
+ INetURLObject aURL( rURLStr );
+ INetURLObject aPathURL( aURL );
+
+ aPathURL.removeSegment();
+ aPathURL.removeFinalSlash();
+
+ XPropertyListRef pList = XPropertyList::CreatePropertyList(
+ t, aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), "" );
+ pList->SetName( aURL.getName() );
+
+ return pList;
+}
+
+static struct {
+ XPropertyListType t;
+ const char *pExt;
+} const pExtnMap[] = {
+ { XPropertyListType::Color, "soc" },
+ { XPropertyListType::LineEnd, "soe" },
+ { XPropertyListType::Dash, "sod" },
+ { XPropertyListType::Hatch, "soh" },
+ { XPropertyListType::Gradient, "sog" },
+ { XPropertyListType::Bitmap, "sob" },
+ { XPropertyListType::Pattern, "sop"}
+};
+
+OUString XPropertyList::GetDefaultExt( XPropertyListType t )
+{
+ for (const auto & i : pExtnMap)
+ {
+ if( i.t == t )
+ return OUString::createFromAscii( i.pExt );
+ }
+ return OUString();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtablend.cxx b/svx/source/xoutdev/xtablend.cxx
new file mode 100644
index 000000000..e8f73a996
--- /dev/null
+++ b/svx/source/xoutdev/xtablend.cxx
@@ -0,0 +1,166 @@
+/* -*- 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 <XPropertyTable.hxx>
+#include <vcl/virdev.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+
+#include <svx/xtable.hxx>
+#include <drawinglayer/attribute/linestartendattribute.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <memory>
+
+using namespace com::sun::star;
+
+XLineEndList::XLineEndList( const OUString& rPath, const OUString& rReferer )
+ : XPropertyList( XPropertyListType::LineEnd, rPath, rReferer )
+{
+}
+
+XLineEndList::~XLineEndList()
+{
+}
+
+XLineEndEntry* XLineEndList::GetLineEnd(long nIndex) const
+{
+ return static_cast<XLineEndEntry*>( XPropertyList::Get(nIndex) );
+}
+
+uno::Reference< container::XNameContainer > XLineEndList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXLineEndTable_createInstance( this ), uno::UNO_QUERY );
+}
+
+bool XLineEndList::Create()
+{
+ basegfx::B2DPolygon aTriangle;
+ aTriangle.append(basegfx::B2DPoint(10.0, 0.0));
+ aTriangle.append(basegfx::B2DPoint(0.0, 30.0));
+ aTriangle.append(basegfx::B2DPoint(20.0, 30.0));
+ aTriangle.setClosed(true);
+ Insert( std::make_unique<XLineEndEntry>( basegfx::B2DPolyPolygon(aTriangle), SvxResId( RID_SVXSTR_ARROW ) ) );
+
+ basegfx::B2DPolygon aSquare;
+ aSquare.append(basegfx::B2DPoint(0.0, 0.0));
+ aSquare.append(basegfx::B2DPoint(10.0, 0.0));
+ aSquare.append(basegfx::B2DPoint(10.0, 10.0));
+ aSquare.append(basegfx::B2DPoint(0.0, 10.0));
+ aSquare.setClosed(true);
+ Insert( std::make_unique<XLineEndEntry>( basegfx::B2DPolyPolygon(aSquare), SvxResId( RID_SVXSTR_SQUARE ) ) );
+
+ basegfx::B2DPolygon aCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), 100.0));
+ Insert( std::make_unique<XLineEndEntry>( basegfx::B2DPolyPolygon(aCircle), SvxResId( RID_SVXSTR_CIRCLE ) ) );
+
+ return true;
+}
+
+BitmapEx XLineEndList::CreateBitmapForUI( long nIndex )
+{
+ BitmapEx aRetval;
+ OSL_ENSURE(nIndex < Count(), "OOps, access out of range (!)");
+
+ if(nIndex < Count())
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size& rSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
+
+ const Size aSize(rSize.Width() * 2, rSize.Height());
+
+ // prepare line geometry
+ basegfx::B2DPolygon aLine;
+ const double fBorderDistance(aSize.Height() * 0.1);
+
+ aLine.append(basegfx::B2DPoint(fBorderDistance, aSize.Height() / 2));
+ aLine.append(basegfx::B2DPoint(aSize.Width() - fBorderDistance, aSize.Height() / 2));
+
+ // prepare LineAttribute
+ const basegfx::BColor aLineColor(rStyleSettings.GetFieldTextColor().getBColor());
+ const double fLineWidth(StyleSettings::GetListBoxPreviewDefaultLineWidth() * 1.1);
+ const drawinglayer::attribute::LineAttribute aLineAttribute(
+ aLineColor,
+ fLineWidth);
+
+ const basegfx::B2DPolyPolygon aLineEnd(GetLineEnd(nIndex)->GetLineEnd());
+ const double fArrowHeight(aSize.Height() - (2.0 * fBorderDistance));
+ const drawinglayer::attribute::LineStartEndAttribute aLineStartEndAttribute(
+ fArrowHeight,
+ aLineEnd,
+ false);
+
+ // prepare line primitive
+ const drawinglayer::primitive2d::Primitive2DReference aLineStartEndPrimitive(
+ new drawinglayer::primitive2d::PolygonStrokeArrowPrimitive2D(
+ aLine,
+ aLineAttribute,
+ aLineStartEndAttribute,
+ aLineStartEndAttribute));
+
+ // prepare VirtualDevice
+ ScopedVclPtrInstance< VirtualDevice > pVirtualDevice;
+ const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
+
+ pVirtualDevice->SetOutputSizePixel(aSize);
+ pVirtualDevice->SetDrawMode(rStyleSettings.GetHighContrastMode()
+ ? DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient
+ : DrawModeFlags::Default);
+
+ if(rStyleSettings.GetPreviewUsesCheckeredBackground())
+ {
+ const Point aNull(0, 0);
+ static const sal_uInt32 nLen(8);
+ static const Color aW(COL_WHITE);
+ static const Color aG(0xef, 0xef, 0xef);
+ pVirtualDevice->DrawCheckered(aNull, aSize, nLen, aW, aG);
+ }
+ else
+ {
+ pVirtualDevice->SetBackground(rStyleSettings.GetFieldColor());
+ pVirtualDevice->Erase();
+ }
+
+ // create processor and draw primitives
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
+ *pVirtualDevice,
+ aNewViewInformation2D));
+
+ if(pProcessor2D)
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer aSequence { aLineStartEndPrimitive };
+
+ pProcessor2D->process(aSequence);
+ pProcessor2D.reset();
+ }
+
+ // get result bitmap and scale
+ aRetval = pVirtualDevice->GetBitmapEx(Point(0, 0), pVirtualDevice->GetOutputSizePixel());
+ }
+
+ return aRetval;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/xoutdev/xtabptrn.cxx b/svx/source/xoutdev/xtabptrn.cxx
new file mode 100644
index 000000000..8a53168b4
--- /dev/null
+++ b/svx/source/xoutdev/xtabptrn.cxx
@@ -0,0 +1,150 @@
+/* -*- 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 <XPropertyTable.hxx>
+
+#include <vcl/virdev.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svx/xtable.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/BitmapTools.hxx>
+
+using namespace com::sun::star;
+
+XBitmapEntry* XPatternList::GetBitmap(long nIndex) const
+{
+ return static_cast<XBitmapEntry*>( XPropertyList::Get(nIndex) );
+}
+
+uno::Reference< container::XNameContainer > XPatternList::createInstance()
+{
+ return uno::Reference< container::XNameContainer >(
+ SvxUnoXBitmapTable_createInstance( this ), uno::UNO_QUERY );
+}
+
+bool XPatternList::Create()
+{
+ OUStringBuffer aStr(SvxResId(RID_SVXSTR_PATTERN));
+ std::array<sal_uInt8,64> aArray;
+ BitmapEx aBitmap;
+ const sal_Int32 nLen(aStr.getLength() - 1);
+
+ aArray.fill(0);
+
+ // white/white bitmap
+ aStr.append(" 1");
+ aBitmap = vcl::bitmap::createHistorical8x8FromArray(aArray, COL_WHITE, COL_WHITE);
+ Insert(std::make_unique<XBitmapEntry>(Graphic(aBitmap), aStr.toString()));
+
+ // black/white bitmap
+ aArray[ 0] = 1; aArray[ 9] = 1; aArray[18] = 1; aArray[27] = 1;
+ aArray[36] = 1; aArray[45] = 1; aArray[54] = 1; aArray[63] = 1;
+ aStr[nLen] = '2';
+ aBitmap = vcl::bitmap::createHistorical8x8FromArray(aArray, COL_BLACK, COL_WHITE);
+ Insert(std::make_unique<XBitmapEntry>(Graphic(aBitmap), aStr.toString()));
+
+ // lightred/white bitmap
+ aArray[ 7] = 1; aArray[14] = 1; aArray[21] = 1; aArray[28] = 1;
+ aArray[35] = 1; aArray[42] = 1; aArray[49] = 1; aArray[56] = 1;
+ aStr[nLen] = '3';
+ aBitmap = vcl::bitmap::createHistorical8x8FromArray(aArray, COL_LIGHTRED, COL_WHITE);
+ Insert(std::make_unique<XBitmapEntry>(Graphic(aBitmap), aStr.toString()));
+
+ // lightblue/white bitmap
+ aArray[24] = 1; aArray[25] = 1; aArray[26] = 1;
+ aArray[29] = 1; aArray[30] = 1; aArray[31] = 1;
+ aStr[nLen] = '4';
+ aBitmap = vcl::bitmap::createHistorical8x8FromArray(aArray, COL_LIGHTBLUE, COL_WHITE);
+ Insert(std::make_unique<XBitmapEntry>(Graphic(aBitmap), aStr.toString()));
+
+ return true;
+}
+
+BitmapEx XPatternList::CreateBitmap( long nIndex, const Size& rSize ) const
+{
+ assert( nIndex < Count() );
+
+ if(nIndex < Count())
+ {
+ BitmapEx rBitmapEx = GetBitmap( nIndex )->GetGraphicObject().GetGraphic().GetBitmapEx();
+ ScopedVclPtrInstance< VirtualDevice > pVirtualDevice;
+ pVirtualDevice->SetOutputSizePixel(rSize);
+
+ if(rBitmapEx.IsTransparent())
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+ if(rStyleSettings.GetPreviewUsesCheckeredBackground())
+ {
+ const Point aNull(0, 0);
+ static const sal_uInt32 nLen(8);
+ static const Color aW(COL_WHITE);
+ static const Color aG(0xef, 0xef, 0xef);
+
+ pVirtualDevice->DrawCheckered(aNull, rSize, nLen, aW, aG);
+ }
+ else
+ {
+ pVirtualDevice->SetBackground(rStyleSettings.GetFieldColor());
+ pVirtualDevice->Erase();
+ }
+ }
+
+ if(rBitmapEx.GetSizePixel().Width() >= rSize.Width() && rBitmapEx.GetSizePixel().Height() >= rSize.Height())
+ {
+ rBitmapEx.Scale(rSize);
+ pVirtualDevice->DrawBitmapEx(Point(0, 0), rBitmapEx);
+ }
+ else
+ {
+ const Size aBitmapSize(rBitmapEx.GetSizePixel());
+
+ for(long y(0); y < rSize.Height(); y += aBitmapSize.Height())
+ {
+ for(long x(0); x < rSize.Width(); x += aBitmapSize.Width())
+ {
+ pVirtualDevice->DrawBitmapEx(
+ Point(x, y),
+ rBitmapEx);
+ }
+ }
+ }
+ rBitmapEx = pVirtualDevice->GetBitmapEx(Point(0, 0), rSize);
+ return rBitmapEx;
+ }
+ else
+ return BitmapEx();
+}
+
+BitmapEx XPatternList::CreateBitmapForUI( long nIndex )
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size& rSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
+ return CreateBitmap(nIndex, rSize);
+}
+
+BitmapEx XPatternList::GetBitmapForPreview( long nIndex, const Size& rSize )
+{
+ return CreateBitmap(nIndex, rSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */