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 <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
21 #include <com/sun/star/lang/DisposedException.hpp>
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <com/sun/star/awt/FontSlant.hpp>
24 #include <com/sun/star/style/VerticalAlignment.hpp>
25 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
26 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
27 #include <com/sun/star/awt/TextAlign.hpp>
28 #include <com/sun/star/style/ParagraphAdjust.hpp>
29 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
30 #include <com/sun/star/drawing/PointSequence.hpp>
31 #include <com/sun/star/drawing/PolygonKind.hpp>
32 #include <com/sun/star/graphic/XGraphic.hpp>
33 #include <com/sun/star/drawing/QRCode.hpp>
34 #include <o3tl/any.hxx>
35 #include <o3tl/safeint.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/wmf.hxx>
38 #include <vcl/cvtgrf.hxx>
39 #include <vcl/GraphicLoader.hxx>
40 
41 #include <svx/svdpool.hxx>
42 
43 #include <editeng/unoprnms.hxx>
44 #include <svx/unoshape.hxx>
45 #include <svx/unopage.hxx>
46 #include <svx/svdobj.hxx>
47 #include <svx/svdpage.hxx>
48 #include <svx/svdmodel.hxx>
49 #include <svx/svdouno.hxx>
50 #include "shapeimpl.hxx"
51 #include <svx/unoshprp.hxx>
52 #include <svx/svdoashp.hxx>
53 #include <svx/svdviter.hxx>
54 #include <svx/svdview.hxx>
55 #include <svx/svdopath.hxx>
56 #include <basegfx/matrix/b2dhommatrix.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <basegfx/point/b2dpoint.hxx>
59 #include <basegfx/polygon/b2dpolygontools.hxx>
60 #include <basegfx/polygon/b2dpolypolygontools.hxx>
61 #include <com/sun/star/awt/XBitmap.hpp>
62 #include <svx/svdograf.hxx>
63 #include <sal/log.hxx>
64 #include <cppuhelper/queryinterface.hxx>
65 #include <tools/stream.hxx>
66 
67 
68 #include <memory>
69 
70 using namespace ::osl;
71 using namespace ::cppu;
72 using namespace ::com::sun::star;
73 using namespace ::com::sun::star::uno;
74 using namespace ::com::sun::star::lang;
75 using namespace ::com::sun::star::container;
76 
77 #define QUERYINT( xint ) \
78     if( rType == cppu::UnoType<xint>::get() ) \
79         aAny <<= Reference< xint >(this)
80 
SvxShapeGroup(SdrObject * pObj,SvxDrawPage * pDrawPage)81 SvxShapeGroup::SvxShapeGroup(SdrObject* pObj, SvxDrawPage* pDrawPage)
82     : SvxShape(pObj, getSvxMapProvider().GetMap(SVXMAP_GROUP), getSvxMapProvider().GetPropertySet(SVXMAP_GROUP, SdrObject::GetGlobalDrawObjectItemPool()))
83     , mxPage(pDrawPage)
84 {
85 }
86 
~SvxShapeGroup()87 SvxShapeGroup::~SvxShapeGroup() noexcept
88 {
89 }
90 
Create(SdrObject * pNewObj,SvxDrawPage * pNewPage)91 void SvxShapeGroup::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage )
92 {
93     SvxShape::Create( pNewObj, pNewPage );
94     mxPage = pNewPage;
95 }
96 
97 
queryInterface(const uno::Type & rType)98 uno::Any SAL_CALL SvxShapeGroup::queryInterface( const uno::Type & rType )
99 {
100     return SvxShape::queryInterface( rType );
101 }
102 
queryAggregation(const uno::Type & rType)103 uno::Any SAL_CALL SvxShapeGroup::queryAggregation( const uno::Type & rType )
104 {
105     uno::Any aAny;
106 
107     QUERYINT( drawing::XShapeGroup );
108     else QUERYINT( drawing::XShapes );
109     else QUERYINT( drawing::XShapes2 );
110     else QUERYINT( container::XIndexAccess );
111     else QUERYINT( container::XElementAccess );
112     else
113         return SvxShape::queryAggregation( rType );
114 
115     return aAny;
116 }
117 
getImplementationId()118 uno::Sequence< sal_Int8 > SAL_CALL SvxShapeGroup::getImplementationId()
119 {
120     return css::uno::Sequence<sal_Int8>();
121 }
122 
123 // css::drawing::XShape
124 
125 
getShapeType()126 OUString SAL_CALL SvxShapeGroup::getShapeType()
127 {
128     return SvxShape::getShapeType();
129 }
130 
getPosition()131 awt::Point SAL_CALL SvxShapeGroup::getPosition()
132 {
133     return SvxShape::getPosition();
134 }
135 
136 
setPosition(const awt::Point & Position)137 void SAL_CALL SvxShapeGroup::setPosition( const awt::Point& Position )
138 {
139     SvxShape::setPosition(Position);
140 }
141 
142 
getSize()143 awt::Size SAL_CALL SvxShapeGroup::getSize()
144 {
145     return SvxShape::getSize();
146 }
147 
148 
setSize(const awt::Size & rSize)149 void SAL_CALL SvxShapeGroup::setSize( const awt::Size& rSize )
150 {
151     SvxShape::setSize( rSize );
152 }
153 
154 // drawing::XShapeGroup
155 
156 
enterGroup()157 void SAL_CALL SvxShapeGroup::enterGroup(  )
158 {
159     // Todo
160 //  pDrView->EnterMarkedGroup();
161 }
162 
163 
leaveGroup()164 void SAL_CALL SvxShapeGroup::leaveGroup(  )
165 {
166     // Todo
167 //  pDrView->LeaveOneGroup();
168 }
169 
addUnoShape(const uno::Reference<drawing::XShape> & xShape,size_t nPos)170 void SvxShapeGroup::addUnoShape( const uno::Reference< drawing::XShape >& xShape, size_t nPos )
171 {
172     if (!HasSdrObject() || !mxPage.is())
173     {
174         OSL_FAIL("could not add XShape to group shape!");
175         return;
176     }
177 
178     SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
179     if (!pShape)
180     {
181         OSL_FAIL("could not add XShape to group shape!");
182         return;
183     }
184 
185     SdrObject* pSdrShape = pShape->GetSdrObject();
186     if( pSdrShape == nullptr )
187         pSdrShape = mxPage->CreateSdrObject_( xShape );
188 
189     if( pSdrShape->IsInserted() )
190         pSdrShape->getParentSdrObjListFromSdrObject()->RemoveObject( pSdrShape->GetOrdNum() );
191 
192     GetSdrObject()->GetSubList()->InsertObject(pSdrShape, nPos);
193     // TTTT Was created using mpModel in CreateSdrObject_ above
194     // TTTT may be good to add an assertion here for the future
195     // pSdrShape->SetModel(GetSdrObject()->GetModel());
196 
197     // #85922# It makes no sense to set the layer asked
198     // from the group object since this is an iteration
199     // over the contained objects. In consequence, this
200     // statement erases all layer information from the draw
201     // objects. Layers need to be set at draw objects directly
202     // and have nothing to do with grouping at all.
203     // pSdrShape->SetLayer(pObject->GetLayer());
204 
205     // Establish connection between new SdrObject and its wrapper before
206     // inserting the new shape into the group.  There a new wrapper
207     // would be created when this connection would not already exist.
208     pShape->Create( pSdrShape, mxPage.get() );
209 
210     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
211 }
212 
213 // XShapes
add(const uno::Reference<drawing::XShape> & xShape)214 void SAL_CALL SvxShapeGroup::add( const uno::Reference< drawing::XShape >& xShape )
215 {
216     ::SolarMutexGuard aGuard;
217 
218     // Add to the top of the stack (i.e. bottom of the list) by default.
219     addUnoShape(xShape, SAL_MAX_SIZE);
220 }
221 
222 
remove(const uno::Reference<drawing::XShape> & xShape)223 void SAL_CALL SvxShapeGroup::remove( const uno::Reference< drawing::XShape >& xShape )
224 {
225     ::SolarMutexGuard aGuard;
226 
227     SdrObject* pSdrShape = SdrObject::getSdrObjectFromXShape( xShape );
228 
229     if( !HasSdrObject() || pSdrShape == nullptr || pSdrShape->getParentSdrObjectFromSdrObject() != GetSdrObject() )
230         throw uno::RuntimeException();
231 
232     SdrObjList& rList = *pSdrShape->getParentSdrObjListFromSdrObject();
233 
234     const size_t nObjCount = rList.GetObjCount();
235     size_t nObjNum = 0;
236     while( nObjNum < nObjCount )
237     {
238         if(rList.GetObj( nObjNum ) == pSdrShape )
239             break;
240         nObjNum++;
241     }
242 
243     if( nObjNum < nObjCount )
244     {
245         // #i29181#
246         // If the SdrObject which is about to be deleted is in any selection,
247         // deselect it first.
248         SdrViewIter aIter( pSdrShape );
249 
250         for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() )
251         {
252             if(SAL_MAX_SIZE != pView->TryToFindMarkedObject(pSdrShape))
253             {
254                 pView->MarkObj(pSdrShape, pView->GetSdrPageView(), true);
255             }
256         }
257 
258         SdrObject* pObject = rList.NbcRemoveObject( nObjNum );
259         SdrObject::Free( pObject );
260     }
261     else
262     {
263         SAL_WARN( "svx", "Fatality! SdrObject is not belonging to its SdrObjList! [CL]" );
264     }
265 
266     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
267 }
268 
addTop(const uno::Reference<drawing::XShape> & xShape)269 void SAL_CALL SvxShapeGroup::addTop( const uno::Reference< drawing::XShape >& xShape )
270 {
271     SolarMutexGuard aGuard;
272 
273     // Add to the top of the stack (i.e. bottom of the list).
274     addUnoShape(xShape, SAL_MAX_SIZE);
275 }
276 
addBottom(const uno::Reference<drawing::XShape> & xShape)277 void SAL_CALL SvxShapeGroup::addBottom( const uno::Reference< drawing::XShape >& xShape )
278 {
279     SolarMutexGuard aGuard;
280 
281     // Add to the bottom of the stack (i.e. top of the list).
282     addUnoShape(xShape, 0);
283 }
284 
285 // XIndexAccess
286 
287 
getCount()288 sal_Int32 SAL_CALL SvxShapeGroup::getCount()
289 {
290     ::SolarMutexGuard aGuard;
291 
292     if(!HasSdrObject() || !GetSdrObject()->GetSubList())
293         throw uno::RuntimeException();
294 
295     sal_Int32 nRetval = GetSdrObject()->GetSubList()->GetObjCount();
296     return nRetval;
297 }
298 
299 
getByIndex(sal_Int32 Index)300 uno::Any SAL_CALL SvxShapeGroup::getByIndex( sal_Int32 Index )
301 {
302     ::SolarMutexGuard aGuard;
303 
304     if( !HasSdrObject() || GetSdrObject()->GetSubList() == nullptr )
305         throw uno::RuntimeException();
306 
307     if( Index<0 || GetSdrObject()->GetSubList()->GetObjCount() <= o3tl::make_unsigned(Index) )
308         throw lang::IndexOutOfBoundsException();
309 
310     SdrObject* pDestObj = GetSdrObject()->GetSubList()->GetObj( Index );
311 
312     if(pDestObj == nullptr)
313         throw lang::IndexOutOfBoundsException();
314 
315     Reference< drawing::XShape > xShape( pDestObj->getUnoShape(), uno::UNO_QUERY );
316     return uno::makeAny( xShape );
317 }
318 
319 // css::container::XElementAccess
320 
321 
getElementType()322 uno::Type SAL_CALL SvxShapeGroup::getElementType()
323 {
324     return cppu::UnoType<drawing::XShape>::get();
325 }
326 
327 
hasElements()328 sal_Bool SAL_CALL SvxShapeGroup::hasElements()
329 {
330     ::SolarMutexGuard aGuard;
331 
332     return HasSdrObject() && GetSdrObject()->GetSubList() && (GetSdrObject()->GetSubList()->GetObjCount() > 0);
333 }
334 
SvxShapeConnector(SdrObject * pObj)335 SvxShapeConnector::SvxShapeConnector(SdrObject* pObj)
336     : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CONNECTOR), getSvxMapProvider().GetPropertySet(SVXMAP_CONNECTOR, SdrObject::GetGlobalDrawObjectItemPool()) )
337 {
338 }
339 
340 
~SvxShapeConnector()341 SvxShapeConnector::~SvxShapeConnector() noexcept
342 {
343 }
344 
345 
queryInterface(const uno::Type & rType)346 uno::Any SAL_CALL SvxShapeConnector::queryInterface( const uno::Type & rType )
347 {
348     return SvxShapeText::queryInterface( rType );
349 }
350 
queryAggregation(const uno::Type & rType)351 uno::Any SAL_CALL SvxShapeConnector::queryAggregation( const uno::Type & rType )
352 {
353     uno::Any aAny;
354 
355     QUERYINT( drawing::XConnectorShape );
356     else
357         return SvxShapeText::queryAggregation( rType );
358 
359     return aAny;
360 }
361 
362 // XTypeProvider
363 
getTypes()364 uno::Sequence< uno::Type > SAL_CALL SvxShapeConnector::getTypes()
365 {
366     return SvxShape::getTypes();
367 }
368 
getImplementationId()369 uno::Sequence< sal_Int8 > SAL_CALL SvxShapeConnector::getImplementationId()
370 {
371     return css::uno::Sequence<sal_Int8>();
372 }
373 
374 // css::drawing::XShape
375 
376 
getShapeType()377 OUString SAL_CALL SvxShapeConnector::getShapeType()
378 {
379     return SvxShapeText::getShapeType();
380 }
381 
getPosition()382 awt::Point SAL_CALL SvxShapeConnector::getPosition()
383 {
384     return SvxShapeText::getPosition();
385 }
386 
387 
setPosition(const awt::Point & Position)388 void SAL_CALL SvxShapeConnector::setPosition( const awt::Point& Position )
389 {
390     SvxShapeText::setPosition(Position);
391 }
392 
393 
getSize()394 awt::Size SAL_CALL SvxShapeConnector::getSize()
395 {
396     return SvxShapeText::getSize();
397 }
398 
399 
setSize(const awt::Size & rSize)400 void SAL_CALL SvxShapeConnector::setSize( const awt::Size& rSize )
401 {
402     SvxShapeText::setSize( rSize );
403 }
404 
405 
406 // XConnectorShape
407 
connectStart(const uno::Reference<drawing::XConnectableShape> & xShape,drawing::ConnectionType)408 void SAL_CALL SvxShapeConnector::connectStart( const uno::Reference< drawing::XConnectableShape >& xShape, drawing::ConnectionType )
409 {
410     ::SolarMutexGuard aGuard;
411 
412     Reference< drawing::XShape > xRef( xShape, UNO_QUERY );
413     SdrObject* pSdrObject = SdrObject::getSdrObjectFromXShape( xRef );
414 
415     if( pSdrObject )
416         GetSdrObject()->ConnectToNode( true, pSdrObject );
417 
418     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
419 }
420 
421 
connectEnd(const uno::Reference<drawing::XConnectableShape> & xShape,drawing::ConnectionType)422 void SAL_CALL SvxShapeConnector::connectEnd( const uno::Reference< drawing::XConnectableShape >& xShape, drawing::ConnectionType  )
423 {
424     ::SolarMutexGuard aGuard;
425 
426     Reference< drawing::XShape > xRef( xShape, UNO_QUERY );
427     SdrObject* pSdrObject = SdrObject::getSdrObjectFromXShape( xRef );
428 
429     if( HasSdrObject() && pSdrObject )
430         GetSdrObject()->ConnectToNode( false, pSdrObject );
431 
432     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
433 }
434 
435 
disconnectBegin(const uno::Reference<drawing::XConnectableShape> &)436 void SAL_CALL SvxShapeConnector::disconnectBegin( const uno::Reference< drawing::XConnectableShape >&  )
437 {
438     ::SolarMutexGuard aGuard;
439 
440     if(HasSdrObject())
441         GetSdrObject()->DisconnectFromNode( true );
442 
443     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
444 }
445 
446 
disconnectEnd(const uno::Reference<drawing::XConnectableShape> &)447 void SAL_CALL SvxShapeConnector::disconnectEnd( const uno::Reference< drawing::XConnectableShape >& )
448 {
449     ::SolarMutexGuard aGuard;
450 
451     if(HasSdrObject())
452         GetSdrObject()->DisconnectFromNode( false );
453 
454     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
455 }
456 
SvxShapeControl(SdrObject * pObj)457 SvxShapeControl::SvxShapeControl(SdrObject* pObj)
458     : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CONTROL), getSvxMapProvider().GetPropertySet(SVXMAP_CONTROL, SdrObject::GetGlobalDrawObjectItemPool()) )
459 {
460     setShapeKind( OBJ_UNO );
461 }
462 
463 
~SvxShapeControl()464 SvxShapeControl::~SvxShapeControl() noexcept
465 {
466 }
467 
468 
queryInterface(const uno::Type & rType)469 uno::Any SAL_CALL SvxShapeControl::queryInterface( const uno::Type & rType )
470 {
471     return SvxShapeText::queryInterface( rType );
472 }
473 
queryAggregation(const uno::Type & rType)474 uno::Any SAL_CALL SvxShapeControl::queryAggregation( const uno::Type & rType )
475 {
476     uno::Any aAny;
477 
478     QUERYINT( drawing::XControlShape );
479     else
480         return SvxShapeText::queryAggregation( rType );
481 
482     return aAny;
483 }
484 
485 // XTypeProvider
486 
getTypes()487 uno::Sequence< uno::Type > SAL_CALL SvxShapeControl::getTypes()
488 {
489     return SvxShape::getTypes();
490 }
491 
getImplementationId()492 uno::Sequence< sal_Int8 > SAL_CALL SvxShapeControl::getImplementationId()
493 {
494     return css::uno::Sequence<sal_Int8>();
495 }
496 
497 // css::drawing::XShape
498 
499 
getShapeType()500 OUString SAL_CALL SvxShapeControl::getShapeType()
501 {
502     return SvxShapeText::getShapeType();
503 }
504 
getPosition()505 awt::Point SAL_CALL SvxShapeControl::getPosition()
506 {
507     return SvxShapeText::getPosition();
508 }
509 
510 
setPosition(const awt::Point & Position)511 void SAL_CALL SvxShapeControl::setPosition( const awt::Point& Position )
512 {
513     SvxShapeText::setPosition(Position);
514 }
515 
516 
getSize()517 awt::Size SAL_CALL SvxShapeControl::getSize()
518 {
519     return SvxShapeText::getSize();
520 }
521 
522 
setSize(const awt::Size & rSize)523 void SAL_CALL SvxShapeControl::setSize( const awt::Size& rSize )
524 {
525     SvxShapeText::setSize( rSize );
526 }
527 
528 
529 // XControlShape
530 
getControl()531 Reference< awt::XControlModel > SAL_CALL SvxShapeControl::getControl()
532 {
533     ::SolarMutexGuard aGuard;
534 
535     Reference< awt::XControlModel > xModel;
536 
537     SdrUnoObj* pUnoObj = dynamic_cast< SdrUnoObj * >(GetSdrObject());
538     if( pUnoObj )
539         xModel = pUnoObj->GetUnoControlModel();
540 
541     return xModel;
542 }
543 
544 
setControl(const Reference<awt::XControlModel> & xControl)545 void SAL_CALL SvxShapeControl::setControl( const Reference< awt::XControlModel >& xControl )
546 {
547     ::SolarMutexGuard aGuard;
548 
549     SdrUnoObj* pUnoObj = dynamic_cast< SdrUnoObj * >(GetSdrObject());
550     if( pUnoObj )
551         pUnoObj->SetUnoControlModel( xControl );
552 
553     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
554 }
555 
556 struct
557 {
558     const char* mpAPIName;
559     sal_uInt16  mnAPINameLen;
560 
561     const char* mpFormName;
562     sal_uInt16  mnFormNameLen;
563 }
564 const SvxShapeControlPropertyMapping[] =
565 {
566     // Warning: The first entry must be FontSlant because the any needs to be converted
567     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_POSTURE), RTL_CONSTASCII_STRINGPARAM("FontSlant")  }, //  const sal_Int16 => css::awt::FontSlant
568     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_FONTNAME), RTL_CONSTASCII_STRINGPARAM("FontName") },
569     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_FONTSTYLENAME), RTL_CONSTASCII_STRINGPARAM("FontStyleName") },
570     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_FONTFAMILY), RTL_CONSTASCII_STRINGPARAM("FontFamily") },
571     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_FONTCHARSET), RTL_CONSTASCII_STRINGPARAM("FontCharset") },
572     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_HEIGHT), RTL_CONSTASCII_STRINGPARAM("FontHeight") },
573     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_FONTPITCH), RTL_CONSTASCII_STRINGPARAM("FontPitch" ) },
574     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_WEIGHT), RTL_CONSTASCII_STRINGPARAM("FontWeight" ) },
575     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_UNDERLINE), RTL_CONSTASCII_STRINGPARAM("FontUnderline") },
576     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_STRIKEOUT), RTL_CONSTASCII_STRINGPARAM("FontStrikeout") },
577     { RTL_CONSTASCII_STRINGPARAM("CharKerning"), RTL_CONSTASCII_STRINGPARAM("FontKerning") },
578     { RTL_CONSTASCII_STRINGPARAM("CharWordMode"), RTL_CONSTASCII_STRINGPARAM("FontWordLineMode" ) },
579     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_COLOR),   RTL_CONSTASCII_STRINGPARAM("TextColor") },
580     { RTL_CONSTASCII_STRINGPARAM("CharBackColor"), RTL_CONSTASCII_STRINGPARAM("CharBackColor") },
581     { RTL_CONSTASCII_STRINGPARAM("CharBackTransparent"), RTL_CONSTASCII_STRINGPARAM("CharBackTransparent") },
582     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_TEXT_CHAINNEXTNAME), RTL_CONSTASCII_STRINGPARAM(UNO_NAME_TEXT_CHAINNEXTNAME) },
583     { RTL_CONSTASCII_STRINGPARAM("CharRelief"),   RTL_CONSTASCII_STRINGPARAM("FontRelief") },
584     { RTL_CONSTASCII_STRINGPARAM("CharUnderlineColor"),   RTL_CONSTASCII_STRINGPARAM("TextLineColor") },
585     { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_PARA_ADJUST), RTL_CONSTASCII_STRINGPARAM("Align") },
586     { RTL_CONSTASCII_STRINGPARAM("TextVerticalAdjust"), RTL_CONSTASCII_STRINGPARAM("VerticalAlign") },
587     { RTL_CONSTASCII_STRINGPARAM("ControlBackground"), RTL_CONSTASCII_STRINGPARAM("BackgroundColor") },
588     { RTL_CONSTASCII_STRINGPARAM("ControlSymbolColor"), RTL_CONSTASCII_STRINGPARAM("SymbolColor") },
589     { RTL_CONSTASCII_STRINGPARAM("ControlBorder"), RTL_CONSTASCII_STRINGPARAM("Border") },
590     { RTL_CONSTASCII_STRINGPARAM("ControlBorderColor"), RTL_CONSTASCII_STRINGPARAM("BorderColor") },
591     { RTL_CONSTASCII_STRINGPARAM("ControlTextEmphasis"),  RTL_CONSTASCII_STRINGPARAM("FontEmphasisMark") },
592     { RTL_CONSTASCII_STRINGPARAM("ImageScaleMode"),  RTL_CONSTASCII_STRINGPARAM("ScaleMode") },
593     { RTL_CONSTASCII_STRINGPARAM("ControlWritingMode"), RTL_CONSTASCII_STRINGPARAM("WritingMode") },
594     //added for exporting OCX control
595     { RTL_CONSTASCII_STRINGPARAM("ControlTypeinMSO"), RTL_CONSTASCII_STRINGPARAM("ControlTypeinMSO") },
596     { RTL_CONSTASCII_STRINGPARAM("ObjIDinMSO"), RTL_CONSTASCII_STRINGPARAM("ObjIDinMSO") },
597     { RTL_CONSTASCII_STRINGPARAM("CharCaseMap"), RTL_CONSTASCII_STRINGPARAM("CharCaseMap") },
598     { nullptr,0, nullptr, 0 }
599 };
600 
601 namespace
602 {
lcl_convertPropertyName(const OUString & rApiName,OUString & rInternalName)603     bool lcl_convertPropertyName( const OUString& rApiName, OUString& rInternalName )
604     {
605         sal_uInt16 i = 0;
606         while( SvxShapeControlPropertyMapping[i].mpAPIName )
607         {
608             if( rApiName.reverseCompareToAsciiL( SvxShapeControlPropertyMapping[i].mpAPIName, SvxShapeControlPropertyMapping[i].mnAPINameLen ) == 0 )
609             {
610                 rInternalName = OUString( SvxShapeControlPropertyMapping[i].mpFormName, SvxShapeControlPropertyMapping[i].mnFormNameLen, RTL_TEXTENCODING_ASCII_US );
611             }
612             ++i;
613         }
614         return !rInternalName.isEmpty();
615     }
616 
617     struct EnumConversionMap
618     {
619         style::ParagraphAdjust   nAPIValue;
620         sal_Int16                nFormValue;
621     };
622 
623     EnumConversionMap const aMapAdjustToAlign[] =
624     {
625         // note that order matters:
626         // lcl_convertTextAlignmentToParaAdjustment and lcl_convertParaAdjustmentToTextAlignment search this map from the _beginning_
627         // and use the first matching entry
628         {style::ParagraphAdjust_LEFT,           sal_Int16(awt::TextAlign::LEFT)},
629         {style::ParagraphAdjust_CENTER,         sal_Int16(awt::TextAlign::CENTER)},
630         {style::ParagraphAdjust_RIGHT,          sal_Int16(awt::TextAlign::RIGHT)},
631         {style::ParagraphAdjust_BLOCK,          sal_Int16(awt::TextAlign::RIGHT)},
632         {style::ParagraphAdjust_STRETCH,        sal_Int16(awt::TextAlign::LEFT)},
633         {style::ParagraphAdjust(-1),-1}
634     };
635 
lcl_convertTextAlignmentToParaAdjustment(Any & _rValue)636     void lcl_convertTextAlignmentToParaAdjustment( Any& _rValue )
637     {
638         sal_Int16 nValue = sal_Int16();
639         OSL_VERIFY( _rValue >>= nValue );
640 
641         for ( auto const & rEntry : aMapAdjustToAlign )
642             if ( nValue == rEntry.nFormValue )
643             {
644                 _rValue <<= static_cast<sal_uInt16>(rEntry.nAPIValue);
645                 return;
646             }
647     }
648 
lcl_convertParaAdjustmentToTextAlignment(Any & _rValue)649     void lcl_convertParaAdjustmentToTextAlignment( Any& _rValue )
650     {
651         sal_Int32 nValue = 0;
652         OSL_VERIFY( _rValue >>= nValue );
653 
654         for ( auto const & rEntry : aMapAdjustToAlign )
655             if ( static_cast<style::ParagraphAdjust>(nValue) == rEntry.nAPIValue )
656             {
657                 _rValue <<= rEntry.nFormValue;
658                 return;
659             }
660     }
661 
convertVerticalAdjustToVerticalAlign(Any & _rValue)662     void convertVerticalAdjustToVerticalAlign( Any& _rValue )
663     {
664         if ( !_rValue.hasValue() )
665             return;
666 
667         drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP;
668         style::VerticalAlignment    eAlign  = style::VerticalAlignment_TOP;
669         if ( !( _rValue >>= eAdjust ) )
670             throw lang::IllegalArgumentException();
671         switch ( eAdjust )
672         {
673         case drawing::TextVerticalAdjust_TOP:    eAlign = style::VerticalAlignment_TOP; break;
674         case drawing::TextVerticalAdjust_BOTTOM: eAlign = style::VerticalAlignment_BOTTOM; break;
675         default:                                 eAlign = style::VerticalAlignment_MIDDLE; break;
676         }
677         _rValue <<= eAlign;
678     }
679 
convertVerticalAlignToVerticalAdjust(Any & _rValue)680     void convertVerticalAlignToVerticalAdjust( Any& _rValue )
681     {
682         if ( !_rValue.hasValue() )
683             return;
684         style::VerticalAlignment    eAlign  = style::VerticalAlignment_TOP;
685         drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP;
686         OSL_VERIFY( _rValue >>= eAlign );
687         switch ( eAlign )
688         {
689         case style::VerticalAlignment_TOP:    eAdjust = drawing::TextVerticalAdjust_TOP; break;
690         case style::VerticalAlignment_BOTTOM: eAdjust = drawing::TextVerticalAdjust_BOTTOM; break;
691         default:                              eAdjust = drawing::TextVerticalAdjust_CENTER; break;
692         }
693         _rValue <<= eAdjust;
694     }
695 }
696 
setPropertyValue(const OUString & aPropertyName,const uno::Any & aValue)697 void SAL_CALL SvxShapeControl::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
698 {
699     OUString aFormsName;
700     if ( lcl_convertPropertyName( aPropertyName, aFormsName ) )
701     {
702         uno::Reference< beans::XPropertySet > xControl( getControl(), uno::UNO_QUERY );
703         if( xControl.is() )
704         {
705             uno::Reference< beans::XPropertySetInfo > xInfo( xControl->getPropertySetInfo() );
706             if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) )
707             {
708                 uno::Any aConvertedValue( aValue );
709                 if ( aFormsName == "FontSlant" )
710                 {
711                     awt::FontSlant nSlant;
712                     if( !(aValue >>= nSlant ) )
713                         throw lang::IllegalArgumentException();
714                     aConvertedValue <<= static_cast<sal_Int16>(nSlant);
715                 }
716                 else if ( aFormsName == "Align" )
717                 {
718                     lcl_convertParaAdjustmentToTextAlignment( aConvertedValue );
719                 }
720                 else if ( aFormsName == "VerticalAlign" )
721                 {
722                     convertVerticalAdjustToVerticalAlign( aConvertedValue );
723                 }
724 
725                 xControl->setPropertyValue( aFormsName, aConvertedValue );
726             }
727         }
728     }
729     else
730     {
731         SvxShape::setPropertyValue( aPropertyName, aValue );
732     }
733 }
734 
getPropertyValue(const OUString & aPropertyName)735 uno::Any SAL_CALL SvxShapeControl::getPropertyValue( const OUString& aPropertyName )
736 {
737     OUString aFormsName;
738     if ( lcl_convertPropertyName( aPropertyName, aFormsName ) )
739     {
740         uno::Reference< beans::XPropertySet > xControl( getControl(), uno::UNO_QUERY );
741 
742         uno::Any aValue;
743         if( xControl.is() )
744         {
745             uno::Reference< beans::XPropertySetInfo > xInfo( xControl->getPropertySetInfo() );
746             if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) )
747             {
748                 aValue = xControl->getPropertyValue( aFormsName );
749                 if ( aFormsName == "FontSlant" )
750                 {
751                     awt::FontSlant eSlant = awt::FontSlant_NONE;
752                     sal_Int16 nSlant = sal_Int16();
753                     if ( aValue >>= nSlant )
754                     {
755                         eSlant = static_cast<awt::FontSlant>(nSlant);
756                     }
757                     else
758                     {
759                         OSL_VERIFY( aValue >>= eSlant );
760                     }
761                     aValue <<= eSlant;
762                 }
763                 else if ( aFormsName == "Align" )
764                 {
765                     lcl_convertTextAlignmentToParaAdjustment( aValue );
766                 }
767                 else if ( aFormsName == "VerticalAlign" )
768                 {
769                     convertVerticalAlignToVerticalAdjust( aValue );
770                 }
771             }
772         }
773 
774         return aValue;
775     }
776     else
777     {
778         return SvxShape::getPropertyValue( aPropertyName );
779     }
780 
781 }
782 
783 // XPropertyState
getPropertyState(const OUString & PropertyName)784 beans::PropertyState SAL_CALL SvxShapeControl::getPropertyState( const OUString& PropertyName )
785 {
786     OUString aFormsName;
787     if ( lcl_convertPropertyName( PropertyName, aFormsName ) )
788     {
789         uno::Reference< beans::XPropertyState > xControl( getControl(), uno::UNO_QUERY );
790         uno::Reference< beans::XPropertySet > xPropSet( getControl(), uno::UNO_QUERY );
791 
792         if( xControl.is() && xPropSet.is() )
793         {
794             uno::Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
795             if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) )
796             {
797                 return xControl->getPropertyState( aFormsName );
798             }
799         }
800 
801         return beans::PropertyState_DEFAULT_VALUE;
802     }
803     else
804     {
805         return SvxShape::getPropertyState( PropertyName );
806     }
807 }
808 
setPropertyToDefault(const OUString & PropertyName)809 void SAL_CALL SvxShapeControl::setPropertyToDefault( const OUString& PropertyName )
810 {
811     OUString aFormsName;
812     if ( lcl_convertPropertyName( PropertyName, aFormsName ) )
813     {
814         uno::Reference< beans::XPropertyState > xControl( getControl(), uno::UNO_QUERY );
815         uno::Reference< beans::XPropertySet > xPropSet( getControl(), uno::UNO_QUERY );
816 
817         if( xControl.is() && xPropSet.is() )
818         {
819             uno::Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
820             if( xInfo.is() && xInfo->hasPropertyByName( aFormsName ) )
821             {
822                 xControl->setPropertyToDefault( aFormsName );
823             }
824         }
825     }
826     else
827     {
828         SvxShape::setPropertyToDefault( PropertyName );
829     }
830 }
831 
getPropertyDefault(const OUString & aPropertyName)832 uno::Any SAL_CALL SvxShapeControl::getPropertyDefault( const OUString& aPropertyName )
833 {
834     OUString aFormsName;
835     if ( lcl_convertPropertyName( aPropertyName, aFormsName ) )
836     {
837         uno::Reference< beans::XPropertyState > xControl( getControl(), uno::UNO_QUERY );
838 
839         if( xControl.is() )
840         {
841             Any aDefault( xControl->getPropertyDefault( aFormsName ) );
842             if ( aFormsName == "FontSlant" )
843             {
844                 sal_Int16 nSlant( 0 );
845                 aDefault >>= nSlant;
846                 aDefault <<= static_cast<awt::FontSlant>(nSlant);
847             }
848             else if ( aFormsName == "Align" )
849             {
850                 lcl_convertTextAlignmentToParaAdjustment( aDefault );
851             }
852             else if ( aFormsName == "VerticalAlign" )
853             {
854                 convertVerticalAlignToVerticalAdjust( aDefault );
855             }
856             return aDefault;
857         }
858 
859         throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
860     }
861     else
862     {
863         return SvxShape::getPropertyDefault( aPropertyName );
864     }
865 }
866 
SvxShapeDimensioning(SdrObject * pObj)867 SvxShapeDimensioning::SvxShapeDimensioning(SdrObject* pObj)
868     : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_DIMENSIONING), getSvxMapProvider().GetPropertySet(SVXMAP_DIMENSIONING, SdrObject::GetGlobalDrawObjectItemPool()) )
869 {
870 }
871 
~SvxShapeDimensioning()872 SvxShapeDimensioning::~SvxShapeDimensioning() noexcept
873 {
874 }
875 
SvxShapeCircle(SdrObject * pObj)876 SvxShapeCircle::SvxShapeCircle(SdrObject* pObj)
877     : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CIRCLE), getSvxMapProvider().GetPropertySet(SVXMAP_CIRCLE, SdrObject::GetGlobalDrawObjectItemPool()) )
878 {
879 }
880 
~SvxShapeCircle()881 SvxShapeCircle::~SvxShapeCircle() noexcept
882 {
883 }
884 
885 //////////////////////////////////////////////////////////////////////////////
886 
SvxShapePolyPolygon(SdrObject * pObj)887 SvxShapePolyPolygon::SvxShapePolyPolygon(
888     SdrObject* pObj)
889 :   SvxShapeText(
890         pObj,
891         getSvxMapProvider().GetMap(SVXMAP_POLYPOLYGON),
892         getSvxMapProvider().GetPropertySet(SVXMAP_POLYPOLYGON, SdrObject::GetGlobalDrawObjectItemPool()))
893 {
894 }
895 
~SvxShapePolyPolygon()896 SvxShapePolyPolygon::~SvxShapePolyPolygon() noexcept
897 {
898 }
899 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)900 bool SvxShapePolyPolygon::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
901 {
902     switch( pProperty->nWID )
903     {
904     case OWN_ATTR_VALUE_POLYPOLYGONBEZIER:
905     {
906         if( auto s = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(rValue) )
907         {
908             basegfx::B2DPolyPolygon aNewPolyPolygon(
909                 basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*s));
910 
911             // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
912             ForceMetricToItemPoolMetric(aNewPolyPolygon);
913 
914             SetPolygon(aNewPolyPolygon);
915             return true;
916         }
917         break;
918     }
919     case OWN_ATTR_VALUE_POLYPOLYGON:
920     {
921         if( auto s = o3tl::tryAccess<drawing::PointSequenceSequence>(rValue) )
922         {
923             basegfx::B2DPolyPolygon aNewPolyPolygon(
924                 basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(*s));
925 
926             // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
927             ForceMetricToItemPoolMetric(aNewPolyPolygon);
928 
929             SetPolygon(aNewPolyPolygon);
930             return true;
931         }
932         break;
933     }
934     case OWN_ATTR_BASE_GEOMETRY:
935     {
936         drawing::PointSequenceSequence aPointSequenceSequence;
937         drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
938 
939         if( rValue >>= aPointSequenceSequence)
940         {
941             if( HasSdrObject() )
942             {
943                 basegfx::B2DPolyPolygon aNewPolyPolygon;
944                 basegfx::B2DHomMatrix aNewHomogenMatrix;
945 
946                 GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon);
947                 aNewPolyPolygon = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(aPointSequenceSequence);
948 
949                 // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
950                 // Need to adapt aNewPolyPolygon from 100thmm to app-specific
951                 ForceMetricToItemPoolMetric(aNewPolyPolygon);
952 
953                 GetSdrObject()->TRSetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon);
954             }
955             return true;
956         }
957         else if( rValue >>= aPolyPolygonBezierCoords)
958         {
959             if( HasSdrObject() )
960             {
961                 basegfx::B2DPolyPolygon aNewPolyPolygon;
962                 basegfx::B2DHomMatrix aNewHomogenMatrix;
963 
964                 GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon);
965                 aNewPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(aPolyPolygonBezierCoords);
966 
967                 // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
968                 ForceMetricToItemPoolMetric(aNewPolyPolygon);
969 
970                 GetSdrObject()->TRSetBaseGeometry(aNewHomogenMatrix, aNewPolyPolygon);
971             }
972             return true;
973         }
974         break;
975     }
976     case OWN_ATTR_VALUE_POLYGON:
977     {
978         if( auto pSequence = o3tl::tryAccess<drawing::PointSequence>(rValue) )
979         {
980             // prepare new polygon
981             basegfx::B2DPolygon aNewPolygon;
982 
983             // get pointer to arrays
984             const awt::Point* pArray    = pSequence->getConstArray();
985             const awt::Point* pArrayEnd = pArray + pSequence->getLength();
986 
987             for(;pArray != pArrayEnd;++pArray)
988             {
989                 aNewPolygon.append(basegfx::B2DPoint(pArray->X, pArray->Y));
990             }
991 
992             // check for closed state flag
993             basegfx::utils::checkClosed(aNewPolygon);
994 
995             // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
996             basegfx::B2DPolyPolygon aNewPolyPolygon(aNewPolygon);
997             ForceMetricToItemPoolMetric(aNewPolyPolygon);
998 
999             // set polygon
1000             SetPolygon(aNewPolyPolygon);
1001             return true;
1002         }
1003         break;
1004     }
1005     default:
1006         return SvxShapeText::setPropertyValueImpl( rName, pProperty, rValue );
1007     }
1008 
1009     throw lang::IllegalArgumentException();
1010 }
1011 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)1012 bool SvxShapePolyPolygon::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty,
1013                                                 css::uno::Any& rValue )
1014 {
1015     switch( pProperty->nWID )
1016     {
1017     case OWN_ATTR_VALUE_POLYPOLYGONBEZIER:
1018     {
1019         // pack a tools::PolyPolygon in a struct tools::PolyPolygon
1020         basegfx::B2DPolyPolygon aPolyPoly(GetPolygon());
1021 
1022         // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
1023         ForceMetricTo100th_mm(aPolyPoly);
1024 
1025         drawing::PolyPolygonBezierCoords aRetval;
1026         basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(aPolyPoly, aRetval);
1027 
1028         rValue <<= aRetval;
1029         break;
1030     }
1031     case OWN_ATTR_VALUE_POLYPOLYGON:
1032     {
1033         // pack a tools::PolyPolygon in a struct tools::PolyPolygon
1034         basegfx::B2DPolyPolygon aPolyPoly(GetPolygon());
1035 
1036         // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
1037         ForceMetricTo100th_mm(aPolyPoly);
1038 
1039         drawing::PointSequenceSequence aRetval( aPolyPoly.count() );
1040         basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPoly, aRetval);
1041 
1042         rValue <<= aRetval;
1043         break;
1044     }
1045     case OWN_ATTR_BASE_GEOMETRY:
1046     {
1047         // pack a tools::PolyPolygon in struct PolyPolygon
1048         basegfx::B2DPolyPolygon aPolyPoly;
1049         basegfx::B2DHomMatrix aNewHomogenMatrix;
1050 
1051         if(HasSdrObject())
1052         {
1053             GetSdrObject()->TRGetBaseGeometry(aNewHomogenMatrix, aPolyPoly);
1054 
1055             // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
1056             ForceMetricTo100th_mm(aPolyPoly);
1057         }
1058 
1059         if(aPolyPoly.areControlPointsUsed())
1060         {
1061             drawing::PolyPolygonBezierCoords aRetval;
1062             basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(aPolyPoly, aRetval);
1063             rValue <<= aRetval;
1064         }
1065         else
1066         {
1067             drawing::PointSequenceSequence aRetval(aPolyPoly.count());
1068             basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPoly, aRetval);
1069             rValue <<= aRetval;
1070         }
1071         break;
1072     }
1073     case OWN_ATTR_VALUE_POLYGON:
1074     {
1075         // pack a tools::PolyPolygon in a struct tools::PolyPolygon
1076         basegfx::B2DPolyPolygon aPolyPoly(GetPolygon());
1077 
1078         // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
1079         ForceMetricTo100th_mm(aPolyPoly);
1080 
1081         const sal_Int32 nCount(0 == aPolyPoly.count() ? 0 : aPolyPoly.getB2DPolygon(0).count());
1082         drawing::PointSequence aRetval( nCount );
1083 
1084         if( nCount > 0 )
1085         {
1086             // get single polygon
1087             const basegfx::B2DPolygon& aPoly(aPolyPoly.getB2DPolygon(0));
1088 
1089             // get pointer to arrays
1090             awt::Point* pSequence = aRetval.getArray();
1091 
1092             for(sal_Int32 b=0;b<nCount;b++)
1093             {
1094                 const basegfx::B2DPoint aPoint(aPoly.getB2DPoint(b));
1095                 *pSequence++ = awt::Point( basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()) );
1096             }
1097         }
1098 
1099         rValue <<= aRetval;
1100         break;
1101     }
1102     case OWN_ATTR_VALUE_POLYGONKIND:
1103     {
1104         rValue <<= GetPolygonKind();
1105         break;
1106     }
1107     default:
1108         return SvxShapeText::getPropertyValueImpl( rName, pProperty, rValue );
1109     }
1110 
1111     return true;
1112 }
1113 
GetPolygonKind() const1114 drawing::PolygonKind SvxShapePolyPolygon::GetPolygonKind() const
1115 {
1116     ::SolarMutexGuard aGuard;
1117     drawing::PolygonKind aRetval(drawing::PolygonKind_LINE);
1118 
1119     if(HasSdrObject())
1120     {
1121         switch(GetSdrObject()->GetObjIdentifier())
1122         {
1123             case OBJ_POLY:      aRetval = drawing::PolygonKind_POLY; break;
1124             case OBJ_PLIN:      aRetval = drawing::PolygonKind_PLIN; break;
1125             case OBJ_SPLNLINE:
1126             case OBJ_PATHLINE:  aRetval = drawing::PolygonKind_PATHLINE; break;
1127             case OBJ_SPLNFILL:
1128             case OBJ_PATHFILL:  aRetval = drawing::PolygonKind_PATHFILL; break;
1129             case OBJ_FREELINE:  aRetval = drawing::PolygonKind_FREELINE; break;
1130             case OBJ_FREEFILL:  aRetval = drawing::PolygonKind_FREEFILL; break;
1131             default: break;
1132         }
1133     }
1134 
1135     return aRetval;
1136 }
1137 
SetPolygon(const basegfx::B2DPolyPolygon & rNew)1138 void SvxShapePolyPolygon::SetPolygon(const basegfx::B2DPolyPolygon& rNew)
1139 {
1140     ::SolarMutexGuard aGuard;
1141 
1142     if(HasSdrObject())
1143         static_cast<SdrPathObj*>(GetSdrObject())->SetPathPoly(rNew);
1144 }
1145 
1146 
GetPolygon() const1147 basegfx::B2DPolyPolygon SvxShapePolyPolygon::GetPolygon() const noexcept
1148 {
1149     ::SolarMutexGuard aGuard;
1150 
1151     if(HasSdrObject())
1152     {
1153         return static_cast<SdrPathObj*>(GetSdrObject())->GetPathPoly();
1154     }
1155     else
1156     {
1157         return basegfx::B2DPolyPolygon();
1158     }
1159 }
1160 
1161 //////////////////////////////////////////////////////////////////////////////
1162 
SvxGraphicObject(SdrObject * pObj)1163 SvxGraphicObject::SvxGraphicObject(SdrObject* pObj)
1164     : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_GRAPHICOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_GRAPHICOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
1165 {
1166 }
1167 
~SvxGraphicObject()1168 SvxGraphicObject::~SvxGraphicObject() noexcept
1169 {
1170 }
1171 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)1172 bool SvxGraphicObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
1173 {
1174     bool bOk = false;
1175     switch( pProperty->nWID )
1176     {
1177     case OWN_ATTR_VALUE_FILLBITMAP:
1178     {
1179         if( auto pSeq = o3tl::tryAccess<uno::Sequence<sal_Int8>>(rValue) )
1180         {
1181             SvMemoryStream  aMemStm;
1182             Graphic         aGraphic;
1183 
1184             aMemStm.SetBuffer( const_cast<css::uno::Sequence<sal_Int8> *>(pSeq)->getArray(), pSeq->getLength(), pSeq->getLength() );
1185 
1186             if( GraphicConverter::Import( aMemStm, aGraphic ) == ERRCODE_NONE )
1187             {
1188                 static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic);
1189                 bOk = true;
1190             }
1191         }
1192         else if (rValue.getValueType() == cppu::UnoType<graphic::XGraphic>::get())
1193         {
1194             auto xGraphic = rValue.get<uno::Reference<graphic::XGraphic>>();
1195             if (xGraphic.is())
1196             {
1197                 static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(Graphic(xGraphic));
1198                 bOk = true;
1199             }
1200         }
1201         else if (rValue.getValueType() == cppu::UnoType<awt::XBitmap>::get())
1202         {
1203             auto xBitmap = rValue.get<uno::Reference<awt::XBitmap>>();
1204             if (xBitmap.is())
1205             {
1206                 uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY);
1207                 Graphic aGraphic(xGraphic);
1208                 static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic);
1209                 bOk = true;
1210             }
1211         }
1212         break;
1213     }
1214 
1215     case OWN_ATTR_GRAFSTREAMURL:
1216     {
1217         OUString aStreamURL;
1218 
1219         if( rValue >>= aStreamURL )
1220         {
1221             if( !aStreamURL.startsWith( UNO_NAME_GRAPHOBJ_URLPKGPREFIX ) )
1222                 aStreamURL.clear();
1223 
1224             if( HasSdrObject() )
1225             {
1226                 static_cast<SdrGrafObj*>(GetSdrObject())->SetGrafStreamURL( aStreamURL );
1227             }
1228             bOk = true;
1229         }
1230         break;
1231     }
1232 
1233     case OWN_ATTR_GRAPHIC_URL:
1234     {
1235         OUString aURL;
1236         uno::Reference<awt::XBitmap> xBitmap;
1237         if (rValue >>= aURL)
1238         {
1239             Graphic aGraphic = vcl::graphic::loadFromURL(aURL);
1240             if (!aGraphic.IsNone())
1241             {
1242                 static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic);
1243                 bOk = true;
1244             }
1245         }
1246         else if (rValue >>= xBitmap)
1247         {
1248             uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY);
1249             if (xGraphic.is())
1250             {
1251                 Graphic aGraphic = xGraphic;
1252                 if (!aGraphic.IsNone())
1253                 {
1254                     static_cast<SdrGrafObj*>(GetSdrObject())->SetGraphic(aGraphic);
1255                     bOk = true;
1256                 }
1257             }
1258         }
1259         break;
1260     }
1261 
1262     case OWN_ATTR_VALUE_GRAPHIC:
1263     {
1264         Reference< graphic::XGraphic > xGraphic( rValue, uno::UNO_QUERY );
1265         if( xGraphic.is() )
1266         {
1267             static_cast< SdrGrafObj*>( GetSdrObject() )->SetGraphic( xGraphic );
1268             bOk = true;
1269         }
1270         break;
1271     }
1272 
1273     case OWN_ATTR_IS_SIGNATURELINE:
1274     {
1275         bool bIsSignatureLine;
1276         if (rValue >>= bIsSignatureLine)
1277         {
1278             static_cast<SdrGrafObj*>(GetSdrObject())->setIsSignatureLine(bIsSignatureLine);
1279             bOk = true;
1280         }
1281         break;
1282     }
1283 
1284     case OWN_ATTR_SIGNATURELINE_ID:
1285     {
1286         OUString aSignatureLineId;
1287         if (rValue >>= aSignatureLineId)
1288         {
1289             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineId(aSignatureLineId);
1290             bOk = true;
1291         }
1292         break;
1293     }
1294 
1295     case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_NAME:
1296     {
1297         OUString aSuggestedSignerName;
1298         if (rValue >>= aSuggestedSignerName)
1299         {
1300             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSuggestedSignerName(aSuggestedSignerName);
1301             bOk = true;
1302         }
1303         break;
1304     }
1305 
1306     case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_TITLE:
1307     {
1308         OUString aSuggestedSignerTitle;
1309         if (rValue >>= aSuggestedSignerTitle)
1310         {
1311             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSuggestedSignerTitle(aSuggestedSignerTitle);
1312             bOk = true;
1313         }
1314         break;
1315     }
1316 
1317     case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_EMAIL:
1318     {
1319         OUString aSuggestedSignerEmail;
1320         if (rValue >>= aSuggestedSignerEmail)
1321         {
1322             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSuggestedSignerEmail(aSuggestedSignerEmail);
1323             bOk = true;
1324         }
1325         break;
1326     }
1327 
1328     case OWN_ATTR_SIGNATURELINE_SIGNING_INSTRUCTIONS:
1329     {
1330         OUString aSigningInstructions;
1331         if (rValue >>= aSigningInstructions)
1332         {
1333             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineSigningInstructions(aSigningInstructions);
1334             bOk = true;
1335         }
1336         break;
1337     }
1338 
1339     case OWN_ATTR_SIGNATURELINE_SHOW_SIGN_DATE:
1340     {
1341         bool bShowSignDate;
1342         if (rValue >>= bShowSignDate)
1343         {
1344             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineShowSignDate(bShowSignDate);
1345             bOk = true;
1346         }
1347         break;
1348     }
1349 
1350     case OWN_ATTR_SIGNATURELINE_CAN_ADD_COMMENT:
1351     {
1352         bool bCanAddComment;
1353         if (rValue >>= bCanAddComment)
1354         {
1355             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineCanAddComment(bCanAddComment);
1356             bOk = true;
1357         }
1358         break;
1359     }
1360 
1361     case OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE:
1362     {
1363         Reference<graphic::XGraphic> xGraphic(rValue, uno::UNO_QUERY);
1364         if (xGraphic.is())
1365         {
1366             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineUnsignedGraphic(xGraphic);
1367             bOk = true;
1368         }
1369         break;
1370     }
1371 
1372     case OWN_ATTR_SIGNATURELINE_IS_SIGNED:
1373     {
1374         bool bIsSigned;
1375         if (rValue >>= bIsSigned)
1376         {
1377             static_cast<SdrGrafObj*>(GetSdrObject())->setSignatureLineIsSigned(bIsSigned);
1378             bOk = true;
1379         }
1380         break;
1381     }
1382 
1383     case OWN_ATTR_QRCODE:
1384     {
1385         css::drawing::QRCode aQrCode;
1386         if (rValue >>= aQrCode)
1387         {
1388             static_cast<SdrGrafObj*>(GetSdrObject())->setQrCode(aQrCode);
1389             bOk = true;
1390         }
1391         break;
1392     }
1393 
1394     default:
1395         return SvxShapeText::setPropertyValueImpl( rName, pProperty, rValue );
1396     }
1397 
1398     if( !bOk )
1399         throw lang::IllegalArgumentException();
1400 
1401     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
1402 
1403     return true;
1404 }
1405 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)1406 bool SvxGraphicObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
1407 {
1408     switch( pProperty->nWID )
1409     {
1410     case OWN_ATTR_VALUE_FILLBITMAP:
1411     {
1412         const Graphic& rGraphic = static_cast<SdrGrafObj*>(GetSdrObject())->GetGraphic();
1413 
1414         if (rGraphic.GetType() != GraphicType::GdiMetafile)
1415         {
1416             uno::Reference<awt::XBitmap> xBitmap(rGraphic.GetXGraphic(), uno::UNO_QUERY);
1417             rValue <<= xBitmap;
1418         }
1419         else
1420         {
1421             SvMemoryStream aDestStrm( 65535, 65535 );
1422 
1423             ConvertGDIMetaFileToWMF( rGraphic.GetGDIMetaFile(), aDestStrm, nullptr, false );
1424             const uno::Sequence<sal_Int8> aSeq(
1425                 static_cast< const sal_Int8* >(aDestStrm.GetData()),
1426                 aDestStrm.GetEndOfData());
1427             rValue <<= aSeq;
1428         }
1429         break;
1430     }
1431 
1432     case OWN_ATTR_REPLACEMENT_GRAPHIC:
1433     {
1434         const GraphicObject* pGrafObj = static_cast< SdrGrafObj* >(GetSdrObject())->GetReplacementGraphicObject();
1435 
1436         if (pGrafObj)
1437         {
1438             rValue <<= pGrafObj->GetGraphic().GetXGraphic();
1439         }
1440 
1441         break;
1442     }
1443 
1444     case OWN_ATTR_GRAFSTREAMURL:
1445     {
1446         const OUString  aStreamURL( static_cast<SdrGrafObj*>( GetSdrObject() )->GetGrafStreamURL() );
1447         if( !aStreamURL.isEmpty() )
1448             rValue <<= aStreamURL;
1449         break;
1450     }
1451 
1452     case OWN_ATTR_GRAPHIC_URL:
1453     case OWN_ATTR_VALUE_GRAPHIC:
1454     {
1455         if (pProperty->nWID == OWN_ATTR_GRAPHIC_URL)
1456         {
1457             SAL_WARN("svx", "Getting Graphic by URL is not supported, getting it by value");
1458         }
1459 
1460         Reference<graphic::XGraphic> xGraphic;
1461         auto pSdrGraphicObject = static_cast<SdrGrafObj*>(GetSdrObject());
1462         if (pSdrGraphicObject
1463             && pSdrGraphicObject->GetGraphicObject().GetType() != GraphicType::NONE)
1464             xGraphic = pSdrGraphicObject->GetGraphic().GetXGraphic();
1465         rValue <<= xGraphic;
1466         break;
1467     }
1468 
1469     case OWN_ATTR_GRAPHIC_STREAM:
1470     {
1471         rValue <<= static_cast< SdrGrafObj* >( GetSdrObject() )->getInputStream();
1472         break;
1473     }
1474 
1475     case OWN_ATTR_IS_SIGNATURELINE:
1476     {
1477         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLine();
1478         break;
1479     }
1480 
1481     case OWN_ATTR_SIGNATURELINE_ID:
1482     {
1483         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineId();
1484         break;
1485     }
1486 
1487     case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_NAME:
1488     {
1489         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSuggestedSignerName();
1490         break;
1491     }
1492 
1493     case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_TITLE:
1494     {
1495         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSuggestedSignerTitle();
1496         break;
1497     }
1498 
1499     case OWN_ATTR_SIGNATURELINE_SUGGESTED_SIGNER_EMAIL:
1500     {
1501         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSuggestedSignerEmail();
1502         break;
1503     }
1504 
1505     case OWN_ATTR_SIGNATURELINE_SIGNING_INSTRUCTIONS:
1506     {
1507         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineSigningInstructions();
1508         break;
1509     }
1510 
1511     case OWN_ATTR_SIGNATURELINE_SHOW_SIGN_DATE:
1512     {
1513         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLineShowSignDate();
1514         break;
1515     }
1516 
1517     case OWN_ATTR_SIGNATURELINE_CAN_ADD_COMMENT:
1518     {
1519         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLineCanAddComment();
1520         break;
1521     }
1522 
1523     case OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE:
1524     {
1525         Reference<graphic::XGraphic> xGraphic(
1526             static_cast<SdrGrafObj*>(GetSdrObject())->getSignatureLineUnsignedGraphic());
1527         rValue <<= xGraphic;
1528         break;
1529     }
1530 
1531     case OWN_ATTR_SIGNATURELINE_IS_SIGNED:
1532     {
1533         rValue <<= static_cast<SdrGrafObj*>(GetSdrObject())->isSignatureLineSigned();
1534         break;
1535     }
1536 
1537     case OWN_ATTR_QRCODE:
1538     {
1539         css::drawing::QRCode* ptr = static_cast<SdrGrafObj*>(GetSdrObject())->getQrCode();
1540         if(ptr)
1541         {
1542             rValue <<= *ptr;
1543         }
1544         break;
1545     }
1546 
1547     default:
1548         return SvxShapeText::getPropertyValueImpl(rName, pProperty,rValue);
1549     }
1550 
1551     return true;
1552 }
1553 
1554 
SvxShapeCaption(SdrObject * pObj)1555 SvxShapeCaption::SvxShapeCaption(SdrObject* pObj)
1556 : SvxShapeText( pObj, getSvxMapProvider().GetMap(SVXMAP_CAPTION), getSvxMapProvider().GetPropertySet(SVXMAP_CAPTION, SdrObject::GetGlobalDrawObjectItemPool()) )
1557 {
1558 }
1559 
~SvxShapeCaption()1560 SvxShapeCaption::~SvxShapeCaption() noexcept
1561 {
1562 }
1563 
SvxCustomShape(SdrObject * pObj)1564 SvxCustomShape::SvxCustomShape(SdrObject* pObj)
1565     : SvxShapeText( pObj, getSvxMapProvider().GetMap( SVXMAP_CUSTOMSHAPE ), getSvxMapProvider().GetPropertySet(SVXMAP_CUSTOMSHAPE, SdrObject::GetGlobalDrawObjectItemPool()) )
1566 {
1567 }
1568 
~SvxCustomShape()1569 SvxCustomShape::~SvxCustomShape() noexcept
1570 {
1571 }
1572 
queryInterface(const uno::Type & rType)1573 uno::Any SAL_CALL SvxCustomShape::queryInterface( const uno::Type & rType )
1574 {
1575     return SvxShapeText::queryInterface( rType );
1576 }
1577 
queryAggregation(const uno::Type & rType)1578 uno::Any SAL_CALL SvxCustomShape::queryAggregation( const uno::Type & rType )
1579 {
1580     css::uno::Any aReturn = SvxShapeText::queryAggregation( rType );
1581     if ( !aReturn.hasValue() )
1582         aReturn = ::cppu::queryInterface(rType, static_cast<drawing::XEnhancedCustomShapeDefaulter*>(this) );
1583     return aReturn;
1584 }
1585 
getImplementationId()1586 uno::Sequence< sal_Int8 > SAL_CALL SvxCustomShape::getImplementationId()
1587 {
1588     return css::uno::Sequence<sal_Int8>();
1589 }
1590 
1591 // css::drawing::XShape
1592 
1593 
getPosition()1594 awt::Point SAL_CALL SvxCustomShape::getPosition()
1595 {
1596     ::SolarMutexGuard aGuard;
1597     if ( HasSdrObject() )
1598     {
1599         SdrAShapeObjGeoData aCustomShapeGeoData;
1600         static_cast<SdrObjCustomShape*>(GetSdrObject())->SaveGeoData( aCustomShapeGeoData );
1601 
1602         bool bMirroredX = false;
1603         bool bMirroredY = false;
1604 
1605         if ( HasSdrObject() )
1606         {
1607             bMirroredX = static_cast<SdrObjCustomShape*>(GetSdrObject())->IsMirroredX();
1608             bMirroredY = static_cast<SdrObjCustomShape*>(GetSdrObject())->IsMirroredY();
1609         }
1610         // get aRect, this is the unrotated snaprect
1611         tools::Rectangle aRect(static_cast<SdrObjCustomShape*>(GetSdrObject())->GetLogicRect());
1612         tools::Rectangle aRectangle( aRect );
1613 
1614         if ( bMirroredX || bMirroredY )
1615         {   // we have to retrieve the unmirrored rect
1616 
1617             GeoStat aNewGeo( aCustomShapeGeoData.aGeo );
1618             if ( bMirroredX )
1619             {
1620                 tools::Polygon aPol( Rect2Poly( aRect, aNewGeo ) );
1621                 tools::Rectangle aBoundRect( aPol.GetBoundRect() );
1622 
1623                 Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() );
1624                 Point aRef2( aRef1.X(), aRef1.Y() + 1000 );
1625                 sal_uInt16 i;
1626                 sal_uInt16 nPointCount=aPol.GetSize();
1627                 for (i=0; i<nPointCount; i++)
1628                 {
1629                     MirrorPoint(aPol[i],aRef1,aRef2);
1630                 }
1631                 // turn and move polygon
1632                 tools::Polygon aPol0(aPol);
1633                 aPol[0]=aPol0[1];
1634                 aPol[1]=aPol0[0];
1635                 aPol[2]=aPol0[3];
1636                 aPol[3]=aPol0[2];
1637                 aPol[4]=aPol0[1];
1638                 Poly2Rect(aPol,aRectangle,aNewGeo);
1639             }
1640             if ( bMirroredY )
1641             {
1642                 tools::Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) );
1643                 tools::Rectangle aBoundRect( aPol.GetBoundRect() );
1644 
1645                 Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 );
1646                 Point aRef2( aRef1.X() + 1000, aRef1.Y() );
1647                 sal_uInt16 i;
1648                 sal_uInt16 nPointCount=aPol.GetSize();
1649                 for (i=0; i<nPointCount; i++)
1650                 {
1651                     MirrorPoint(aPol[i],aRef1,aRef2);
1652                 }
1653                 // turn and move polygon
1654                 tools::Polygon aPol0(aPol);
1655                 aPol[0]=aPol0[1];
1656                 aPol[1]=aPol0[0];
1657                 aPol[2]=aPol0[3];
1658                 aPol[3]=aPol0[2];
1659                 aPol[4]=aPol0[1];
1660                 Poly2Rect( aPol, aRectangle, aNewGeo );
1661             }
1662         }
1663         Point aPt( aRectangle.TopLeft() );
1664 
1665         if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() )
1666             aPt -= GetSdrObject()->GetAnchorPos();
1667 
1668         ForceMetricTo100th_mm(aPt);
1669         return css::awt::Point( aPt.X(), aPt.Y() );
1670     }
1671     else
1672         return SvxShape::getPosition();
1673 }
1674 
1675 
setPropertyValue(const OUString & aPropertyName,const uno::Any & aValue)1676 void SAL_CALL SvxCustomShape::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
1677 {
1678     ::SolarMutexGuard aGuard;
1679 
1680     SdrObject* pObject = GetSdrObject();
1681 
1682     // tdf#98163 Use a custom slot to have filter code flush the UNO
1683     // API implementations of SdrObjCustomShape. Used e.g. by
1684     // ~SdXMLCustomShapeContext, see there for more information
1685     if("FlushCustomShapeUnoApiObjects" == aPropertyName)
1686     {
1687         SdrObjCustomShape* pTarget = dynamic_cast< SdrObjCustomShape* >(pObject);
1688         if(pTarget)
1689         {
1690             // Luckily, the object causing problems in tdf#93994 is not the
1691             // UNO API object, but the XCustomShapeEngine involved. This
1692             // object is on-demand replaceable and can be reset here. This
1693             // will free the involved EditEngine and VirtualDevice.
1694             pTarget->mxCustomShapeEngine.set(nullptr);
1695         }
1696         // since this case is only for the application cores
1697         // we should return from this function now
1698         return;
1699     }
1700 
1701     bool bCustomShapeGeometry = pObject && aPropertyName == "CustomShapeGeometry";
1702 
1703     bool bMirroredX = false;
1704     bool bMirroredY = false;
1705 
1706     if ( bCustomShapeGeometry )
1707     {
1708         bMirroredX = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredX();
1709         bMirroredY = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredY();
1710     }
1711 
1712     SvxShape::setPropertyValue( aPropertyName, aValue );
1713 
1714     if ( !bCustomShapeGeometry )
1715         return;
1716 
1717     static_cast<SdrObjCustomShape*>(pObject)->MergeDefaultAttributes();
1718     tools::Rectangle aRect( pObject->GetSnapRect() );
1719 
1720     // #i38892#
1721     bool bNeedsMirrorX = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredX() != bMirroredX;
1722     bool bNeedsMirrorY = static_cast<SdrObjCustomShape*>(pObject)->IsMirroredY() != bMirroredY;
1723 
1724     std::unique_ptr< SdrGluePointList > pListCopy;
1725     if( bNeedsMirrorX || bNeedsMirrorY )
1726     {
1727         const SdrGluePointList* pList = pObject->GetGluePointList();
1728         if( pList )
1729             pListCopy.reset( new SdrGluePointList(*pList) );
1730     }
1731 
1732     if ( bNeedsMirrorX )
1733     {
1734         Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
1735         Point aBottom( aTop.X(), aTop.Y() + 1000 );
1736         pObject->NbcMirror( aTop, aBottom );
1737         // NbcMirroring is flipping the current mirror state,
1738         // so we have to set the correct state again
1739         static_cast<SdrObjCustomShape*>(pObject)->SetMirroredX( !bMirroredX );
1740     }
1741     if ( bNeedsMirrorY )
1742     {
1743         Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
1744         Point aRight( aLeft.X() + 1000, aLeft.Y() );
1745         pObject->NbcMirror( aLeft, aRight );
1746         // NbcMirroring is flipping the current mirror state,
1747         // so we have to set the correct state again
1748         static_cast<SdrObjCustomShape*>(pObject)->SetMirroredY( !bMirroredY );
1749     }
1750 
1751     if( pListCopy )
1752     {
1753         SdrGluePointList* pNewList = const_cast< SdrGluePointList* >( pObject->GetGluePointList() );
1754         if(pNewList)
1755             *pNewList = *pListCopy;
1756     }
1757 }
1758 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)1759 bool SvxCustomShape::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
1760 {
1761     switch( pProperty->nWID )
1762     {
1763     case SDRATTR_ROTATEANGLE:
1764     {
1765         double fAngle = static_cast<SdrObjCustomShape*>(GetSdrObject())->GetObjectRotation();
1766         fAngle *= 100;
1767         rValue <<= static_cast<sal_Int32>(fAngle);
1768         return true;
1769     }
1770     default:
1771         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
1772     }
1773 }
1774 
createCustomShapeDefaults(const OUString & rValueType)1775 void SvxCustomShape::createCustomShapeDefaults( const OUString& rValueType )
1776 {
1777     if (!HasSdrObject())
1778     {
1779         OSL_FAIL("could not create Custom Shape Defaults!");
1780         return;
1781     }
1782 
1783     static_cast<SdrObjCustomShape*>(GetSdrObject())->MergeDefaultAttributes( &rValueType );
1784 }
1785 
1786 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1787