xref: /core/svx/source/xoutdev/xattr.cxx (revision 42b03777256ef9688f01d39792cfd0cbc89d0ad3)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <utility>
23 
24 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
25 #include <com/sun/star/drawing/Hatch.hpp>
26 #include <com/sun/star/drawing/LineStyle.hpp>
27 #include <com/sun/star/drawing/LineDash.hpp>
28 #include <com/sun/star/drawing/DashStyle.hpp>
29 #include <com/sun/star/drawing/FillStyle.hpp>
30 #include <com/sun/star/awt/Gradient2.hpp>
31 #include <com/sun/star/uno/Sequence.hxx>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 
34 #include <comphelper/propertyvalue.hxx>
35 #include <o3tl/string_view.hxx>
36 #include <o3tl/any.hxx>
37 #include <svl/itempool.hxx>
38 #include <editeng/memberids.h>
39 #include <docmodel/uno/UnoGradientTools.hxx>
40 #include <docmodel/uno/UnoComplexColor.hxx>
41 #include <docmodel/color/ComplexColorJSON.hxx>
42 #include <tools/mapunit.hxx>
43 #include <tools/UnitConversion.hxx>
44 #include <osl/diagnose.h>
45 
46 #include <svx/unoapi.hxx>
47 #include <svl/style.hxx>
48 
49 #include <tools/bigint.hxx>
50 #include <svl/itemset.hxx>
51 #include <svx/strings.hrc>
52 #include <svx/xfillit0.hxx>
53 #include <svx/xflasit.hxx>
54 #include <svx/xlineit0.hxx>
55 #include <svx/xlnasit.hxx>
56 #include <svx/xtextit0.hxx>
57 #include <svx/xtable.hxx>
58 #include <svx/dialmgr.hxx>
59 #include <svx/xflclit.hxx>
60 #include <svx/xflgrit.hxx>
61 #include <svx/xflftrit.hxx>
62 #include <svx/xsflclit.hxx>
63 #include <svx/xflhtit.hxx>
64 #include <svx/xbtmpit.hxx>
65 #include <svx/xlndsit.hxx>
66 #include <svx/xlnwtit.hxx>
67 #include <svx/xlnclit.hxx>
68 #include <svx/xlnstit.hxx>
69 #include <svx/xlnedit.hxx>
70 #include <svx/xlnstwit.hxx>
71 #include <svx/xlnedwit.hxx>
72 #include <svx/xlnstcit.hxx>
73 #include <svx/xlnedcit.hxx>
74 #include <editeng/itemtype.hxx>
75 #include <editeng/eerdll.hxx>
76 #include <svx/xdef.hxx>
77 #include <svx/unomid.hxx>
78 #include <svx/svdmodel.hxx>
79 #include <svx/xftdiit.hxx>
80 #include <svx/xftstit.hxx>
81 #include <svx/xftmrit.hxx>
82 #include <svx/xftouit.hxx>
83 #include <svx/xftshit.hxx>
84 #include <svx/xftshcit.hxx>
85 #include <svx/xftshxy.hxx>
86 #include <svx/xftadit.hxx>
87 #include <svx/svddef.hxx>
88 #include <basegfx/polygon/b2dpolypolygontools.hxx>
89 #include <unotools/intlwrapper.hxx>
90 #include <unotools/syslocale.hxx>
91 #include <string>
92 
93 #include <boost/property_tree/ptree.hpp>
94 #include <libxml/xmlwriter.h>
95 
96 using namespace ::com::sun::star;
97 
98 typedef std::map<OUString, OUString> StringMap;
99 
NameOrIndex(TypedWhichId<NameOrIndex> _nWhich,sal_Int32 nIndex)100 NameOrIndex::NameOrIndex(TypedWhichId<NameOrIndex> _nWhich, sal_Int32 nIndex) :
101     SfxStringItem(_nWhich, OUString()),
102     m_nPalIndex(nIndex)
103 {
104     setNameOrIndex();
105 }
106 
NameOrIndex(TypedWhichId<NameOrIndex> _nWhich,const OUString & rName)107 NameOrIndex::NameOrIndex(TypedWhichId<NameOrIndex> _nWhich, const OUString& rName) :
108     SfxStringItem(_nWhich, rName),
109     m_nPalIndex(-1)
110 {
111     setNameOrIndex();
112 }
113 
NameOrIndex(const NameOrIndex & rNameOrIndex)114 NameOrIndex::NameOrIndex(const NameOrIndex& rNameOrIndex) :
115     SfxStringItem(rNameOrIndex),
116     m_nPalIndex(rNameOrIndex.m_nPalIndex)
117 {
118     setNameOrIndex();
119 }
120 
operator ==(const SfxPoolItem & rItem) const121 bool NameOrIndex::operator==(const SfxPoolItem& rItem) const
122 {
123     return ( SfxStringItem::operator==(rItem) &&
124             static_cast<const NameOrIndex&>(rItem).m_nPalIndex == m_nPalIndex );
125 }
126 
Clone(SfxItemPool *) const127 NameOrIndex* NameOrIndex::Clone(SfxItemPool* /*pPool*/) const
128 {
129     return new NameOrIndex(*this);
130 }
131 
132 /** this static checks if the given NameOrIndex item has a unique name for its value.
133     The returned String is a unique name for an item with this value in both given pools.
134     Argument pPool2 can be null.
135     If returned string equals NameOrIndex->GetName(), the name was already unique.
136 */
CheckNamedItem(const sal_uInt16 nWhich,const SfxItemPool * pPool1,SvxCompareValueFunc pCompareValueFunc,TranslateId pPrefixResId,const XPropertyListRef & pDefaults) const137 OUString NameOrIndex::CheckNamedItem(const sal_uInt16 nWhich, const SfxItemPool* pPool1, SvxCompareValueFunc pCompareValueFunc, TranslateId pPrefixResId, const XPropertyListRef &pDefaults) const
138 {
139     bool bForceNew = false;
140 
141     OUString aUniqueName = SvxUnogetInternalNameForItem(nWhich, GetName());
142 
143     // 2. if we have a name check if there is already an item with the
144     // same name in the documents pool with a different line end or start
145 
146     if (!aUniqueName.isEmpty() && pPool1)
147     {
148         // use special version to get buffered NameOrIndex Items
149         for (const SfxPoolItem* pItem : pPool1->GetItemSurrogatesForItem(*this))
150         {
151             const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
152 
153             // need to check for WhichID, GetItemSurrogatesForItem does buffer on type only
154             if( pNameOrIndex != this && pNameOrIndex->Which() == nWhich && pNameOrIndex->GetName() == GetName() )
155             {
156                 // if there is already an item with the same name and the same
157                 // value it's ok to set it
158                 if( !pCompareValueFunc( pNameOrIndex, this ) )
159                 {
160                     // same name but different value, we need a new name for this item
161                     aUniqueName.clear();
162                     bForceNew = true;
163                 }
164                 break;
165             }
166         }
167     }
168 
169     // if we have no name yet, find existing item with same content or
170     // create a unique name
171     if (aUniqueName.isEmpty())
172     {
173         sal_Int32 nUserIndex = 1;
174         const OUString aUser(SvxResId(pPrefixResId) + " ");
175 
176         if( pDefaults )
177         {
178             const int nCount = pDefaults->Count();
179             int nIndex;
180             for( nIndex = 0; nIndex < nCount; nIndex++ )
181             {
182                 const XPropertyEntry* pEntry = pDefaults->Get(nIndex);
183                 if( pEntry )
184                 {
185                     bool bFound = false;
186 
187                     switch( nWhich )
188                     {
189                     case XATTR_FILLBITMAP:
190                     {
191                         const GraphicObject& rGraphicObjectA(static_cast<const XFillBitmapItem*>(this)->GetGraphicObject());
192                         const GraphicObject& rGraphicObjectB(static_cast<const XBitmapEntry*>(pEntry)->GetGraphicObject());
193 
194                         bFound = (rGraphicObjectA == rGraphicObjectB);
195                         break;
196                     }
197                     case XATTR_LINEDASH:
198                         bFound = static_cast<const XLineDashItem*>(this)->GetDashValue() == static_cast<const XDashEntry*>(pEntry)->GetDash();
199                         break;
200                     case XATTR_LINESTART:
201                         bFound = static_cast<const XLineStartItem*>(this)->GetLineStartValue() == static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd();
202                         break;
203                     case XATTR_LINEEND:
204                         bFound = static_cast<const XLineEndItem*>(this)->GetLineEndValue() == static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd();
205                         break;
206                     case XATTR_FILLGRADIENT:
207                         bFound = static_cast<const XFillGradientItem*>(this)->GetGradientValue() == static_cast<const XGradientEntry*>(pEntry)->GetGradient();
208                         break;
209                     case XATTR_FILLHATCH:
210                         bFound = static_cast<const XFillHatchItem*>(this)->GetHatchValue() == static_cast<const XHatchEntry*>(pEntry)->GetHatch();
211                         break;
212                     }
213 
214                     if( bFound )
215                     {
216                         aUniqueName = pEntry->GetName();
217                         break;
218                     }
219                     else
220                     {
221                         const OUString& aEntryName = pEntry->GetName();
222                         if(aEntryName.getLength() >= aUser.getLength())
223                         {
224                             sal_Int32 nThisIndex = o3tl::toInt32(aEntryName.subView( aUser.getLength() ));
225                             if( nThisIndex >= nUserIndex )
226                                 nUserIndex = nThisIndex + 1;
227                         }
228                     }
229                 }
230             }
231         }
232 
233         if (aUniqueName.isEmpty() && pPool1)
234         {
235             // use special version to get buffered NameOrIndex Items
236             for (const SfxPoolItem* pItem : pPool1->GetItemSurrogatesForItem(*this))
237             {
238                 const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
239 
240                 // need to check for WhichID, GetItemSurrogatesForItem does buffer on type only
241                 if( pNameOrIndex != this && pNameOrIndex->Which() == nWhich && !pNameOrIndex->GetName().isEmpty() )
242                 {
243                     if( !bForceNew && pCompareValueFunc( pNameOrIndex, this ) )
244                         return pNameOrIndex->GetName();
245 
246                     if( pNameOrIndex->GetName().startsWith( aUser ) )
247                     {
248                         sal_Int32 nThisIndex = o3tl::toInt32(pNameOrIndex->GetName().subView( aUser.getLength() ));
249                         if( nThisIndex >= nUserIndex )
250                             nUserIndex = nThisIndex + 1;
251                     }
252                 }
253             }
254             aUniqueName = aUser + OUString::number( nUserIndex );
255         }
256     }
257 
258     return aUniqueName;
259 }
260 
dumpAsXml(xmlTextWriterPtr pWriter) const261 void NameOrIndex::dumpAsXml(xmlTextWriterPtr pWriter) const
262 {
263     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("NameOrIndex"));
264     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
265     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("isIndex"), BAD_CAST(OString::boolean(IsIndex()).getStr()));
266     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
267     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("index"), BAD_CAST(OString::number(m_nPalIndex).getStr()));
268     (void)xmlTextWriterEndElement(pWriter);
269 }
270 
CreateDefault()271 SfxPoolItem* XColorItem::CreateDefault() { return new XColorItem(); }
272 
XColorItem(TypedWhichId<XColorItem> _nWhich,sal_Int32 nIndex,const Color & rTheColor)273 XColorItem::XColorItem(TypedWhichId<XColorItem> _nWhich, sal_Int32 nIndex, const Color& rTheColor) :
274     NameOrIndex(_nWhich, nIndex),
275     m_aColor(rTheColor)
276 {
277 }
278 
XColorItem(TypedWhichId<XColorItem> _nWhich,const OUString & rName,const Color & rTheColor)279 XColorItem::XColorItem(TypedWhichId<XColorItem> _nWhich, const OUString& rName, const Color& rTheColor) :
280     NameOrIndex(_nWhich, rName),
281     m_aColor(rTheColor)
282 {
283 }
284 
XColorItem(TypedWhichId<XColorItem> _nWhich,const Color & rTheColor)285 XColorItem::XColorItem(TypedWhichId<XColorItem> _nWhich, const Color& rTheColor)
286     : NameOrIndex(_nWhich, OUString())
287     , m_aColor(rTheColor)
288 {
289 }
290 
XColorItem(const XColorItem & rItem)291 XColorItem::XColorItem(const XColorItem& rItem) :
292     NameOrIndex(rItem),
293     m_aColor(rItem.m_aColor),
294     maComplexColor(rItem.maComplexColor)
295 {
296 }
297 
Clone(SfxItemPool *) const298 XColorItem* XColorItem::Clone(SfxItemPool* /*pPool*/) const
299 {
300     return new XColorItem(*this);
301 }
302 
operator ==(const SfxPoolItem & rItem) const303 bool XColorItem::operator==(const SfxPoolItem& rItem) const
304 {
305     return ( NameOrIndex::operator==(rItem) &&
306             static_cast<const XColorItem&>(rItem).m_aColor == m_aColor ) &&
307             static_cast<const XColorItem&>(rItem).maComplexColor == maComplexColor;
308 }
309 
GetColorValue() const310 const Color& XColorItem::GetColorValue() const
311 {
312     assert(!IsIndex());
313     return m_aColor;
314 
315 }
316 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const317 bool XColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId) const
318 {
319     nMemberId &= ~CONVERT_TWIPS;
320     switch (nMemberId)
321     {
322         case MID_COMPLEX_COLOR:
323         {
324             auto xComplexColor = model::color::createXComplexColor(getComplexColor());
325             rVal <<= xComplexColor;
326             break;
327         }
328         case MID_COMPLEX_COLOR_JSON:
329         {
330             rVal <<= OStringToOUString(model::color::convertToJSON(getComplexColor()), RTL_TEXTENCODING_UTF8);
331             break;
332         }
333         default:
334         {
335             rVal <<= GetColorValue().GetRGBColor();
336             break;
337         }
338     }
339     return true;
340 }
341 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)342 bool XColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId)
343 {
344     nMemberId &= ~CONVERT_TWIPS;
345     switch (nMemberId)
346     {
347         case MID_COMPLEX_COLOR:
348         {
349             css::uno::Reference<css::util::XComplexColor> xComplexColor;
350             if (!(rVal >>= xComplexColor))
351                 return false;
352             setComplexColor(model::color::getFromXComplexColor(xComplexColor));
353         }
354         break;
355         case MID_COMPLEX_COLOR_JSON:
356         {
357             OUString sComplexColorJson;
358             if (!(rVal >>= sComplexColorJson))
359                 return false;
360 
361             if (sComplexColorJson.isEmpty())
362                 return false;
363 
364             OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
365             model::ComplexColor aComplexColor;
366             model::color::convertFromJSON(aJSON, aComplexColor);
367             setComplexColor(aComplexColor);
368         }
369         break;
370         default:
371         {
372             Color nValue;
373             if(!(rVal >>= nValue ))
374                 return false;
375 
376             SetColorValue( nValue );
377 
378         }
379         break;
380     }
381     return true;
382 }
383 
dumpAsXml(xmlTextWriterPtr pWriter) const384 void XColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const
385 {
386     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XColorItem"));
387     if (Which() == SDRATTR_SHADOWCOLOR)
388     {
389         (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST("SDRATTR_SHADOWCOLOR"));
390     }
391     else if (Which() == XATTR_FILLCOLOR)
392     {
393         (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST("XATTR_FILLCOLOR"));
394     }
395     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("aColor"),
396                                 BAD_CAST(m_aColor.AsRGBHexString().toUtf8().getStr()));
397 
398     NameOrIndex::dumpAsXml(pWriter);
399 
400     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("complex-color"));
401 
402     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("scheme-index"),
403                                       BAD_CAST(OString::number(sal_Int16(maComplexColor.getThemeColorType())).getStr()));
404 
405     for (auto const& rTransform : maComplexColor.getTransformations())
406     {
407         (void)xmlTextWriterStartElement(pWriter, BAD_CAST("transformation"));
408         (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("type"),
409                                       BAD_CAST(OString::number(sal_Int16(rTransform.meType)).getStr()));
410         (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
411                                       BAD_CAST(OString::number(rTransform.mnValue).getStr()));
412         (void)xmlTextWriterEndElement(pWriter);
413     }
414 
415     (void)xmlTextWriterEndElement(pWriter);
416 
417     (void)xmlTextWriterEndElement(pWriter);
418 }
419 
420 // --- line attributes ---
421 
422 
CreateDefault()423 SfxPoolItem* XLineStyleItem::CreateDefault() { return new XLineStyleItem; }
424 
XLineStyleItem(css::drawing::LineStyle eTheLineStyle)425 XLineStyleItem::XLineStyleItem(css::drawing::LineStyle eTheLineStyle) :
426     SfxEnumItem(XATTR_LINESTYLE, eTheLineStyle)
427 {
428 }
429 
Clone(SfxItemPool *) const430 XLineStyleItem* XLineStyleItem::Clone(SfxItemPool* /*pPool*/) const
431 {
432     return new XLineStyleItem( *this );
433 }
434 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const435 bool XLineStyleItem::GetPresentation
436 (
437     SfxItemPresentation /*ePres*/,
438     MapUnit             /*eCoreUnit*/,
439     MapUnit             /*ePresUnit*/,
440     OUString&           rText, const IntlWrapper&
441 )   const
442 {
443     rText.clear();
444 
445     TranslateId pId;
446 
447     switch( GetValue() )
448     {
449         case css::drawing::LineStyle_NONE:
450             pId = RID_SVXSTR_INVISIBLE;
451             break;
452         case css::drawing::LineStyle_SOLID:
453             pId = RID_SVXSTR_SOLID;
454             break;
455         default: break;
456     }
457 
458     if (pId)
459         rText = SvxResId(pId);
460     return true;
461 }
462 
QueryValue(css::uno::Any & rVal,sal_uInt8) const463 bool XLineStyleItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
464 {
465     css::drawing::LineStyle eLS = GetValue();
466     rVal <<= eLS;
467     return true;
468 }
469 
PutValue(const css::uno::Any & rVal,sal_uInt8)470 bool XLineStyleItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
471 {
472     css::drawing::LineStyle eLS;
473     if(!(rVal >>= eLS ))
474     {
475         // also try an int (for Basic)
476         sal_Int32 nLS = 0;
477         if(!(rVal >>= nLS))
478             return false;
479         eLS = static_cast<css::drawing::LineStyle>(nLS);
480     }
481 
482     SetValue( eLS );
483     return true;
484 }
485 
XDash(css::drawing::DashStyle eTheDash,sal_uInt16 nTheDots,double nTheDotLen,sal_uInt16 nTheDashes,double nTheDashLen,double nTheDistance)486 XDash::XDash(css::drawing::DashStyle eTheDash, sal_uInt16 nTheDots, double nTheDotLen,
487              sal_uInt16 nTheDashes, double nTheDashLen, double nTheDistance) :
488     m_eDash(eTheDash),
489     m_nDots(nTheDots),
490     m_nDashes(nTheDashes),
491     m_nDotLen(nTheDotLen),
492     m_nDashLen(nTheDashLen),
493     m_nDistance(nTheDistance)
494 {
495 }
496 
operator ==(const XDash & rDash) const497 bool XDash::operator==(const XDash& rDash) const
498 {
499     return ( m_eDash      == rDash.m_eDash      &&
500              m_nDots      == rDash.m_nDots      &&
501              m_nDotLen    == rDash.m_nDotLen    &&
502              m_nDashes    == rDash.m_nDashes    &&
503              m_nDashLen   == rDash.m_nDashLen   &&
504              m_nDistance  == rDash.m_nDistance );
505 }
506 
507 // XDash is translated into an array of doubles which describe the lengths of the
508 // dashes, dots and empty passages. It returns the complete length of the full DashDot
509 // sequence and fills the given vector of doubles accordingly (also resizing, so deleting it).
510 const double SMALLEST_DASH_WIDTH(26.95);
511 
CreateDotDashArray(::std::vector<double> & rDotDashArray,double fLineWidth) const512 double XDash::CreateDotDashArray(::std::vector< double >& rDotDashArray, double fLineWidth) const
513 {
514     double fFullDotDashLen(0.0);
515     const sal_uInt16 nNumDotDashArray = (GetDots() + GetDashes()) * 2;
516     rDotDashArray.resize( nNumDotDashArray, 0.0 );
517     sal_uInt16 a;
518     sal_uInt16 nIns(0);
519     double fDashDotDistance = GetDistance();
520     double fSingleDashLen = GetDashLen();
521     double fSingleDotLen = GetDotLen();
522 
523     if (fLineWidth == 0.0)
524         fLineWidth = SMALLEST_DASH_WIDTH;
525 
526     if(GetDashStyle() == css::drawing::DashStyle_RECTRELATIVE || GetDashStyle() == css::drawing::DashStyle_ROUNDRELATIVE)
527     {
528         double fFactor = fLineWidth / 100.0;
529 
530         if(GetDashes())
531         {
532             if(GetDashLen())
533             {
534                 // is a dash
535                 fSingleDashLen *= fFactor;
536             }
537             else
538             {
539                 // is a dot
540                 fSingleDashLen = fLineWidth;
541             }
542         }
543 
544         if(GetDots())
545         {
546             if(GetDotLen())
547             {
548                 // is a dash
549                 fSingleDotLen *= fFactor;
550             }
551             else
552             {
553                 // is a dot
554                 fSingleDotLen = fLineWidth;
555             }
556         }
557 
558         if(GetDashes() || GetDots())
559         {
560             if(GetDistance())
561             {
562                 // dash as distance
563                 fDashDotDistance *= fFactor;
564             }
565             else
566             {
567                 // dot as distance
568                 fDashDotDistance = fLineWidth;
569             }
570         }
571     }
572     else
573     {
574         // absolute values
575         if(GetDashes())
576         {
577             if(GetDashLen())
578             {
579                 // is a dash
580                 if(fSingleDashLen < SMALLEST_DASH_WIDTH)
581                 {
582                     fSingleDashLen = SMALLEST_DASH_WIDTH;
583                 }
584             }
585             else
586             {
587                 // is a dot
588                 if(fSingleDashLen < fLineWidth)
589                 {
590                     fSingleDashLen = fLineWidth;
591                 }
592             }
593         }
594 
595         if(GetDots())
596         {
597             if(GetDotLen())
598             {
599                 // is a dash
600                 if(fSingleDotLen < SMALLEST_DASH_WIDTH)
601                 {
602                     fSingleDotLen = SMALLEST_DASH_WIDTH;
603                 }
604             }
605             else
606             {
607                 // is a dot
608                 if(fSingleDotLen < fLineWidth)
609                 {
610                     fSingleDotLen = fLineWidth;
611                 }
612             }
613         }
614 
615         if(GetDashes() || GetDots())
616         {
617             if(GetDistance())
618             {
619                 // dash as distance
620                 if(fDashDotDistance < SMALLEST_DASH_WIDTH)
621                 {
622                     fDashDotDistance = SMALLEST_DASH_WIDTH;
623                 }
624             }
625             else
626             {
627                 // dot as distance
628                 if(fDashDotDistance < fLineWidth)
629                 {
630                     fDashDotDistance = fLineWidth;
631                 }
632             }
633         }
634     }
635 
636     for(a=0;a<GetDots();a++)
637     {
638         rDotDashArray[nIns++] = fSingleDotLen;
639         fFullDotDashLen += fSingleDotLen;
640         rDotDashArray[nIns++] = fDashDotDistance;
641         fFullDotDashLen += fDashDotDistance;
642     }
643 
644     for(a=0;a<GetDashes();a++)
645     {
646         rDotDashArray[nIns++] = fSingleDashLen;
647         fFullDotDashLen += fSingleDashLen;
648         rDotDashArray[nIns++] = fDashDotDistance;
649         fFullDotDashLen += fDashDotDistance;
650     }
651 
652     return fFullDotDashLen;
653 }
654 
CreateDefault()655 SfxPoolItem* XLineDashItem::CreateDefault() {return new XLineDashItem;}
656 
XLineDashItem(const OUString & rName,const XDash & rTheDash)657 XLineDashItem::XLineDashItem(const OUString& rName, const XDash& rTheDash) :
658     NameOrIndex(XATTR_LINEDASH, rName),
659     m_aDash(rTheDash)
660 {
661 }
662 
XLineDashItem(const XLineDashItem & rItem)663 XLineDashItem::XLineDashItem(const XLineDashItem& rItem) :
664     NameOrIndex(rItem),
665     m_aDash(rItem.m_aDash)
666 {
667 }
668 
XLineDashItem(const XDash & rTheDash)669 XLineDashItem::XLineDashItem(const XDash& rTheDash)
670 :   NameOrIndex( XATTR_LINEDASH, -1 ),
671     m_aDash(rTheDash)
672 {
673 }
674 
Clone(SfxItemPool *) const675 XLineDashItem* XLineDashItem::Clone(SfxItemPool* /*pPool*/) const
676 {
677     return new XLineDashItem(*this);
678 }
679 
operator ==(const SfxPoolItem & rItem) const680 bool XLineDashItem::operator==(const SfxPoolItem& rItem) const
681 {
682     return ( NameOrIndex::operator==(rItem) &&
683              m_aDash == static_cast<const XLineDashItem&>(rItem).m_aDash );
684 }
685 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const686 bool XLineDashItem::GetPresentation
687 (
688     SfxItemPresentation /*ePres*/,
689     MapUnit             /*eCoreUnit*/,
690     MapUnit             /*ePresUnit*/,
691     OUString&           rText, const IntlWrapper&
692 )   const
693 {
694     rText = GetName();
695     return true;
696 }
697 
HasMetrics() const698 bool XLineDashItem::HasMetrics() const
699 {
700     return true;
701 }
702 
ScaleMetrics(tools::Long nMul,tools::Long nDiv)703 void XLineDashItem::ScaleMetrics(tools::Long nMul, tools::Long nDiv)
704 {
705     m_aDash.SetDotLen( BigInt::Scale( m_aDash.GetDotLen(), nMul, nDiv ) );
706     m_aDash.SetDashLen( BigInt::Scale( m_aDash.GetDashLen(), nMul, nDiv ) );
707     m_aDash.SetDistance( BigInt::Scale( m_aDash.GetDistance(), nMul, nDiv ) );
708 }
709 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const710 bool XLineDashItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
711 {
712     nMemberId &= ~CONVERT_TWIPS;
713 
714     switch ( nMemberId )
715     {
716         case 0:
717         {
718             css::drawing::LineDash aLineDash;
719 
720             const XDash& rXD = GetDashValue();
721             aLineDash.Style = static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(rXD.GetDashStyle()));
722             aLineDash.Dots = rXD.GetDots();
723             aLineDash.DotLen = rXD.GetDotLen();
724             aLineDash.Dashes = rXD.GetDashes();
725             aLineDash.DashLen = rXD.GetDashLen();
726             aLineDash.Distance = rXD.GetDistance();
727 
728             uno::Sequence< beans::PropertyValue > aPropSeq{
729                 comphelper::makePropertyValue(u"Name"_ustr, SvxUnogetApiNameForItem(Which(), GetName())),
730                 comphelper::makePropertyValue(u"LineDash"_ustr, aLineDash)
731             };
732             rVal <<= aPropSeq;
733             break;
734         }
735 
736         case MID_NAME:
737         {
738             rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
739             break;
740         }
741 
742         case MID_LINEDASH:
743         {
744             const XDash& rXD = GetDashValue();
745 
746             css::drawing::LineDash aLineDash;
747 
748             aLineDash.Style = static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(rXD.GetDashStyle()));
749             aLineDash.Dots = rXD.GetDots();
750             aLineDash.DotLen = rXD.GetDotLen();
751             aLineDash.Dashes = rXD.GetDashes();
752             aLineDash.DashLen = rXD.GetDashLen();
753             aLineDash.Distance = rXD.GetDistance();
754 
755             rVal <<= aLineDash;
756             break;
757         }
758 
759         case MID_LINEDASH_STYLE:
760         {
761             const XDash& rXD = GetDashValue();
762             rVal <<= static_cast<css::drawing::DashStyle>(static_cast<sal_Int16>(rXD.GetDashStyle()));
763             break;
764         }
765 
766         case MID_LINEDASH_DOTS:
767         {
768             const XDash& rXD = GetDashValue();
769             rVal <<= rXD.GetDots();
770             break;
771         }
772 
773         case MID_LINEDASH_DOTLEN:
774         {
775             const XDash& rXD = GetDashValue();
776             rVal <<= rXD.GetDotLen();
777             break;
778         }
779 
780         case MID_LINEDASH_DASHES:
781         {
782             const XDash& rXD = GetDashValue();
783             rVal <<= rXD.GetDashes();
784             break;
785         }
786 
787         case MID_LINEDASH_DASHLEN:
788         {
789             const XDash& rXD = GetDashValue();
790             rVal <<= rXD.GetDashLen();
791             break;
792         }
793 
794         case MID_LINEDASH_DISTANCE:
795         {
796             const XDash& rXD = GetDashValue();
797             rVal <<= rXD.GetDistance();
798             break;
799         }
800 
801         default: OSL_FAIL("Wrong MemberId!"); return false;
802     }
803 
804     return true;
805 }
806 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)807 bool XLineDashItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
808 {
809     nMemberId &= ~CONVERT_TWIPS;
810 
811     switch ( nMemberId )
812     {
813         case 0:
814         {
815             uno::Sequence< beans::PropertyValue >   aPropSeq;
816 
817             if ( rVal >>= aPropSeq )
818             {
819                 css::drawing::LineDash aLineDash;
820                 OUString aName;
821                 bool bLineDash( false );
822                 for (const auto& rProp : aPropSeq)
823                 {
824                     if ( rProp.Name == "Name" )
825                         rProp.Value >>= aName;
826                     else if ( rProp.Name == "LineDash" )
827                     {
828                         if ( rProp.Value >>= aLineDash )
829                             bLineDash = true;
830                     }
831                 }
832 
833                 SetName( aName );
834                 if ( bLineDash )
835                 {
836                     XDash aXDash;
837 
838                     aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(aLineDash.Style)));
839                     aXDash.SetDots(aLineDash.Dots);
840                     aXDash.SetDotLen(aLineDash.DotLen);
841                     aXDash.SetDashes(aLineDash.Dashes);
842                     aXDash.SetDashLen(aLineDash.DashLen);
843                     aXDash.SetDistance(aLineDash.Distance);
844 
845                     if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
846                         aXDash.SetDots(1);
847 
848                     SetDashValue( aXDash );
849                 }
850 
851                 return true;
852             }
853 
854             return false;
855         }
856 
857         case MID_NAME:
858         {
859             OUString aName;
860             if (!(rVal >>= aName))
861                 return false;
862             SetName( aName );
863             break;
864         }
865 
866         case MID_LINEDASH:
867         {
868             css::drawing::LineDash aLineDash;
869             if(!(rVal >>= aLineDash))
870                 return false;
871 
872             XDash aXDash;
873 
874             aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(aLineDash.Style)));
875             aXDash.SetDots(aLineDash.Dots);
876             aXDash.SetDotLen(aLineDash.DotLen);
877             aXDash.SetDashes(aLineDash.Dashes);
878             aXDash.SetDashLen(aLineDash.DashLen);
879             aXDash.SetDistance(aLineDash.Distance);
880 
881             if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
882                 aXDash.SetDots(1);
883 
884             SetDashValue( aXDash );
885             break;
886         }
887 
888         case MID_LINEDASH_STYLE:
889         {
890             sal_Int16 nVal = sal_Int16();
891             if(!(rVal >>= nVal))
892                 return false;
893 
894             XDash aXDash = GetDashValue();
895             aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(nVal)));
896 
897             if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
898                 aXDash.SetDots(1);
899 
900             SetDashValue( aXDash );
901 
902             break;
903         }
904 
905         case MID_LINEDASH_DOTS:
906         case MID_LINEDASH_DASHES:
907         {
908             sal_Int16 nVal = sal_Int16();
909             if(!(rVal >>= nVal))
910                 return false;
911 
912             XDash aXDash = GetDashValue();
913             if ( nMemberId == MID_LINEDASH_DOTS )
914                 aXDash.SetDots( nVal );
915             else
916                 aXDash.SetDashes( nVal );
917 
918             if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
919                 aXDash.SetDots(1);
920 
921             SetDashValue( aXDash );
922             break;
923         }
924 
925         case MID_LINEDASH_DOTLEN:
926         case MID_LINEDASH_DASHLEN:
927         case MID_LINEDASH_DISTANCE:
928         {
929             sal_uInt32 nVal = 0;
930             if(!(rVal >>= nVal))
931                 return false;
932 
933             XDash aXDash = GetDashValue();
934             if ( nMemberId == MID_LINEDASH_DOTLEN )
935                 aXDash.SetDotLen( nVal );
936             else if ( nMemberId == MID_LINEDASH_DASHLEN )
937                 aXDash.SetDashLen( nVal );
938             else
939                 aXDash.SetDistance( nVal );
940 
941             if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
942                 aXDash.SetDots(1);
943 
944             SetDashValue( aXDash );
945             break;
946         }
947     }
948 
949     return true;
950 }
951 
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)952 bool XLineDashItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
953 {
954     return static_cast<const XLineDashItem*>(p1)->GetDashValue() == static_cast<const XLineDashItem*>(p2)->GetDashValue();
955 }
956 
checkForUniqueItem(SdrModel & rModel) const957 std::unique_ptr<XLineDashItem> XLineDashItem::checkForUniqueItem( SdrModel& rModel ) const
958 {
959     const OUString aUniqueName(CheckNamedItem(
960         XATTR_LINEDASH, &rModel.GetItemPool(),
961         XLineDashItem::CompareValueFunc, RID_SVXSTR_DASH20,
962         rModel.GetPropertyList(XPropertyListType::Dash)));
963 
964     // if the given name is not valid, replace it!
965     if( aUniqueName != GetName() )
966         return std::make_unique<XLineDashItem>( aUniqueName, m_aDash );
967 
968     return nullptr;
969 }
970 
CreateDefault()971 SfxPoolItem* XLineWidthItem::CreateDefault() {return new XLineWidthItem;}
972 
XLineWidthItem(tools::Long nWidth)973 XLineWidthItem::XLineWidthItem(tools::Long nWidth) :
974     SfxMetricItem(XATTR_LINEWIDTH, nWidth)
975 {
976 }
977 
Clone(SfxItemPool *) const978 XLineWidthItem* XLineWidthItem::Clone(SfxItemPool* /*pPool*/) const
979 {
980     return new XLineWidthItem(*this);
981 }
982 
GetPresentation(SfxItemPresentation,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntl) const983 bool XLineWidthItem::GetPresentation
984 (
985     SfxItemPresentation /*ePres*/,
986     MapUnit             eCoreUnit,
987     MapUnit             ePresUnit,
988     OUString&           rText, const IntlWrapper& rIntl
989 )   const
990 {
991     rText = GetMetricText( static_cast<tools::Long>(GetValue()),
992                             eCoreUnit, ePresUnit, &rIntl) +
993             " " + EditResId( GetMetricId( ePresUnit) );
994     return true;
995 }
996 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const997 bool XLineWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
998 {
999     sal_Int32 nValue = GetValue();
1000     if( 0 != (nMemberId&CONVERT_TWIPS) )
1001         nValue = convertTwipToMm100(nValue);
1002 
1003     rVal <<= nValue;
1004     return true;
1005 }
1006 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1007 bool XLineWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1008 {
1009     sal_Int32 nValue = 0;
1010     rVal >>= nValue;
1011     if( 0 != (nMemberId&CONVERT_TWIPS) )
1012         nValue = o3tl::toTwips(nValue, o3tl::Length::mm100);
1013 
1014     SetValue( nValue );
1015     return true;
1016 }
1017 
CreateDefault()1018 SfxPoolItem* XLineColorItem::CreateDefault() { return new XLineColorItem; }
1019 
XLineColorItem(sal_Int32 nIndex,const Color & rTheColor)1020 XLineColorItem::XLineColorItem(sal_Int32 nIndex, const Color& rTheColor) :
1021     XColorItem(XATTR_LINECOLOR, nIndex, rTheColor)
1022 {
1023 }
1024 
XLineColorItem(const OUString & rName,const Color & rTheColor)1025 XLineColorItem::XLineColorItem(const OUString& rName, const Color& rTheColor) :
1026     XColorItem(XATTR_LINECOLOR, rName, rTheColor)
1027 {
1028 }
1029 
Clone(SfxItemPool *) const1030 XLineColorItem* XLineColorItem::Clone(SfxItemPool* /*pPool*/) const
1031 {
1032     return new XLineColorItem(*this);
1033 }
1034 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1035 bool XLineColorItem::GetPresentation
1036 (
1037     SfxItemPresentation /*ePres*/,
1038     MapUnit             /*eCoreUnit*/,
1039     MapUnit             /*ePresUnit*/,
1040     OUString&           rText, const IntlWrapper&
1041 )   const
1042 {
1043     rText = GetName();
1044     return true;
1045 }
1046 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1047 bool XLineColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId) const
1048 {
1049     nMemberId &= ~CONVERT_TWIPS;
1050     switch (nMemberId)
1051     {
1052         case MID_COMPLEX_COLOR:
1053         {
1054             auto xComplexColor = model::color::createXComplexColor(getComplexColor());
1055             rVal <<= xComplexColor;
1056             break;
1057         }
1058         case MID_COMPLEX_COLOR_JSON:
1059         {
1060             rVal <<= OStringToOUString(model::color::convertToJSON(getComplexColor()), RTL_TEXTENCODING_UTF8);
1061             break;
1062         }
1063         default:
1064         {
1065             rVal <<= GetColorValue().GetRGBColor();
1066             break;
1067         }
1068     }
1069     return true;
1070 }
1071 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1072 bool XLineColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId)
1073 {
1074     nMemberId &= ~CONVERT_TWIPS;
1075     switch(nMemberId)
1076     {
1077         case MID_COMPLEX_COLOR:
1078         {
1079             css::uno::Reference<css::util::XComplexColor> xComplexColor;
1080             if (!(rVal >>= xComplexColor))
1081                 return false;
1082             setComplexColor(model::color::getFromXComplexColor(xComplexColor));
1083         }
1084         break;
1085         case MID_COMPLEX_COLOR_JSON:
1086         {
1087             OUString sComplexColorJson;
1088             if (!(rVal >>= sComplexColorJson))
1089                 return false;
1090 
1091             if (sComplexColorJson.isEmpty())
1092                 return false;
1093             model::ComplexColor aComplexColor;
1094             OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
1095             model::color::convertFromJSON(aJSON, aComplexColor);
1096             setComplexColor(aComplexColor);
1097         }
1098         break;
1099         default:
1100         {
1101             sal_Int32 nValue;
1102             if(!(rVal >>= nValue ))
1103                 return false;
1104 
1105             SetColorValue( Color(ColorTransparency, nValue) );
1106             break;
1107         }
1108     }
1109     return true;
1110 }
1111 
1112 
CreateDefault()1113 SfxPoolItem* XLineStartItem::CreateDefault() {return new XLineStartItem;}
1114 
XLineStartItem(sal_Int32 nIndex)1115 XLineStartItem::XLineStartItem(sal_Int32 nIndex)
1116 :   NameOrIndex(XATTR_LINESTART, nIndex)
1117 {
1118 }
1119 
XLineStartItem(const OUString & rName,basegfx::B2DPolyPolygon aPolyPolygon)1120 XLineStartItem::XLineStartItem(const OUString& rName, basegfx::B2DPolyPolygon aPolyPolygon)
1121 :   NameOrIndex(XATTR_LINESTART, rName),
1122     maPolyPolygon(std::move(aPolyPolygon))
1123 {
1124 }
1125 
XLineStartItem(const XLineStartItem & rItem)1126 XLineStartItem::XLineStartItem(const XLineStartItem& rItem)
1127 :   NameOrIndex(rItem),
1128     maPolyPolygon(rItem.maPolyPolygon)
1129 {
1130 }
1131 
XLineStartItem(basegfx::B2DPolyPolygon aPolyPolygon)1132 XLineStartItem::XLineStartItem(basegfx::B2DPolyPolygon aPolyPolygon)
1133 :   NameOrIndex( XATTR_LINESTART, -1 ),
1134     maPolyPolygon(std::move(aPolyPolygon))
1135 {
1136 }
1137 
Clone(SfxItemPool *) const1138 XLineStartItem* XLineStartItem::Clone(SfxItemPool* /*pPool*/) const
1139 {
1140     return new XLineStartItem(*this);
1141 }
1142 
operator ==(const SfxPoolItem & rItem) const1143 bool XLineStartItem::operator==(const SfxPoolItem& rItem) const
1144 {
1145     return ( NameOrIndex::operator==(rItem) && static_cast<const XLineStartItem&>(rItem).maPolyPolygon == maPolyPolygon );
1146 }
1147 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1148 bool XLineStartItem::GetPresentation
1149 (
1150     SfxItemPresentation /*ePres*/,
1151     MapUnit             /*eCoreUnit*/,
1152     MapUnit             /*ePresUnit*/,
1153     OUString&           rText, const IntlWrapper&
1154 )   const
1155 {
1156     rText = GetName();
1157     return true;
1158 }
1159 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1160 bool XLineStartItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1161 {
1162     nMemberId &= ~CONVERT_TWIPS;
1163     if( nMemberId == MID_NAME )
1164     {
1165         rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
1166     }
1167     else
1168     {
1169         css::drawing::PolyPolygonBezierCoords aBezier;
1170         basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( maPolyPolygon, aBezier );
1171         rVal <<= aBezier;
1172     }
1173 
1174     return true;
1175 }
1176 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1177 bool XLineStartItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1178 {
1179     nMemberId &= ~CONVERT_TWIPS;
1180     if( nMemberId == MID_NAME )
1181     {
1182         return false;
1183     }
1184     else
1185     {
1186         maPolyPolygon.clear();
1187 
1188         if( rVal.hasValue() )
1189         {
1190             auto pCoords = o3tl::tryAccess<css::drawing::PolyPolygonBezierCoords>(
1191                 rVal);
1192             if( !pCoords )
1193                 return false;
1194 
1195             if( pCoords->Coordinates.getLength() > 0 )
1196             {
1197                 maPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords );
1198                 // #i72807# close line start/end polygons hard
1199                 // maPolyPolygon.setClosed(true);
1200             }
1201         }
1202     }
1203 
1204     return true;
1205 }
1206 
HasConflictingStartEndItems(const SfxItemPool & pool,std::u16string_view name,const basegfx::B2DPolyPolygon & value)1207 static bool HasConflictingStartEndItems(const SfxItemPool& pool, std::u16string_view name,
1208                                         const basegfx::B2DPolyPolygon& value)
1209 {
1210     // XATTR_LINESTART
1211     for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineStartItemType))
1212     {
1213         auto pItem = static_cast<const XLineStartItem*>(p);
1214 
1215         if (pItem->GetName() == name)
1216         {
1217             // if there is already an item with the same name and the same value it's not a conflict
1218             if (pItem->GetLineStartValue() == value)
1219                 break;
1220             // same name but different value
1221             return true;
1222         }
1223     }
1224     // XATTR_LINEEND
1225     for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineEndItemType))
1226     {
1227         auto pItem = static_cast<const XLineEndItem*>(p);
1228 
1229         if (pItem->GetName() == name)
1230         {
1231             // if there is already an item with the same name and the same value it's not a conflict
1232             if (pItem->GetLineEndValue() == value)
1233                 break;
1234             // same name but different value
1235             return true;
1236         }
1237     }
1238     return false;
1239 }
1240 
1241 /** this function searches in both the models pool and the styles pool for XLineStartItem and
1242     XLineEndItem with the same name and returns true when it exists and has a different value. */
HasConflictingStartEndItems(const SdrModel & model,std::u16string_view name,const basegfx::B2DPolyPolygon & value)1243 static bool HasConflictingStartEndItems(const SdrModel& model, std::u16string_view name,
1244                                         const basegfx::B2DPolyPolygon& value)
1245 {
1246     return HasConflictingStartEndItems(model.GetItemPool(), name, value)
1247            || (model.GetStyleSheetPool()
1248                && HasConflictingStartEndItems(model.GetStyleSheetPool()->GetPool(), name, value));
1249 }
1250 
CreateNameForValue(const SfxItemPool & pool,const basegfx::B2DPolyPolygon & value,bool forceNew)1251 static OUString CreateNameForValue(const SfxItemPool& pool, const basegfx::B2DPolyPolygon& value,
1252                                    bool forceNew)
1253 {
1254     sal_Int32 nUserIndex = 1;
1255     const OUString aUser(SvxResId(RID_SVXSTR_LINEEND));
1256 
1257     // XATTR_LINEEND first, because previous code preferred existing name from it
1258     for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineEndItemType))
1259     {
1260         auto pItem = static_cast<const XLineEndItem*>(p);
1261 
1262         if (!pItem->GetName().isEmpty())
1263         {
1264             if (!forceNew && pItem->GetLineEndValue() == value)
1265                 return pItem->GetName(); // Found existing
1266 
1267             if (pItem->GetName().startsWith(aUser))
1268             {
1269                 sal_Int32 nThisIndex = o3tl::toInt32(pItem->GetName().subView(aUser.getLength()));
1270                 if (nThisIndex >= nUserIndex)
1271                     nUserIndex = nThisIndex + 1;
1272             }
1273         }
1274     }
1275 
1276     // XATTR_LINESTART
1277     for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineStartItemType))
1278     {
1279         auto pItem = static_cast<const XLineStartItem*>(p);
1280 
1281         if (!pItem->GetName().isEmpty())
1282         {
1283             if (!forceNew && pItem->GetLineStartValue() == value)
1284                 return pItem->GetName(); // Found existing
1285 
1286             if (pItem->GetName().startsWith(aUser))
1287             {
1288                 sal_Int32 nThisIndex = o3tl::toInt32(pItem->GetName().subView(aUser.getLength()));
1289                 if (nThisIndex >= nUserIndex)
1290                     nUserIndex = nThisIndex + 1;
1291             }
1292         }
1293     }
1294 
1295     return aUser + " " + OUString::number(nUserIndex);
1296 }
1297 
1298 /** this function searches in both the models pool and the styles pool for XLineStartItem
1299     and XLineEndItem with the same value or name and returns an item with the value of
1300     this item and a unique name for an item with this value. */
checkForUniqueItem(SdrModel & rModel) const1301 std::unique_ptr<XLineStartItem> XLineStartItem::checkForUniqueItem( SdrModel& rModel ) const
1302 {
1303     std::unique_ptr<XLineStartItem> pTempItem;
1304     const XLineStartItem* pLineStartItem = this;
1305 
1306     OUString aUniqueName( GetName() );
1307 
1308     if( !maPolyPolygon.count() )
1309     {
1310         // if the polygon is empty, check if the name is empty
1311         if( aUniqueName.isEmpty() )
1312             return nullptr;
1313 
1314         // force empty name for empty polygons
1315         return std::make_unique<XLineStartItem>( "", maPolyPolygon );
1316     }
1317 
1318     if( maPolyPolygon.count() > 1 )
1319     {
1320         // check if the polygon is closed
1321         if(!maPolyPolygon.isClosed())
1322         {
1323             // force a closed polygon
1324             basegfx::B2DPolyPolygon aNew(maPolyPolygon);
1325             aNew.setClosed(true);
1326             pTempItem.reset(new XLineStartItem( aUniqueName, std::move(aNew) ));
1327             pLineStartItem = pTempItem.get();
1328         }
1329     }
1330 
1331     bool bForceNew = false;
1332 
1333     // 2. if we have a name check if there is already an item with the
1334     // same name in the documents pool with a different line end or start
1335 
1336     if (!aUniqueName.isEmpty()
1337         && HasConflictingStartEndItems(rModel, pLineStartItem->GetName(),
1338                                        pLineStartItem->GetLineStartValue()))
1339     {
1340         bForceNew = true;
1341         aUniqueName.clear();
1342     }
1343 
1344     // if we have no name yet, find existing item with same content or
1345     // create a unique name
1346     if( aUniqueName.isEmpty() )
1347     {
1348         aUniqueName = CreateNameForValue(rModel.GetItemPool(), pLineStartItem->GetLineStartValue(),
1349                                          bForceNew);
1350     }
1351 
1352     // if the given name is not valid, replace it!
1353     if( aUniqueName != GetName() || pTempItem )
1354     {
1355         if( pTempItem )
1356         {
1357             pTempItem->SetName( aUniqueName );
1358             return pTempItem;
1359         }
1360         else
1361         {
1362             return std::make_unique<XLineStartItem>( aUniqueName, maPolyPolygon );
1363         }
1364     }
1365 
1366     return nullptr;
1367 }
1368 
CreateDefault()1369 SfxPoolItem* XLineEndItem::CreateDefault() {return new XLineEndItem;}
1370 
XLineEndItem(sal_Int32 nIndex)1371 XLineEndItem::XLineEndItem(sal_Int32 nIndex)
1372 :   NameOrIndex(XATTR_LINEEND, nIndex)
1373 {
1374 }
1375 
XLineEndItem(const OUString & rName,basegfx::B2DPolyPolygon aPolyPolygon)1376 XLineEndItem::XLineEndItem(const OUString& rName, basegfx::B2DPolyPolygon aPolyPolygon)
1377 :   NameOrIndex(XATTR_LINEEND, rName),
1378     maPolyPolygon(std::move(aPolyPolygon))
1379 {
1380 }
1381 
XLineEndItem(const XLineEndItem & rItem)1382 XLineEndItem::XLineEndItem(const XLineEndItem& rItem)
1383 :   NameOrIndex(rItem),
1384     maPolyPolygon(rItem.maPolyPolygon)
1385 {
1386 }
1387 
XLineEndItem(basegfx::B2DPolyPolygon aPolyPolygon)1388 XLineEndItem::XLineEndItem(basegfx::B2DPolyPolygon aPolyPolygon)
1389 :   NameOrIndex( XATTR_LINEEND, -1 ),
1390     maPolyPolygon(std::move(aPolyPolygon))
1391 {
1392 }
1393 
Clone(SfxItemPool *) const1394 XLineEndItem* XLineEndItem::Clone(SfxItemPool* /*pPool*/) const
1395 {
1396     return new XLineEndItem(*this);
1397 }
1398 
operator ==(const SfxPoolItem & rItem) const1399 bool XLineEndItem::operator==(const SfxPoolItem& rItem) const
1400 {
1401     return ( NameOrIndex::operator==(rItem) && static_cast<const XLineEndItem&>(rItem).maPolyPolygon == maPolyPolygon );
1402 }
1403 
1404 
1405 /** this function searches in both the models pool and the styles pool for XLineStartItem
1406     and XLineEndItem with the same value or name and returns an item with the value of
1407     this item and a unique name for an item with this value. */
checkForUniqueItem(SdrModel & rModel) const1408 std::unique_ptr<XLineEndItem> XLineEndItem::checkForUniqueItem( SdrModel& rModel ) const
1409 {
1410     std::unique_ptr<XLineEndItem> pTempItem;
1411     const XLineEndItem* pLineEndItem = this;
1412 
1413     OUString aUniqueName( GetName() );
1414 
1415     if( !maPolyPolygon.count() )
1416     {
1417         // if the polygon is empty, check if the name is empty
1418         if( aUniqueName.isEmpty() )
1419             return nullptr;
1420 
1421         // force empty name for empty polygons
1422         return std::make_unique<XLineEndItem>( "", maPolyPolygon );
1423     }
1424 
1425     if( maPolyPolygon.count() > 1 )
1426     {
1427         // check if the polygon is closed
1428         if(!maPolyPolygon.isClosed())
1429         {
1430             // force a closed polygon
1431             basegfx::B2DPolyPolygon aNew(maPolyPolygon);
1432             aNew.setClosed(true);
1433             pTempItem.reset(new XLineEndItem( aUniqueName, std::move(aNew) ));
1434             pLineEndItem = pTempItem.get();
1435         }
1436     }
1437 
1438     bool bForceNew = false;
1439 
1440     // 2. if we have a name check if there is already an item with the
1441     // same name in the documents pool with a different line end or start
1442 
1443     if (!aUniqueName.isEmpty()
1444         && HasConflictingStartEndItems(rModel, pLineEndItem->GetName(),
1445                                        pLineEndItem->GetLineEndValue()))
1446     {
1447         bForceNew = true;
1448         aUniqueName.clear();
1449     }
1450 
1451     // if we have no name yet, find existing item with same content or
1452     // create a unique name
1453     if( aUniqueName.isEmpty() )
1454     {
1455         aUniqueName = CreateNameForValue(rModel.GetItemPool(), pLineEndItem->GetLineEndValue(),
1456                                          bForceNew);
1457     }
1458 
1459     // if the given name is not valid, replace it!
1460     if( aUniqueName != GetName() || pTempItem )
1461     {
1462         if( pTempItem )
1463         {
1464             pTempItem->SetName( aUniqueName );
1465             return pTempItem;
1466         }
1467         else
1468         {
1469             return std::make_unique<XLineEndItem>( aUniqueName, maPolyPolygon );
1470         }
1471     }
1472 
1473     return nullptr;
1474 }
1475 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1476 bool XLineEndItem::GetPresentation
1477 (
1478     SfxItemPresentation /*ePres*/,
1479     MapUnit             /*eCoreUnit*/,
1480     MapUnit             /*ePresUnit*/,
1481     OUString&           rText, const IntlWrapper&
1482 )   const
1483 {
1484     rText = GetName();
1485     return true;
1486 }
1487 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1488 bool XLineEndItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1489 {
1490     nMemberId &= ~CONVERT_TWIPS;
1491     if( nMemberId == MID_NAME )
1492     {
1493         rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
1494     }
1495     else
1496     {
1497         css::drawing::PolyPolygonBezierCoords aBezier;
1498         basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( maPolyPolygon, aBezier );
1499         rVal <<= aBezier;
1500     }
1501     return true;
1502 }
1503 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1504 bool XLineEndItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1505 {
1506     nMemberId &= ~CONVERT_TWIPS;
1507     if( nMemberId == MID_NAME )
1508     {
1509         return false;
1510     }
1511     else
1512     {
1513         maPolyPolygon.clear();
1514 
1515         if( rVal.hasValue() )
1516         {
1517             auto pCoords = o3tl::tryAccess<css::drawing::PolyPolygonBezierCoords>(
1518                 rVal);
1519             if( !pCoords )
1520                 return false;
1521 
1522             if( pCoords->Coordinates.getLength() > 0 )
1523             {
1524                 maPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords );
1525                 // #i72807# close line start/end polygons hard
1526                 // maPolyPolygon.setClosed(true);
1527             }
1528         }
1529     }
1530 
1531     return true;
1532 }
1533 
XLineStartWidthItem(tools::Long nWidth)1534 XLineStartWidthItem::XLineStartWidthItem(tools::Long nWidth) :
1535     SfxMetricItem(XATTR_LINESTARTWIDTH, nWidth)
1536 {
1537 }
1538 
Clone(SfxItemPool *) const1539 XLineStartWidthItem* XLineStartWidthItem::Clone(SfxItemPool* /*pPool*/) const
1540 {
1541     return new XLineStartWidthItem(*this);
1542 }
1543 
GetPresentation(SfxItemPresentation,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntl) const1544 bool XLineStartWidthItem::GetPresentation
1545 (
1546     SfxItemPresentation /*ePres*/,
1547     MapUnit             eCoreUnit,
1548     MapUnit             ePresUnit,
1549     OUString&           rText, const IntlWrapper& rIntl
1550 )   const
1551 {
1552     rText = GetMetricText( static_cast<tools::Long>(GetValue()),
1553                             eCoreUnit, ePresUnit, &rIntl) +
1554             " " + EditResId( GetMetricId( ePresUnit) );
1555     return true;
1556 }
1557 
QueryValue(css::uno::Any & rVal,sal_uInt8) const1558 bool XLineStartWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1559 {
1560     rVal <<= GetValue();
1561     return true;
1562 }
1563 
PutValue(const css::uno::Any & rVal,sal_uInt8)1564 bool XLineStartWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1565 {
1566     sal_Int32 nValue = 0;
1567     rVal >>= nValue;
1568     SetValue( nValue );
1569     return true;
1570 }
1571 
XLineEndWidthItem(tools::Long nWidth)1572 XLineEndWidthItem::XLineEndWidthItem(tools::Long nWidth) :
1573    SfxMetricItem(XATTR_LINEENDWIDTH, nWidth)
1574 {
1575 }
1576 
Clone(SfxItemPool *) const1577 XLineEndWidthItem* XLineEndWidthItem::Clone(SfxItemPool* /*pPool*/) const
1578 {
1579     return new XLineEndWidthItem(*this);
1580 }
1581 
GetPresentation(SfxItemPresentation,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntl) const1582 bool XLineEndWidthItem::GetPresentation
1583 (
1584     SfxItemPresentation /*ePres*/,
1585     MapUnit             eCoreUnit,
1586     MapUnit             ePresUnit,
1587     OUString&           rText, const IntlWrapper& rIntl
1588 )   const
1589 {
1590     rText = GetMetricText( static_cast<tools::Long>(GetValue()),
1591                             eCoreUnit, ePresUnit, &rIntl) +
1592             " " + EditResId( GetMetricId( ePresUnit) );
1593     return true;
1594 }
1595 
QueryValue(css::uno::Any & rVal,sal_uInt8) const1596 bool XLineEndWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1597 {
1598     rVal <<= GetValue();
1599     return true;
1600 }
1601 
PutValue(const css::uno::Any & rVal,sal_uInt8)1602 bool XLineEndWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1603 {
1604     sal_Int32 nValue = 0;
1605     rVal >>= nValue;
1606     SetValue( nValue );
1607     return true;
1608 }
1609 
XLineStartCenterItem(bool bStartCenter)1610 XLineStartCenterItem::XLineStartCenterItem(bool bStartCenter) :
1611     SfxBoolItem(XATTR_LINESTARTCENTER, bStartCenter)
1612 {
1613 }
1614 
Clone(SfxItemPool *) const1615 XLineStartCenterItem* XLineStartCenterItem::Clone(SfxItemPool* /*pPool*/) const
1616 {
1617     return new XLineStartCenterItem(*this);
1618 }
1619 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1620 bool XLineStartCenterItem::GetPresentation
1621 (
1622     SfxItemPresentation /*ePres*/,
1623     MapUnit             /*eCoreUnit*/,
1624     MapUnit             /*ePresUnit*/,
1625     OUString&           rText, const IntlWrapper&
1626 )   const
1627 {
1628     rText = SvxResId(GetValue() ? RID_SVXSTR_CENTERED : RID_SVXSTR_NOTCENTERED);
1629     return true;
1630 }
1631 
QueryValue(css::uno::Any & rVal,sal_uInt8) const1632 bool XLineStartCenterItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1633 {
1634     bool bValue = GetValue();
1635     rVal <<= bValue;
1636     return true;
1637 }
1638 
PutValue(const css::uno::Any & rVal,sal_uInt8)1639 bool XLineStartCenterItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1640 {
1641     auto b = o3tl::tryAccess<bool>(rVal);
1642     if( !b.has_value() )
1643         return false;
1644 
1645     SetValue( *b );
1646     return true;
1647 }
1648 
XLineEndCenterItem(bool bEndCenter)1649 XLineEndCenterItem::XLineEndCenterItem(bool bEndCenter) :
1650     SfxBoolItem(XATTR_LINEENDCENTER, bEndCenter)
1651 {
1652 }
1653 
Clone(SfxItemPool *) const1654 XLineEndCenterItem* XLineEndCenterItem::Clone(SfxItemPool* /*pPool*/) const
1655 {
1656     return new XLineEndCenterItem(*this);
1657 }
1658 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1659 bool XLineEndCenterItem::GetPresentation
1660 (
1661     SfxItemPresentation /*ePres*/,
1662     MapUnit             /*eCoreUnit*/,
1663     MapUnit             /*ePresUnit*/,
1664     OUString&           rText, const IntlWrapper&
1665 )   const
1666 {
1667     rText = SvxResId(GetValue() ? RID_SVXSTR_CENTERED : RID_SVXSTR_NOTCENTERED);
1668     return true;
1669 }
1670 
QueryValue(css::uno::Any & rVal,sal_uInt8) const1671 bool XLineEndCenterItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1672 {
1673     bool bValue = GetValue();
1674     rVal <<= bValue;
1675     return true;
1676 }
1677 
PutValue(const css::uno::Any & rVal,sal_uInt8)1678 bool XLineEndCenterItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1679 {
1680     auto b = o3tl::tryAccess<bool>(rVal);
1681     if( !b.has_value() )
1682         return false;
1683 
1684     SetValue( *b );
1685     return true;
1686 }
1687 
1688 // --- fill attributes ---
1689 
1690 
CreateDefault()1691 SfxPoolItem* XFillStyleItem::CreateDefault() { return new XFillStyleItem; }
1692 
XFillStyleItem(drawing::FillStyle eFillStyle)1693 XFillStyleItem::XFillStyleItem(drawing::FillStyle eFillStyle) :
1694     SfxEnumItem(XATTR_FILLSTYLE, eFillStyle)
1695 {
1696 }
1697 
Clone(SfxItemPool *) const1698 XFillStyleItem* XFillStyleItem::Clone(SfxItemPool* /*pPool*/) const
1699 {
1700     return new XFillStyleItem( *this );
1701 }
1702 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1703 bool XFillStyleItem::GetPresentation
1704 (
1705     SfxItemPresentation /*ePres*/,
1706     MapUnit             /*eCoreUnit*/,
1707     MapUnit             /*ePresUnit*/,
1708     OUString&           rText, const IntlWrapper&
1709 )   const
1710 {
1711     rText.clear();
1712 
1713     TranslateId pId;
1714 
1715     switch( GetValue() )
1716     {
1717         case drawing::FillStyle_NONE:
1718             pId = RID_SVXSTR_INVISIBLE;
1719             break;
1720         case drawing::FillStyle_SOLID:
1721             pId = RID_SVXSTR_SOLID;
1722             break;
1723         case drawing::FillStyle_GRADIENT:
1724             pId = RID_SVXSTR_GRADIENT;
1725             break;
1726         case drawing::FillStyle_HATCH:
1727             pId = RID_SVXSTR_HATCH;
1728             break;
1729         case drawing::FillStyle_BITMAP:
1730             pId = RID_SVXSTR_BITMAP;
1731             break;
1732         default: break;
1733     }
1734 
1735     if (pId)
1736         rText = SvxResId(pId);
1737     return true;
1738 }
1739 
QueryValue(css::uno::Any & rVal,sal_uInt8) const1740 bool XFillStyleItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1741 {
1742     css::drawing::FillStyle eFS = GetValue();
1743 
1744     rVal <<= eFS;
1745 
1746     return true;
1747 }
1748 
PutValue(const css::uno::Any & rVal,sal_uInt8)1749 bool XFillStyleItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1750 {
1751     css::drawing::FillStyle eFS;
1752     if(!(rVal >>= eFS))
1753     {
1754         // also try an int (for Basic)
1755         sal_Int32 nFS = 0;
1756         if(!(rVal >>= nFS))
1757             return false;
1758         eFS = static_cast<css::drawing::FillStyle>(nFS);
1759     }
1760 
1761     SetValue( eFS );
1762 
1763     return true;
1764 }
1765 
dumpAsXml(xmlTextWriterPtr pWriter) const1766 void XFillStyleItem::dumpAsXml(xmlTextWriterPtr pWriter) const
1767 {
1768     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XFillStyleItem"));
1769     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
1770     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(static_cast<sal_Int16>(GetValue())).getStr()));
1771 
1772     OUString aPresentation;
1773     IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
1774     GetPresentation(SfxItemPresentation::Nameless, MapUnit::Map100thMM, MapUnit::Map100thMM, aPresentation, aIntlWrapper);
1775     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"), BAD_CAST(aPresentation.toUtf8().getStr()));
1776 
1777     (void)xmlTextWriterEndElement(pWriter);
1778 }
1779 
dumpAsJSON() const1780 boost::property_tree::ptree XFillStyleItem::dumpAsJSON() const
1781 {
1782     boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
1783 
1784     if (Which() == XATTR_FILLSTYLE)
1785         aTree.put("commandName", ".uno:FillStyle");
1786 
1787     OUString sValue;
1788 
1789     switch( GetValue() )
1790     {
1791         case drawing::FillStyle_NONE:
1792             sValue = "NONE";
1793             break;
1794         case drawing::FillStyle_SOLID:
1795             sValue = "SOLID";
1796             break;
1797         case drawing::FillStyle_GRADIENT:
1798             sValue = "GRADIENT";
1799             break;
1800         case drawing::FillStyle_HATCH:
1801             sValue = "HATCH";
1802             break;
1803         case drawing::FillStyle_BITMAP:
1804             sValue = "BITMAP";
1805             break;
1806         default: break;
1807     }
1808 
1809     aTree.put("state", sValue);
1810 
1811     return aTree;
1812 }
1813 
1814 
CreateDefault()1815 SfxPoolItem* XFillColorItem::CreateDefault() { return new XFillColorItem; }
1816 
XFillColorItem(sal_Int32 nIndex,const Color & rTheColor)1817 XFillColorItem::XFillColorItem(sal_Int32 nIndex, const Color& rTheColor) :
1818     XColorItem(XATTR_FILLCOLOR, nIndex, rTheColor)
1819 {
1820 }
1821 
XFillColorItem(const OUString & rName,const Color & rTheColor)1822 XFillColorItem::XFillColorItem(const OUString& rName, const Color& rTheColor) :
1823     XColorItem(XATTR_FILLCOLOR, rName, rTheColor)
1824 {
1825 }
1826 
Clone(SfxItemPool *) const1827 XFillColorItem* XFillColorItem::Clone(SfxItemPool* /*pPool*/) const
1828 {
1829     return new XFillColorItem(*this);
1830 }
1831 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1832 bool XFillColorItem::GetPresentation
1833 (
1834     SfxItemPresentation /*ePres*/,
1835     MapUnit             /*eCoreUnit*/,
1836     MapUnit             /*ePresUnit*/,
1837     OUString&           rText, const IntlWrapper&
1838 )   const
1839 {
1840     rText = GetName();
1841     return true;
1842 }
1843 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1844 bool XFillColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1845 {
1846     nMemberId &= ~CONVERT_TWIPS;
1847     switch (nMemberId)
1848     {
1849         case MID_COLOR_THEME_INDEX:
1850         {
1851             rVal <<= sal_Int16(getComplexColor().getThemeColorType());
1852             break;
1853         }
1854         case MID_COLOR_LUM_MOD:
1855         {
1856             sal_Int16 nValue = 10000;
1857             for (auto const& rTransform : getComplexColor().getTransformations())
1858             {
1859                 if (rTransform.meType == model::TransformationType::LumMod)
1860                     nValue = rTransform.mnValue;
1861             }
1862             rVal <<= nValue;
1863             break;
1864         }
1865         case MID_COLOR_LUM_OFF:
1866         {
1867             sal_Int16 nValue = 0;
1868             for (auto const& rTransform : getComplexColor().getTransformations())
1869             {
1870                 if (rTransform.meType == model::TransformationType::LumOff)
1871                     nValue = rTransform.mnValue;
1872             }
1873             rVal <<= nValue;
1874             break;
1875         }
1876         case MID_COMPLEX_COLOR:
1877         {
1878             auto xComplexColor = model::color::createXComplexColor(getComplexColor());
1879             rVal <<= xComplexColor;
1880             break;
1881         }
1882         case MID_COMPLEX_COLOR_JSON:
1883         {
1884             rVal <<= OStringToOUString(model::color::convertToJSON(getComplexColor()), RTL_TEXTENCODING_UTF8);
1885             break;
1886         }
1887         default:
1888         {
1889             rVal <<= GetColorValue().GetRGBColor();
1890             break;
1891         }
1892     }
1893 
1894     return true;
1895 }
1896 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1897 bool XFillColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1898 {
1899     nMemberId &= ~CONVERT_TWIPS;
1900     switch(nMemberId)
1901     {
1902         case MID_COLOR_THEME_INDEX:
1903         {
1904             sal_Int16 nIndex = -1;
1905             if (!(rVal >>= nIndex))
1906                 return false;
1907             getComplexColor().setThemeColor(model::convertToThemeColorType(nIndex));
1908         }
1909         break;
1910         case MID_COLOR_LUM_MOD:
1911         {
1912             sal_Int16 nLumMod = 10000;
1913             if (!(rVal >>= nLumMod))
1914                 return false;
1915             getComplexColor().removeTransformations(model::TransformationType::LumMod);
1916             getComplexColor().addTransformation({model::TransformationType::LumMod, nLumMod});
1917         }
1918         break;
1919         case MID_COLOR_LUM_OFF:
1920         {
1921             sal_Int16 nLumOff = 0;
1922             if (!(rVal >>= nLumOff))
1923                 return false;
1924             getComplexColor().removeTransformations(model::TransformationType::LumOff);
1925             getComplexColor().addTransformation({model::TransformationType::LumOff, nLumOff});
1926         }
1927         break;
1928         case MID_COMPLEX_COLOR:
1929         {
1930             css::uno::Reference<css::util::XComplexColor> xComplexColor;
1931             if (!(rVal >>= xComplexColor))
1932                 return false;
1933             setComplexColor(model::color::getFromXComplexColor(xComplexColor));
1934         }
1935         break;
1936         case MID_COMPLEX_COLOR_JSON:
1937         {
1938             OUString sComplexColorJson;
1939             if (!(rVal >>= sComplexColorJson))
1940                 return false;
1941 
1942             if (sComplexColorJson.isEmpty())
1943                 return false;
1944 
1945             OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
1946             model::ComplexColor aComplexColor;
1947             model::color::convertFromJSON(aJSON, aComplexColor);
1948             setComplexColor(aComplexColor);
1949         }
1950         break;
1951         default:
1952         {
1953             Color nValue;
1954             if(!(rVal >>= nValue ))
1955                 return false;
1956 
1957             SetColorValue( nValue );
1958 
1959         }
1960         break;
1961     }
1962     return true;
1963 }
1964 
dumpAsXml(xmlTextWriterPtr pWriter) const1965 void XFillColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const
1966 {
1967     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XFillColorItem"));
1968     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
1969 
1970     XColorItem::dumpAsXml(pWriter);
1971 
1972     (void)xmlTextWriterEndElement(pWriter);
1973 }
1974 
dumpAsJSON() const1975 boost::property_tree::ptree XFillColorItem::dumpAsJSON() const
1976 {
1977     boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
1978 
1979     if (Which() == XATTR_FILLCOLOR)
1980         aTree.put("commandName", ".uno:FillPageColor");
1981 
1982     aTree.put("state", GetColorValue().AsRGBHexString());
1983 
1984     return aTree;
1985 }
1986 
XSecondaryFillColorItem(const OUString & rName,const Color & rTheColor)1987 XSecondaryFillColorItem::XSecondaryFillColorItem(const OUString& rName, const Color& rTheColor) :
1988     XColorItem(XATTR_SECONDARYFILLCOLOR, rName, rTheColor)
1989 {
1990 }
1991 
Clone(SfxItemPool *) const1992 XSecondaryFillColorItem* XSecondaryFillColorItem::Clone(SfxItemPool* /*pPool*/) const
1993 {
1994     return new XSecondaryFillColorItem(*this);
1995 }
1996 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1997 bool XSecondaryFillColorItem::GetPresentation
1998 (
1999     SfxItemPresentation /*ePres*/,
2000     MapUnit             /*eCoreUnit*/,
2001     MapUnit             /*ePresUnit*/,
2002     OUString&           rText, const IntlWrapper&
2003 )   const
2004 {
2005     rText = GetName();
2006     return true;
2007 }
2008 
CreateDefault()2009 SfxPoolItem* XFillGradientItem::CreateDefault() { return new XFillGradientItem; }
2010 
XFillGradientItem(sal_Int32 nIndex,const basegfx::BGradient & rTheGradient,TypedWhichId<XFillGradientItem> nWhich)2011 XFillGradientItem::XFillGradientItem(sal_Int32 nIndex,
2012                                    const basegfx::BGradient& rTheGradient,
2013                                    TypedWhichId<XFillGradientItem> nWhich) :
2014     NameOrIndex(nWhich, nIndex),
2015     m_aGradient(rTheGradient)
2016 {
2017 }
2018 
XFillGradientItem(const OUString & rName,const basegfx::BGradient & rTheGradient,TypedWhichId<XFillGradientItem> nWhich)2019 XFillGradientItem::XFillGradientItem(const OUString& rName,
2020                                    const basegfx::BGradient& rTheGradient,
2021                                    TypedWhichId<XFillGradientItem> nWhich)
2022     : NameOrIndex(nWhich, rName)
2023     , m_aGradient(rTheGradient)
2024 {
2025 }
2026 
XFillGradientItem(const XFillGradientItem & rItem)2027 XFillGradientItem::XFillGradientItem(const XFillGradientItem& rItem) :
2028     NameOrIndex(rItem),
2029     m_aGradient(rItem.m_aGradient)
2030 {
2031 }
2032 
XFillGradientItem(const basegfx::BGradient & rTheGradient,TypedWhichId<XFillGradientItem> nWhich)2033 XFillGradientItem::XFillGradientItem( const basegfx::BGradient& rTheGradient,
2034                                     TypedWhichId<XFillGradientItem> nWhich)
2035 :   NameOrIndex( nWhich, -1 ),
2036     m_aGradient(rTheGradient)
2037 {
2038 }
2039 
Clone(SfxItemPool *) const2040 XFillGradientItem* XFillGradientItem::Clone(SfxItemPool* /*pPool*/) const
2041 {
2042     return new XFillGradientItem(*this);
2043 }
2044 
operator ==(const SfxPoolItem & rItem) const2045 bool XFillGradientItem::operator==(const SfxPoolItem& rItem) const
2046 {
2047     return ( NameOrIndex::operator==(rItem) &&
2048              m_aGradient == static_cast<const XFillGradientItem&>(rItem).m_aGradient );
2049 }
2050 
GetGradientValue() const2051 const basegfx::BGradient& XFillGradientItem::GetGradientValue() const // GetValue -> GetGradientValue
2052 {
2053     if (!IsIndex())
2054         return m_aGradient;
2055     // ToDo: This should fail. We never called this code with a table so this should always
2056     // have failed. Thus, I'm thinking that XFillGradientItem can't be an Index.
2057     return m_aGradient;
2058 }
2059 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const2060 bool XFillGradientItem::GetPresentation
2061 (
2062     SfxItemPresentation /*ePres*/,
2063     MapUnit             /*eCoreUnit*/,
2064     MapUnit             /*ePresUnit*/,
2065     OUString&           rText, const IntlWrapper&
2066 )   const
2067 {
2068     rText = GetName();
2069     return true;
2070 }
2071 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const2072 bool XFillGradientItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
2073 {
2074     nMemberId &= ~CONVERT_TWIPS;
2075     switch ( nMemberId )
2076     {
2077         case 0:
2078         {
2079             // fill values
2080             const css::awt::Gradient2 aGradient2 = model::gradient::createUnoGradient2(GetGradientValue());
2081 
2082             // create sequence
2083             uno::Sequence< beans::PropertyValue > aPropSeq{
2084                 comphelper::makePropertyValue(u"Name"_ustr, SvxUnogetApiNameForItem(Which(), GetName())),
2085                 comphelper::makePropertyValue(u"FillGradient"_ustr, aGradient2)
2086             };
2087             rVal <<= aPropSeq;
2088             break;
2089         }
2090 
2091         case MID_FILLGRADIENT:
2092         {
2093             // fill values
2094             const css::awt::Gradient2 aGradient2 = model::gradient::createUnoGradient2(GetGradientValue());
2095 
2096             // create sequence
2097             rVal <<= aGradient2;
2098             break;
2099         }
2100 
2101         case MID_NAME:
2102         {
2103             rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
2104             break;
2105         }
2106 
2107         case MID_GRADIENT_COLORSTOPSEQUENCE:
2108         {
2109             // fill values
2110             const css::awt::ColorStopSequence aColorStopSequence = model::gradient::createColorStopSequence(GetGradientValue().GetColorStops());
2111 
2112             // create sequence
2113             rVal <<= aColorStopSequence;
2114             break;
2115         }
2116 
2117         case MID_GRADIENT_STYLE: rVal <<= static_cast<sal_Int16>(GetGradientValue().GetGradientStyle()); break;
2118         case MID_GRADIENT_STARTCOLOR: rVal <<= Color(GetGradientValue().GetColorStops().front().getStopColor()); break;
2119         case MID_GRADIENT_ENDCOLOR: rVal <<= Color(GetGradientValue().GetColorStops().back().getStopColor()); break;
2120         case MID_GRADIENT_ANGLE: rVal <<= static_cast<sal_Int16>(GetGradientValue().GetAngle()); break;
2121         case MID_GRADIENT_BORDER: rVal <<= GetGradientValue().GetBorder(); break;
2122         case MID_GRADIENT_XOFFSET: rVal <<= GetGradientValue().GetXOffset(); break;
2123         case MID_GRADIENT_YOFFSET: rVal <<= GetGradientValue().GetYOffset(); break;
2124         case MID_GRADIENT_STARTINTENSITY: rVal <<= GetGradientValue().GetStartIntens(); break;
2125         case MID_GRADIENT_ENDINTENSITY: rVal <<= GetGradientValue().GetEndIntens(); break;
2126         case MID_GRADIENT_STEPCOUNT: rVal <<= GetGradientValue().GetSteps(); break;
2127 
2128         default: OSL_FAIL("Wrong MemberId!"); return false;
2129     }
2130 
2131     return true;
2132 }
2133 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)2134 bool XFillGradientItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
2135 {
2136     nMemberId &= ~CONVERT_TWIPS;
2137 
2138     switch ( nMemberId )
2139     {
2140         case 0:
2141         {
2142             uno::Sequence< beans::PropertyValue >   aPropSeq;
2143             css::uno::Any aGradientAny;
2144 
2145             if ( rVal >>= aPropSeq )
2146             {
2147                 OUString aName;
2148 
2149                 for (const auto& rProp : aPropSeq)
2150                 {
2151                     if ( rProp.Name == "Name" )
2152                         rProp.Value >>= aName;
2153                     else if ( rProp.Name == "FillGradient" )
2154                         aGradientAny = rProp.Value;
2155                 }
2156 
2157                 SetName( aName );
2158 
2159                 if (aGradientAny.hasValue() && (aGradientAny.has<css::awt::Gradient>() || aGradientAny.has<css::awt::Gradient2>()))
2160                 {
2161                     SetGradientValue(model::gradient::getFromAny(aGradientAny));
2162                 }
2163 
2164                 return true;
2165             }
2166 
2167             return false;
2168         }
2169 
2170         case MID_NAME:
2171         {
2172             OUString aName;
2173             if (!(rVal >>= aName ))
2174                 return false;
2175             SetName( aName );
2176             break;
2177         }
2178 
2179         case MID_FILLGRADIENT:
2180         {
2181             if (rVal.hasValue() && (rVal.has<css::awt::Gradient>() || rVal.has<css::awt::Gradient2>()))
2182             {
2183                 SetGradientValue(model::gradient::getFromAny(rVal));
2184             }
2185 
2186             break;
2187         }
2188 
2189         case MID_GRADIENT_COLORSTOPSEQUENCE:
2190         {
2191             // check if we have a awt::ColorStopSequence
2192             if (rVal.hasValue() && rVal.has<css::awt::ColorStopSequence>())
2193             {
2194 
2195                 const basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromAny(rVal);
2196 
2197                 if (!aColorStops.empty())
2198                 {
2199                     basegfx::BGradient aBGradient(GetGradientValue());
2200                     aBGradient.SetColorStops(aColorStops);
2201                     SetGradientValue(aBGradient);
2202                 }
2203             }
2204             break;
2205         }
2206 
2207         case MID_GRADIENT_STARTCOLOR:
2208         case MID_GRADIENT_ENDCOLOR:
2209         {
2210             Color nVal;
2211             if(!(rVal >>= nVal ))
2212                 return false;
2213 
2214             basegfx::BGradient aBGradient(GetGradientValue());
2215             basegfx::BColorStops aNewColorStops(aBGradient.GetColorStops());
2216 
2217             if ( nMemberId == MID_GRADIENT_STARTCOLOR )
2218             {
2219                 aNewColorStops.replaceStartColor(nVal.getBColor());
2220             }
2221             else
2222             {
2223                 aNewColorStops.replaceEndColor(nVal.getBColor());
2224             }
2225 
2226             aBGradient.SetColorStops(aNewColorStops);
2227             SetGradientValue( aBGradient );
2228             break;
2229         }
2230 
2231         case MID_GRADIENT_STYLE:
2232         case MID_GRADIENT_ANGLE:
2233         case MID_GRADIENT_BORDER:
2234         case MID_GRADIENT_STARTINTENSITY:
2235         case MID_GRADIENT_ENDINTENSITY:
2236         case MID_GRADIENT_STEPCOUNT:
2237         case MID_GRADIENT_XOFFSET:
2238         case MID_GRADIENT_YOFFSET:
2239         {
2240             sal_Int16 nVal = sal_Int16();
2241             if(!(rVal >>= nVal ))
2242                 return false;
2243 
2244             basegfx::BGradient aBGradient = GetGradientValue();
2245 
2246             switch ( nMemberId )
2247             {
2248                 case MID_GRADIENT_STYLE:
2249                     aBGradient.SetGradientStyle( static_cast<css::awt::GradientStyle>(nVal) ); break;
2250                 case MID_GRADIENT_ANGLE:
2251                     aBGradient.SetAngle( Degree10(nVal) ); break;
2252                 case MID_GRADIENT_BORDER:
2253                     aBGradient.SetBorder( nVal ); break;
2254                 case MID_GRADIENT_STARTINTENSITY:
2255                     aBGradient.SetStartIntens( nVal ); break;
2256                 case MID_GRADIENT_ENDINTENSITY:
2257                     aBGradient.SetEndIntens( nVal ); break;
2258                 case MID_GRADIENT_STEPCOUNT:
2259                     aBGradient.SetSteps( nVal ); break;
2260                 case MID_GRADIENT_XOFFSET:
2261                     aBGradient.SetXOffset( nVal ); break;
2262                 case MID_GRADIENT_YOFFSET:
2263                     aBGradient.SetYOffset( nVal ); break;
2264             }
2265 
2266             SetGradientValue( aBGradient );
2267             break;
2268         }
2269     }
2270 
2271     return true;
2272 }
2273 
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)2274 bool XFillGradientItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
2275 {
2276     return static_cast<const XFillGradientItem*>(p1)->GetGradientValue() == static_cast<const XFillGradientItem*>(p2)->GetGradientValue();
2277 }
2278 
checkForUniqueItem(SdrModel & rModel) const2279 std::unique_ptr<XFillGradientItem> XFillGradientItem::checkForUniqueItem( SdrModel& rModel ) const
2280 {
2281     const OUString aUniqueName(CheckNamedItem(
2282         Which(), &rModel.GetItemPool(),
2283         XFillGradientItem::CompareValueFunc, RID_SVXSTR_GRADIENT,
2284         rModel.GetPropertyList(XPropertyListType::Gradient)));
2285 
2286     // if the given name is not valid, replace it!
2287     if( aUniqueName != GetName() )
2288         return std::make_unique<XFillGradientItem>( aUniqueName, m_aGradient, TypedWhichId<XFillGradientItem>(Which()) );
2289 
2290     return nullptr;
2291 }
2292 
dumpAsJSON() const2293 boost::property_tree::ptree XFillGradientItem::dumpAsJSON() const
2294 {
2295     boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
2296 
2297     if (Which() == XATTR_FILLGRADIENT)
2298         aTree.put("commandName", ".uno:FillGradient");
2299 
2300     aTree.push_back(std::make_pair("state", GetGradientValue().dumpAsJSON()));
2301 
2302     return aTree;
2303 }
2304 
2305 
CreateDefault()2306 SfxPoolItem* XFillFloatTransparenceItem::CreateDefault() { return new XFillFloatTransparenceItem; }
2307 
XFillFloatTransparenceItem()2308 XFillFloatTransparenceItem::XFillFloatTransparenceItem() :
2309     XFillGradientItem(XATTR_FILLFLOATTRANSPARENCE),
2310     m_bEnabled( false )
2311 {
2312 }
2313 
XFillFloatTransparenceItem(const OUString & rName,const basegfx::BGradient & rGradient,bool bEnable)2314 XFillFloatTransparenceItem::XFillFloatTransparenceItem(const OUString& rName, const basegfx::BGradient& rGradient, bool bEnable ) :
2315     XFillGradientItem   ( rName, rGradient, XATTR_FILLFLOATTRANSPARENCE ),
2316     m_bEnabled            ( bEnable )
2317 {
2318 }
2319 
XFillFloatTransparenceItem(const XFillFloatTransparenceItem & rItem)2320 XFillFloatTransparenceItem::XFillFloatTransparenceItem( const XFillFloatTransparenceItem& rItem ) :
2321     XFillGradientItem   ( rItem ),
2322     m_bEnabled            ( rItem.m_bEnabled )
2323 {
2324 }
2325 
XFillFloatTransparenceItem(const basegfx::BGradient & rTheGradient,bool bEnable)2326 XFillFloatTransparenceItem::XFillFloatTransparenceItem(const basegfx::BGradient& rTheGradient, bool bEnable )
2327 :   XFillGradientItem   ( -1, rTheGradient, XATTR_FILLFLOATTRANSPARENCE ),
2328     m_bEnabled            ( bEnable )
2329 {
2330 }
2331 
operator ==(const SfxPoolItem & rItem) const2332 bool XFillFloatTransparenceItem::operator==( const SfxPoolItem& rItem ) const
2333 {
2334     return ( XFillGradientItem::operator==(rItem) ) &&
2335            ( m_bEnabled == static_cast<const XFillFloatTransparenceItem&>(rItem).m_bEnabled );
2336 }
2337 
Clone(SfxItemPool *) const2338 XFillFloatTransparenceItem* XFillFloatTransparenceItem::Clone( SfxItemPool* /*pPool*/) const
2339 {
2340     return new XFillFloatTransparenceItem( *this );
2341 }
2342 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const2343 bool XFillFloatTransparenceItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
2344 {
2345     if (MID_GRADIENT_STARTINTENSITY == nMemberId
2346         || MID_GRADIENT_ENDINTENSITY == nMemberId
2347         || MID_GRADIENT_STEPCOUNT == nMemberId)
2348     {
2349         // tdf#155913 handle attributes not supported by transparency gradient as error
2350         return false;
2351     }
2352 
2353     if (!IsEnabled() && nMemberId == MID_NAME)
2354     {
2355         // make sure that we return empty string in case of query for
2356         // "FillTransparenceGradientName" if the item is disabled
2357         rVal <<= OUString();
2358         return true;
2359     }
2360 
2361     return XFillGradientItem::QueryValue( rVal, nMemberId );
2362 }
2363 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)2364 bool XFillFloatTransparenceItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
2365 {
2366     if (MID_GRADIENT_STARTINTENSITY == nMemberId
2367         || MID_GRADIENT_ENDINTENSITY == nMemberId
2368         || MID_GRADIENT_STEPCOUNT == nMemberId)
2369     {
2370         // tdf#155913 handle attributes not supported by transparency gradient as error
2371         return false;
2372     }
2373 
2374     return XFillGradientItem::PutValue( rVal, nMemberId );
2375 }
2376 
GetPresentation(SfxItemPresentation ePres,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntlWrapper) const2377 bool XFillFloatTransparenceItem::GetPresentation(    SfxItemPresentation ePres,
2378                                                                     MapUnit eCoreUnit, MapUnit ePresUnit,
2379                                                                     OUString& rText,
2380                                                                     const IntlWrapper& rIntlWrapper ) const
2381 {
2382     return XFillGradientItem::GetPresentation( ePres, eCoreUnit, ePresUnit, rText, rIntlWrapper );
2383 }
2384 
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)2385 bool XFillFloatTransparenceItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
2386 {
2387     return  static_cast<const XFillFloatTransparenceItem*>(p1)->IsEnabled() == static_cast<const XFillFloatTransparenceItem*>(p2)->IsEnabled() &&
2388             static_cast<const XFillFloatTransparenceItem*>(p1)->GetGradientValue()  == static_cast<const XFillFloatTransparenceItem*>(p2)->GetGradientValue();
2389 }
2390 
checkForUniqueItem(SdrModel & rModel) const2391 std::unique_ptr<XFillFloatTransparenceItem> XFillFloatTransparenceItem::checkForUniqueItem( SdrModel& rModel ) const
2392 {
2393     // #85953# unique name only necessary when enabled
2394     if(IsEnabled())
2395     {
2396         const OUString aUniqueName(CheckNamedItem(
2397             XATTR_FILLFLOATTRANSPARENCE,
2398             &rModel.GetItemPool(),
2399             XFillFloatTransparenceItem::CompareValueFunc,
2400             RID_SVXSTR_TRASNGR0,
2401             XPropertyListRef()));
2402 
2403         // if the given name is not valid, replace it!
2404         if( aUniqueName != GetName() )
2405         {
2406             return std::make_unique<XFillFloatTransparenceItem>( aUniqueName, GetGradientValue(), true );
2407         }
2408     }
2409     else
2410     {
2411         // #85953# if disabled, force name to empty string
2412         if( !GetName().isEmpty() )
2413         {
2414             return std::make_unique<XFillFloatTransparenceItem>(OUString(), GetGradientValue(), false);
2415         }
2416     }
2417 
2418     return nullptr;
2419 }
2420 
dumpAsJSON() const2421 boost::property_tree::ptree XFillFloatTransparenceItem::dumpAsJSON() const
2422 {
2423     boost::property_tree::ptree aTree = XFillGradientItem::dumpAsJSON();
2424     aTree.put("commandName", ".uno:FillFloatTransparence");
2425 
2426     if (!m_bEnabled)
2427     {
2428         boost::property_tree::ptree& rState = aTree.get_child("state");
2429         // When gradient fill is disabled, the intensity fields contain the
2430         // constant encoded percent-transparency. However we use that here to just
2431         // distinguish between 'None' and 'Solid' types and correct the 'style'
2432         // property appropriately.
2433         if (GetGradientValue().GetStartIntens() == 100)
2434             rState.put("style", "NONE");
2435         else
2436             rState.put("style", "SOLID");
2437     }
2438 
2439     return aTree;
2440 }
2441 
XHatch(const Color & rCol,css::drawing::HatchStyle eTheStyle,tools::Long nTheDistance,Degree10 nTheAngle)2442 XHatch::XHatch(const Color& rCol, css::drawing::HatchStyle eTheStyle, tools::Long nTheDistance,
2443                Degree10 nTheAngle) :
2444     m_eStyle(eTheStyle),
2445     m_aColor(rCol),
2446     m_nDistance(nTheDistance),
2447     m_nAngle(nTheAngle)
2448 {
2449 }
2450 
operator ==(const XHatch & rHatch) const2451 bool XHatch::operator==(const XHatch& rHatch) const
2452 {
2453     return ( m_eStyle     == rHatch.m_eStyle    &&
2454              m_aColor     == rHatch.m_aColor    &&
2455              m_nDistance  == rHatch.m_nDistance &&
2456              m_nAngle     == rHatch.m_nAngle );
2457 }
2458 
2459 
CreateDefault()2460 SfxPoolItem* XFillHatchItem::CreateDefault() { return new XFillHatchItem; }
2461 
XFillHatchItem(const OUString & rName,const XHatch & rTheHatch)2462 XFillHatchItem::XFillHatchItem(const OUString& rName,
2463                              const XHatch& rTheHatch) :
2464     NameOrIndex(XATTR_FILLHATCH, rName),
2465     m_aHatch(rTheHatch)
2466 {
2467 }
2468 
XFillHatchItem(const XFillHatchItem & rItem)2469 XFillHatchItem::XFillHatchItem(const XFillHatchItem& rItem) :
2470     NameOrIndex(rItem),
2471     m_aHatch(rItem.m_aHatch)
2472 {
2473 }
2474 
XFillHatchItem(const XHatch & rTheHatch)2475 XFillHatchItem::XFillHatchItem(const XHatch& rTheHatch)
2476 :   NameOrIndex( XATTR_FILLHATCH, -1 ),
2477     m_aHatch(rTheHatch)
2478 {
2479 }
2480 
Clone(SfxItemPool *) const2481 XFillHatchItem* XFillHatchItem::Clone(SfxItemPool* /*pPool*/) const
2482 {
2483     return new XFillHatchItem(*this);
2484 }
2485 
operator ==(const SfxPoolItem & rItem) const2486 bool XFillHatchItem::operator==(const SfxPoolItem& rItem) const
2487 {
2488     return ( NameOrIndex::operator==(rItem) &&
2489              m_aHatch == static_cast<const XFillHatchItem&>(rItem).m_aHatch );
2490 }
2491 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const2492 bool XFillHatchItem::GetPresentation
2493 (
2494     SfxItemPresentation /*ePres*/,
2495     MapUnit             /*eCoreUnit*/,
2496     MapUnit             /*ePresUnit*/,
2497     OUString&           rText, const IntlWrapper&
2498 )   const
2499 {
2500     rText = GetName();
2501     return true;
2502 }
2503 
HasMetrics() const2504 bool XFillHatchItem::HasMetrics() const
2505 {
2506     return true;
2507 }
2508 
ScaleMetrics(tools::Long nMul,tools::Long nDiv)2509 void XFillHatchItem::ScaleMetrics(tools::Long nMul, tools::Long nDiv)
2510 {
2511     m_aHatch.SetDistance( BigInt::Scale( m_aHatch.GetDistance(), nMul, nDiv ) );
2512 }
2513 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const2514 bool XFillHatchItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
2515 {
2516     nMemberId &= ~CONVERT_TWIPS;
2517 
2518     switch ( nMemberId )
2519     {
2520         case 0:
2521         {
2522             css::drawing::Hatch aUnoHatch;
2523 
2524             aUnoHatch.Style = m_aHatch.GetHatchStyle();
2525             aUnoHatch.Color = sal_Int32(m_aHatch.GetColor());
2526             aUnoHatch.Distance = m_aHatch.GetDistance();
2527             aUnoHatch.Angle = m_aHatch.GetAngle().get();
2528 
2529             uno::Sequence< beans::PropertyValue > aPropSeq{
2530                 comphelper::makePropertyValue(u"Name"_ustr, SvxUnogetApiNameForItem(Which(), GetName())),
2531                 comphelper::makePropertyValue(u"FillHatch"_ustr, aUnoHatch)
2532             };
2533             rVal <<= aPropSeq;
2534             break;
2535         }
2536 
2537         case MID_FILLHATCH:
2538         {
2539             css::drawing::Hatch aUnoHatch;
2540 
2541             aUnoHatch.Style = m_aHatch.GetHatchStyle();
2542             aUnoHatch.Color = sal_Int32(m_aHatch.GetColor());
2543             aUnoHatch.Distance = m_aHatch.GetDistance();
2544             aUnoHatch.Angle = m_aHatch.GetAngle().get();
2545             rVal <<= aUnoHatch;
2546             break;
2547         }
2548 
2549         case MID_NAME:
2550         {
2551             rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
2552             break;
2553         }
2554 
2555         case MID_HATCH_STYLE:
2556             rVal <<= m_aHatch.GetHatchStyle(); break;
2557         case MID_HATCH_COLOR:
2558             rVal <<= m_aHatch.GetColor(); break;
2559         case MID_HATCH_DISTANCE:
2560             rVal <<= m_aHatch.GetDistance(); break;
2561         case MID_HATCH_ANGLE:
2562             rVal <<= m_aHatch.GetAngle().get(); break;
2563 
2564         default: OSL_FAIL("Wrong MemberId!"); return false;
2565     }
2566 
2567     return true;
2568 }
2569 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)2570 bool XFillHatchItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
2571 {
2572     nMemberId &= ~CONVERT_TWIPS;
2573 
2574     switch ( nMemberId )
2575     {
2576         case 0:
2577         {
2578             uno::Sequence< beans::PropertyValue >   aPropSeq;
2579             if ( rVal >>= aPropSeq )
2580             {
2581                 css::drawing::Hatch aUnoHatch;
2582                 OUString aName;
2583                 bool bHatch( false );
2584                 for (const auto& rProp : aPropSeq)
2585                 {
2586                     if ( rProp.Name == "Name" )
2587                         rProp.Value >>= aName;
2588                     else if ( rProp.Name == "FillHatch" )
2589                     {
2590                         if ( rProp.Value >>= aUnoHatch )
2591                             bHatch = true;
2592                     }
2593                 }
2594 
2595                 SetName( aName );
2596                 if ( bHatch )
2597                 {
2598                     m_aHatch.SetHatchStyle( aUnoHatch.Style );
2599                     m_aHatch.SetColor( Color(ColorTransparency, aUnoHatch.Color) );
2600                     m_aHatch.SetDistance( aUnoHatch.Distance );
2601                     m_aHatch.SetAngle( Degree10(aUnoHatch.Angle) );
2602                 }
2603 
2604                 return true;
2605             }
2606 
2607             return false;
2608         }
2609 
2610         case MID_FILLHATCH:
2611         {
2612             css::drawing::Hatch aUnoHatch;
2613             if(!(rVal >>= aUnoHatch))
2614                 return false;
2615 
2616             m_aHatch.SetHatchStyle( aUnoHatch.Style );
2617             m_aHatch.SetColor( Color(ColorTransparency, aUnoHatch.Color) );
2618             m_aHatch.SetDistance( aUnoHatch.Distance );
2619             m_aHatch.SetAngle( Degree10(aUnoHatch.Angle) );
2620             break;
2621         }
2622 
2623         case MID_NAME:
2624         {
2625             OUString aName;
2626             if (!(rVal >>= aName ))
2627                 return false;
2628             SetName( aName );
2629             break;
2630         }
2631 
2632         case MID_HATCH_STYLE:
2633         {
2634             sal_Int16 nVal = sal_Int16();
2635             if (!(rVal >>= nVal ))
2636                 return false;
2637             m_aHatch.SetHatchStyle( static_cast<css::drawing::HatchStyle>(nVal) );
2638             break;
2639         }
2640 
2641         case MID_HATCH_COLOR:
2642         case MID_HATCH_DISTANCE:
2643         case MID_HATCH_ANGLE:
2644         {
2645             sal_Int32 nVal = 0;
2646             if (!(rVal >>= nVal ))
2647                 return false;
2648 
2649             if ( nMemberId == MID_HATCH_COLOR )
2650                 m_aHatch.SetColor( Color(ColorTransparency, nVal) );
2651             else if ( nMemberId == MID_HATCH_DISTANCE )
2652                 m_aHatch.SetDistance( nVal );
2653             else
2654                 m_aHatch.SetAngle( Degree10(nVal) );
2655             break;
2656         }
2657 
2658         default: OSL_FAIL("Wrong MemberId!"); return false;
2659     }
2660 
2661     return true;
2662 }
2663 
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)2664 bool XFillHatchItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
2665 {
2666     return static_cast<const XFillHatchItem*>(p1)->GetHatchValue() == static_cast<const XFillHatchItem*>(p2)->GetHatchValue();
2667 }
2668 
checkForUniqueItem(SdrModel & rModel) const2669 std::unique_ptr<XFillHatchItem> XFillHatchItem::checkForUniqueItem( SdrModel& rModel ) const
2670 {
2671     const OUString aUniqueName(CheckNamedItem(
2672         XATTR_FILLHATCH, &rModel.GetItemPool(),
2673         XFillHatchItem::CompareValueFunc, RID_SVXSTR_HATCH10,
2674         rModel.GetPropertyList(XPropertyListType::Hatch)));
2675 
2676     // if the given name is not valid, replace it!
2677     if( aUniqueName != GetName() )
2678         return std::make_unique<XFillHatchItem>( aUniqueName, m_aHatch );
2679 
2680     return nullptr;
2681 }
2682 
2683 // --- form text attributes ---
2684 
2685 
CreateDefault()2686 SfxPoolItem* XFormTextStyleItem::CreateDefault() { return new XFormTextStyleItem; }
2687 
XFormTextStyleItem(XFormTextStyle eTheStyle)2688 XFormTextStyleItem::XFormTextStyleItem(XFormTextStyle eTheStyle) :
2689     SfxEnumItem(XATTR_FORMTXTSTYLE, eTheStyle)
2690 {
2691 }
2692 
Clone(SfxItemPool *) const2693 XFormTextStyleItem* XFormTextStyleItem::Clone(SfxItemPool* /*pPool*/) const
2694 {
2695     return new XFormTextStyleItem( *this );
2696 }
2697 
QueryValue(uno::Any & rVal,sal_uInt8) const2698 bool XFormTextStyleItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
2699 {
2700     rVal <<= static_cast<sal_Int32>(GetValue());
2701     return true;
2702 }
2703 
PutValue(const uno::Any & rVal,sal_uInt8)2704 bool XFormTextStyleItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
2705 {
2706     sal_Int32 nValue = 0;
2707     rVal >>= nValue;
2708     SetValue(static_cast<XFormTextStyle>(nValue));
2709 
2710     return true;
2711 }
2712 
2713 
CreateDefault()2714 SfxPoolItem* XFormTextAdjustItem::CreateDefault() { return new XFormTextAdjustItem; }
2715 
XFormTextAdjustItem(XFormTextAdjust eTheAdjust)2716 XFormTextAdjustItem::XFormTextAdjustItem(XFormTextAdjust eTheAdjust) :
2717     SfxEnumItem(XATTR_FORMTXTADJUST, eTheAdjust)
2718 {
2719 }
2720 
Clone(SfxItemPool *) const2721 XFormTextAdjustItem* XFormTextAdjustItem::Clone(SfxItemPool* /*pPool*/) const
2722 {
2723     return new XFormTextAdjustItem( *this );
2724 }
2725 
QueryValue(uno::Any & rVal,sal_uInt8) const2726 bool XFormTextAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
2727 {
2728     rVal <<= static_cast<sal_Int32>(GetValue());
2729     return true;
2730 }
2731 
PutValue(const uno::Any & rVal,sal_uInt8)2732 bool XFormTextAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
2733 {
2734     sal_Int32 nValue = 0;
2735     rVal >>= nValue;
2736     SetValue(static_cast<XFormTextAdjust>(nValue));
2737 
2738     return true;
2739 }
2740 
2741 
CreateDefault()2742 SfxPoolItem* XFormTextDistanceItem::CreateDefault() { return new XFormTextDistanceItem; }
2743 
XFormTextDistanceItem(tools::Long nDist)2744 XFormTextDistanceItem::XFormTextDistanceItem(tools::Long nDist) :
2745     SfxMetricItem(XATTR_FORMTXTDISTANCE, nDist)
2746 {
2747 }
2748 
Clone(SfxItemPool *) const2749 XFormTextDistanceItem* XFormTextDistanceItem::Clone(SfxItemPool* /*pPool*/) const
2750 {
2751     return new XFormTextDistanceItem(*this);
2752 }
2753 
CreateDefault()2754 SfxPoolItem* XFormTextStartItem::CreateDefault() { return new XFormTextStartItem; }
2755 
XFormTextStartItem(tools::Long nStart)2756 XFormTextStartItem::XFormTextStartItem(tools::Long nStart) :
2757     SfxMetricItem(XATTR_FORMTXTSTART, nStart)
2758 {
2759 }
2760 
Clone(SfxItemPool *) const2761 XFormTextStartItem* XFormTextStartItem::Clone(SfxItemPool* /*pPool*/) const
2762 {
2763     return new XFormTextStartItem(*this);
2764 }
2765 
CreateDefault()2766 SfxPoolItem* XFormTextMirrorItem::CreateDefault() { return new XFormTextMirrorItem; }
2767 
XFormTextMirrorItem(bool bMirror)2768 XFormTextMirrorItem::XFormTextMirrorItem(bool bMirror) :
2769     SfxBoolItem(XATTR_FORMTXTMIRROR, bMirror)
2770 {
2771 }
2772 
Clone(SfxItemPool *) const2773 XFormTextMirrorItem* XFormTextMirrorItem::Clone(SfxItemPool* /*pPool*/) const
2774 {
2775     return new XFormTextMirrorItem(*this);
2776 }
2777 
CreateDefault()2778 SfxPoolItem* XFormTextOutlineItem::CreateDefault() { return new XFormTextOutlineItem; }
2779 
XFormTextOutlineItem(bool bOutline)2780 XFormTextOutlineItem::XFormTextOutlineItem(bool bOutline) :
2781     SfxBoolItem(XATTR_FORMTXTOUTLINE, bOutline)
2782 {
2783 }
2784 
Clone(SfxItemPool *) const2785 XFormTextOutlineItem* XFormTextOutlineItem::Clone(SfxItemPool* /*pPool*/) const
2786 {
2787     return new XFormTextOutlineItem(*this);
2788 }
2789 
CreateDefault()2790 SfxPoolItem* XFormTextShadowItem::CreateDefault() { return new XFormTextShadowItem; }
2791 
XFormTextShadowItem(XFormTextShadow eFormTextShadow)2792 XFormTextShadowItem::XFormTextShadowItem(XFormTextShadow eFormTextShadow) :
2793     SfxEnumItem(XATTR_FORMTXTSHADOW, eFormTextShadow)
2794 {
2795 }
2796 
Clone(SfxItemPool *) const2797 XFormTextShadowItem* XFormTextShadowItem::Clone(SfxItemPool* /*pPool*/) const
2798 {
2799     return new XFormTextShadowItem( *this );
2800 }
2801 
QueryValue(uno::Any & rVal,sal_uInt8) const2802 bool XFormTextShadowItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
2803 {
2804     rVal <<= static_cast<sal_Int32>(GetValue());
2805     return true;
2806 }
2807 
PutValue(const uno::Any & rVal,sal_uInt8)2808 bool XFormTextShadowItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
2809 {
2810     sal_Int32 nValue = 0;
2811     rVal >>= nValue;
2812     SetValue(static_cast<XFormTextShadow>(nValue));
2813 
2814     return true;
2815 }
2816 
2817 
CreateDefault()2818 SfxPoolItem* XFormTextShadowColorItem::CreateDefault() { return new XFormTextShadowColorItem; }
2819 
XFormTextShadowColorItem(const OUString & rName,const Color & rTheColor)2820 XFormTextShadowColorItem::XFormTextShadowColorItem(const OUString& rName,
2821                                                      const Color& rTheColor) :
2822     XColorItem(XATTR_FORMTXTSHDWCOLOR, rName, rTheColor)
2823 {
2824 }
2825 
Clone(SfxItemPool *) const2826 XFormTextShadowColorItem* XFormTextShadowColorItem::Clone(SfxItemPool* /*pPool*/) const
2827 {
2828     return new XFormTextShadowColorItem(*this);
2829 }
2830 
CreateDefault()2831 SfxPoolItem* XFormTextShadowXValItem::CreateDefault() { return new XFormTextShadowXValItem; }
2832 
XFormTextShadowXValItem(tools::Long nVal)2833 XFormTextShadowXValItem::XFormTextShadowXValItem(tools::Long nVal) :
2834     SfxMetricItem(XATTR_FORMTXTSHDWXVAL, nVal)
2835 {
2836 }
2837 
Clone(SfxItemPool *) const2838 XFormTextShadowXValItem* XFormTextShadowXValItem::Clone(SfxItemPool* /*pPool*/) const
2839 {
2840     return new XFormTextShadowXValItem(*this);
2841 }
2842 
CreateDefault()2843 SfxPoolItem* XFormTextShadowYValItem::CreateDefault() { return new XFormTextShadowYValItem; }
2844 
XFormTextShadowYValItem(tools::Long nVal)2845 XFormTextShadowYValItem::XFormTextShadowYValItem(tools::Long nVal) :
2846     SfxMetricItem(XATTR_FORMTXTSHDWYVAL, nVal)
2847 {
2848 }
2849 
Clone(SfxItemPool *) const2850 XFormTextShadowYValItem* XFormTextShadowYValItem::Clone(SfxItemPool* /*pPool*/) const
2851 {
2852     return new XFormTextShadowYValItem(*this);
2853 }
2854 
CreateDefault()2855 SfxPoolItem* XFormTextHideFormItem::CreateDefault() { return new XFormTextHideFormItem; }
2856 
XFormTextHideFormItem(bool bHide)2857 XFormTextHideFormItem::XFormTextHideFormItem(bool bHide) :
2858     SfxBoolItem(XATTR_FORMTXTHIDEFORM, bHide)
2859 {
2860 }
2861 
Clone(SfxItemPool *) const2862 XFormTextHideFormItem* XFormTextHideFormItem::Clone(SfxItemPool* /*pPool*/) const
2863 {
2864     return new XFormTextHideFormItem(*this);
2865 }
2866 
2867 // --- SetItems ---
2868 
2869 
2870 /// a line attribute set item
XLineAttrSetItem(SfxItemSet && pItemSet)2871 XLineAttrSetItem::XLineAttrSetItem( SfxItemSet&& pItemSet ) :
2872     SfxSetItem( XATTRSET_LINE, std::move(pItemSet))
2873 {
2874 }
2875 
XLineAttrSetItem(SfxItemPool * pItemPool)2876 XLineAttrSetItem::XLineAttrSetItem( SfxItemPool* pItemPool ) :
2877     SfxSetItem(XATTRSET_LINE,
2878                SfxItemSet::makeFixedSfxItemSet<XATTR_LINE_FIRST, XATTR_LINE_LAST>(*pItemPool))
2879 {
2880 }
2881 
XLineAttrSetItem(const XLineAttrSetItem & rLineAttr)2882 XLineAttrSetItem::XLineAttrSetItem( const XLineAttrSetItem& rLineAttr ) :
2883     SfxSetItem( rLineAttr )
2884 {
2885 }
2886 
XLineAttrSetItem(const XLineAttrSetItem & rLineAttr,SfxItemPool * pItemPool)2887 XLineAttrSetItem::XLineAttrSetItem( const XLineAttrSetItem& rLineAttr,
2888                                     SfxItemPool* pItemPool) :
2889     SfxSetItem( rLineAttr, pItemPool )
2890 {
2891 }
2892 
Clone(SfxItemPool * pPool) const2893 XLineAttrSetItem* XLineAttrSetItem::Clone( SfxItemPool* pPool ) const
2894 {
2895     return new XLineAttrSetItem( *this, pPool );
2896 }
2897 
2898 /// fill attribute set item
XFillAttrSetItem(SfxItemSet && pItemSet)2899 XFillAttrSetItem::XFillAttrSetItem( SfxItemSet&& pItemSet ) :
2900     SfxSetItem( XATTRSET_FILL, std::move(pItemSet))
2901 {
2902 }
2903 
XFillAttrSetItem(SfxItemPool * pItemPool)2904 XFillAttrSetItem::XFillAttrSetItem( SfxItemPool* pItemPool ) :
2905     SfxSetItem(XATTRSET_FILL,
2906                SfxItemSet::makeFixedSfxItemSet<XATTR_FILL_FIRST, XATTR_FILL_LAST>(*pItemPool))
2907 {
2908 }
2909 
XFillAttrSetItem(const XFillAttrSetItem & rFillAttr)2910 XFillAttrSetItem::XFillAttrSetItem( const XFillAttrSetItem& rFillAttr ) :
2911     SfxSetItem( rFillAttr )
2912 {
2913 }
2914 
XFillAttrSetItem(const XFillAttrSetItem & rFillAttr,SfxItemPool * pItemPool)2915 XFillAttrSetItem::XFillAttrSetItem( const XFillAttrSetItem& rFillAttr,
2916                                     SfxItemPool* pItemPool ) :
2917     SfxSetItem( rFillAttr, pItemPool )
2918 {
2919 }
2920 
Clone(SfxItemPool * pPool) const2921 XFillAttrSetItem* XFillAttrSetItem::Clone( SfxItemPool* pPool ) const
2922 {
2923     return new XFillAttrSetItem( *this, pPool );
2924 }
2925 
2926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2927