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 <initializer_list>
23 #include <string_view>
24 
25 #include <com/sun/star/drawing/HomogenMatrix.hpp>
26 #include <com/sun/star/drawing/Position3D.hpp>
27 #include <com/sun/star/drawing/Direction3D.hpp>
28 #include <com/sun/star/drawing/DoubleSequence.hpp>
29 #include <com/sun/star/drawing/CameraGeometry.hpp>
30 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
31 #include <o3tl/safeint.hxx>
32 #include <vcl/svapp.hxx>
33 #include <comphelper/sequence.hxx>
34 #include <sal/log.hxx>
35 
36 #include <svx/svdpool.hxx>
37 #include <svx/svditer.hxx>
38 #include <svx/unoshape.hxx>
39 #include <svx/unopage.hxx>
40 #include <svx/cube3d.hxx>
41 #include <svx/sphere3d.hxx>
42 #include <svx/lathe3d.hxx>
43 #include <extrud3d.hxx>
44 #include <polygn3d.hxx>
45 #include <svx/unoshprp.hxx>
46 #include <svx/svdmodel.hxx>
47 #include <svx/scene3d.hxx>
48 #include <basegfx/polygon/b3dpolygon.hxx>
49 #include <basegfx/polygon/b3dpolygontools.hxx>
50 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
51 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <basegfx/matrix/b3dhommatrixtools.hxx>
53 #include "shapeimpl.hxx"
54 
55 using namespace ::cppu;
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::container;
60 
61 #define QUERYINT( xint ) \
62     if( rType == cppu::UnoType<xint>::get() ) \
63         aAny <<= Reference< xint >(this)
64 
Svx3DSceneObject(SdrObject * pObj,SvxDrawPage * pDrawPage)65 Svx3DSceneObject::Svx3DSceneObject(SdrObject* pObj, SvxDrawPage* pDrawPage)
66 :   SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DSCENEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DSCENEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
67 ,   mxPage( pDrawPage )
68 {
69 }
70 
71 
~Svx3DSceneObject()72 Svx3DSceneObject::~Svx3DSceneObject() noexcept
73 {
74 }
75 
76 
Create(SdrObject * pNewObj,SvxDrawPage * pNewPage)77 void Svx3DSceneObject::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage )
78 {
79     SvxShape::Create( pNewObj, pNewPage );
80     mxPage = pNewPage;
81 }
82 
83 
queryAggregation(const uno::Type & rType)84 uno::Any SAL_CALL Svx3DSceneObject::queryAggregation( const uno::Type & rType )
85 {
86     uno::Any aAny;
87 
88     QUERYINT( drawing::XShapes );
89     else QUERYINT( container::XIndexAccess );
90     else QUERYINT( container::XElementAccess );
91     else
92         return SvxShape::queryAggregation( rType );
93 
94     return aAny;
95 }
96 
queryInterface(const uno::Type & rType)97 uno::Any SAL_CALL Svx3DSceneObject::queryInterface( const uno::Type & rType )
98 {
99     return SvxShape::queryInterface( rType );
100 }
101 
102 // XTypeProvider
103 
getImplementationId()104 uno::Sequence< sal_Int8 > SAL_CALL Svx3DSceneObject::getImplementationId()
105 {
106     return css::uno::Sequence<sal_Int8>();
107 }
108 
109 
add(const Reference<drawing::XShape> & xShape)110 void SAL_CALL Svx3DSceneObject::add( const Reference< drawing::XShape >& xShape )
111 {
112     SolarMutexGuard aGuard;
113 
114     SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
115 
116     if(!HasSdrObject() || !mxPage.is() || pShape == nullptr || nullptr != pShape->GetSdrObject() )
117         throw uno::RuntimeException();
118 
119     SdrObject* pSdrShape = mxPage->CreateSdrObject_( xShape );
120     if( dynamic_cast<const E3dObject* >(pSdrShape) !=  nullptr )
121     {
122         GetSdrObject()->GetSubList()->NbcInsertObject( pSdrShape );
123         pShape->Create(pSdrShape, mxPage.get());
124     }
125     else
126     {
127         SdrObject::Free( pSdrShape );
128         throw uno::RuntimeException();
129     }
130 
131     GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
132 }
133 
134 
remove(const Reference<drawing::XShape> & xShape)135 void SAL_CALL Svx3DSceneObject::remove( const Reference< drawing::XShape >& xShape )
136 {
137     SolarMutexGuard aGuard;
138 
139     SdrObject* pSdrShape = SdrObject::getSdrObjectFromXShape( xShape );
140 
141     if(!HasSdrObject() || !pSdrShape ||
142         pSdrShape->getParentSdrObjectFromSdrObject() != GetSdrObject())
143         throw uno::RuntimeException();
144 
145     SdrObjList& rList = *pSdrShape->getParentSdrObjListFromSdrObject();
146 
147     const size_t nObjCount = rList.GetObjCount();
148     size_t nObjNum = 0;
149     while( nObjNum < nObjCount )
150     {
151         if(rList.GetObj( nObjNum ) == pSdrShape )
152             break;
153         nObjNum++;
154     }
155 
156     if( nObjNum < nObjCount )
157     {
158         SdrObject* pObject = rList.NbcRemoveObject( nObjNum );
159         SdrObject::Free( pObject );
160     }
161     else
162     {
163         SAL_WARN( "svx", "Fatality! SdrObject is not belonging to its SdrObjList! [CL]" );
164     }
165 }
166 
167 
getCount()168 sal_Int32 SAL_CALL Svx3DSceneObject::getCount()
169 {
170     SolarMutexGuard aGuard;
171 
172     sal_Int32 nRetval = 0;
173 
174     if(HasSdrObject() && dynamic_cast<const E3dScene* >(GetSdrObject()) != nullptr && GetSdrObject()->GetSubList())
175         nRetval = GetSdrObject()->GetSubList()->GetObjCount();
176     return nRetval;
177 }
178 
179 
getByIndex(sal_Int32 Index)180 uno::Any SAL_CALL Svx3DSceneObject::getByIndex( sal_Int32 Index )
181 {
182     SolarMutexGuard aGuard;
183 
184     if( !HasSdrObject() || GetSdrObject()->GetSubList() == nullptr )
185         throw uno::RuntimeException();
186 
187     if( Index<0 || GetSdrObject()->GetSubList()->GetObjCount() <= o3tl::make_unsigned(Index) )
188         throw lang::IndexOutOfBoundsException();
189 
190     SdrObject* pDestObj = GetSdrObject()->GetSubList()->GetObj( Index );
191     if(pDestObj == nullptr)
192         throw lang::IndexOutOfBoundsException();
193 
194     Reference< drawing::XShape > xShape( pDestObj->getUnoShape(), uno::UNO_QUERY );
195     return uno::Any(xShape);
196 }
197 
198 
199 // css::container::XElementAccess
200 
getElementType()201 uno::Type SAL_CALL Svx3DSceneObject::getElementType()
202 {
203     return cppu::UnoType<drawing::XShape>::get();
204 }
205 
206 
hasElements()207 sal_Bool SAL_CALL Svx3DSceneObject::hasElements()
208 {
209     SolarMutexGuard aGuard;
210 
211     return HasSdrObject() && GetSdrObject()->GetSubList() && (GetSdrObject()->GetSubList()->GetObjCount() > 0);
212 }
213 
214 
ConvertHomogenMatrixToObject(E3dObject * pObject,const Any & rValue)215 static bool ConvertHomogenMatrixToObject( E3dObject* pObject, const Any& rValue )
216 {
217     drawing::HomogenMatrix aMat;
218     if( rValue >>= aMat )
219     {
220         pObject->SetTransform(basegfx::utils::UnoHomogenMatrixToB3DHomMatrix(aMat));
221         return true;
222     }
223     return false;
224 }
225 
ConvertObjectToHomogenMatric(E3dObject const * pObject,Any & rValue)226 static void ConvertObjectToHomogenMatric( E3dObject const * pObject, Any& rValue )
227 {
228     drawing::HomogenMatrix aHomMat;
229     const basegfx::B3DHomMatrix& rMat = pObject->GetTransform();
230     basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(rMat, aHomMat);
231     rValue <<= aHomMat;
232 }
233 
234 namespace {
235 
236 struct ImpRememberTransAndRect
237 {
238     basegfx::B3DHomMatrix                   maMat;
239     tools::Rectangle                   maRect;
240 };
241 
242 }
243 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)244 bool Svx3DSceneObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
245 {
246     switch( pProperty->nWID )
247     {
248     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
249     {
250         // patch transformation matrix to the object
251         if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) )
252             return true;
253         break;
254     }
255     case OWN_ATTR_3D_VALUE_CAMERA_GEOMETRY:
256     {
257         // set CameraGeometry at scene
258         E3dScene* pScene = static_cast< E3dScene* >( GetSdrObject() );
259         drawing::CameraGeometry aCamGeo;
260 
261         if(rValue >>= aCamGeo)
262         {
263             basegfx::B3DPoint aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ);
264             basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ);
265             basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ);
266 
267             // rescue scene transformation
268             ImpRememberTransAndRect aSceneTAR;
269             aSceneTAR.maMat = pScene->GetTransform();
270             aSceneTAR.maRect = pScene->GetSnapRect();
271 
272             // rescue object transformations
273             SdrObjListIter aIter(pScene->GetSubList(), SdrIterMode::DeepWithGroups);
274             std::vector<basegfx::B3DHomMatrix*> aObjTrans;
275             while(aIter.IsMore())
276             {
277                 E3dObject* p3DObj = static_cast<E3dObject*>(aIter.Next());
278                 basegfx::B3DHomMatrix* pNew = new basegfx::B3DHomMatrix;
279                 *pNew = p3DObj->GetTransform();
280                 aObjTrans.push_back(pNew);
281             }
282 
283             // reset object transformations
284             aIter.Reset();
285             while(aIter.IsMore())
286             {
287                 E3dObject* p3DObj = static_cast<E3dObject*>(aIter.Next());
288                 p3DObj->NbcSetTransform(basegfx::B3DHomMatrix());
289             }
290 
291             // reset scene transformation and make a complete recalc
292             pScene->NbcSetTransform(basegfx::B3DHomMatrix());
293 
294             // fill old camera from new parameters
295             Camera3D aCam(pScene->GetCamera());
296             const basegfx::B3DRange& rVolume = pScene->GetBoundVolume();
297             double fW = rVolume.getWidth();
298             double fH = rVolume.getHeight();
299 
300             const SfxItemSet& rSceneSet = pScene->GetMergedItemSet();
301             double fCamPosZ =
302                 static_cast<double>(rSceneSet.Get(SDRATTR_3DSCENE_DISTANCE).GetValue());
303             double fCamFocal =
304                 static_cast<double>(rSceneSet.Get(SDRATTR_3DSCENE_FOCAL_LENGTH).GetValue());
305 
306             aCam.SetAutoAdjustProjection(false);
307             aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
308             basegfx::B3DPoint aLookAt;
309             basegfx::B3DPoint aCamPos(0.0, 0.0, fCamPosZ);
310             aCam.SetPosAndLookAt(aCamPos, aLookAt);
311             aCam.SetFocalLength(fCamFocal / 100.0);
312             aCam.SetDeviceWindow(tools::Rectangle(0, 0, static_cast<tools::Long>(fW), static_cast<tools::Long>(fH)));
313 
314             // set at scene
315             pScene->SetCamera(aCam);
316 
317             // #91047# use imported VRP, VPN and VUP (if used)
318             bool bVRPUsed(!aVRP.equal(basegfx::B3DPoint(0.0, 0.0, 1.0)));
319             bool bVPNUsed(!aVPN.equal(basegfx::B3DVector(0.0, 0.0, 1.0)));
320             bool bVUPUsed(!aVUP.equal(basegfx::B3DVector(0.0, 1.0, 0.0)));
321 
322             if(bVRPUsed || bVPNUsed || bVUPUsed)
323             {
324                 pScene->GetCameraSet().SetViewportValues(aVRP, aVPN, aVUP);
325             }
326 
327             // set object transformations again at objects
328             aIter.Reset();
329             sal_uInt32 nIndex(0);
330             while(aIter.IsMore())
331             {
332                 E3dObject* p3DObj = static_cast<E3dObject*>(aIter.Next());
333                 basegfx::B3DHomMatrix* pMat = aObjTrans[nIndex++];
334                 p3DObj->NbcSetTransform(*pMat);
335                 delete pMat;
336             }
337 
338             // set scene transformation again at scene
339             pScene->NbcSetTransform(aSceneTAR.maMat);
340             pScene->NbcSetSnapRect(aSceneTAR.maRect);
341 
342             return true;
343         }
344         break;
345     }
346     default:
347         return SvxShape::setPropertyValueImpl(rName, pProperty, rValue);
348     }
349 
350     throw IllegalArgumentException();
351 }
352 
353 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)354 bool Svx3DSceneObject::getPropertyValueImpl(const OUString& rName, const SfxItemPropertyMapEntry* pProperty,
355     css::uno::Any& rValue)
356 {
357     switch( pProperty->nWID )
358     {
359     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
360     {
361         // patch object to a homogeneous 4x4 matrix
362         ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue );
363         break;
364     }
365     case OWN_ATTR_3D_VALUE_CAMERA_GEOMETRY:
366     {
367         // get CameraGeometry from scene
368         E3dScene* pScene = static_cast< E3dScene* >( GetSdrObject() );
369         drawing::CameraGeometry aCamGeo;
370 
371         // fill Vectors from scene camera
372         B3dCamera& aCameraSet = pScene->GetCameraSet();
373         basegfx::B3DPoint aVRP(aCameraSet.GetVRP());
374         basegfx::B3DVector aVPN(aCameraSet.GetVPN());
375         basegfx::B3DVector aVUP(aCameraSet.GetVUV());
376 
377         // transfer to structure
378         aCamGeo.vrp.PositionX = aVRP.getX();
379         aCamGeo.vrp.PositionY = aVRP.getY();
380         aCamGeo.vrp.PositionZ = aVRP.getZ();
381         aCamGeo.vpn.DirectionX = aVPN.getX();
382         aCamGeo.vpn.DirectionY = aVPN.getY();
383         aCamGeo.vpn.DirectionZ = aVPN.getZ();
384         aCamGeo.vup.DirectionX = aVUP.getX();
385         aCamGeo.vup.DirectionY = aVUP.getY();
386         aCamGeo.vup.DirectionZ = aVUP.getZ();
387 
388         rValue <<= aCamGeo;
389         break;
390     }
391     default:
392         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
393     }
394 
395     return true;
396 }
397 
398 // css::lang::XServiceInfo
getSupportedServiceNames()399 uno::Sequence< OUString > SAL_CALL Svx3DSceneObject::getSupportedServiceNames()
400 {
401     return comphelper::concatSequences(
402         SvxShape::getSupportedServiceNames(),
403         std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3DScene" });
404 }
405 
Svx3DCubeObject(SdrObject * pObj)406 Svx3DCubeObject::Svx3DCubeObject(SdrObject* pObj)
407 :   SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DCUBEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DCUBEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
408 {
409 }
410 
~Svx3DCubeObject()411 Svx3DCubeObject::~Svx3DCubeObject() noexcept
412 {
413 }
414 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)415 bool Svx3DCubeObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
416 {
417     SolarMutexGuard aGuard;
418 
419     switch( pProperty->nWID )
420     {
421     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
422     {
423         // pack transformationmatrix to the object
424         if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) )
425             return true;
426         break;
427     }
428     case OWN_ATTR_3D_VALUE_POSITION:
429     {
430         // pack position to the object
431         drawing::Position3D aUnoPos;
432         if( rValue >>= aUnoPos )
433         {
434             basegfx::B3DPoint aPos(aUnoPos.PositionX, aUnoPos.PositionY, aUnoPos.PositionZ);
435             static_cast< E3dCubeObj* >( GetSdrObject() )->SetCubePos(aPos);
436             return true;
437         }
438         break;
439     }
440     case OWN_ATTR_3D_VALUE_SIZE:
441     {
442         // pack size to the object
443         drawing::Direction3D aDirection;
444         if( rValue >>= aDirection )
445         {
446             basegfx::B3DVector aSize(aDirection.DirectionX, aDirection.DirectionY, aDirection.DirectionZ);
447             static_cast< E3dCubeObj* >( GetSdrObject() )->SetCubeSize(aSize);
448             return true;
449         }
450         break;
451     }
452     case OWN_ATTR_3D_VALUE_POS_IS_CENTER:
453     {
454         bool bNew = false;
455         // pack sal_Bool bPosIsCenter to the object
456         if( rValue >>= bNew )
457         {
458             static_cast< E3dCubeObj* >( GetSdrObject() )->SetPosIsCenter(bNew);
459             return true;
460         }
461         break;
462     }
463     default:
464         return SvxShape::setPropertyValueImpl( rName, pProperty, rValue );
465     }
466 
467     throw IllegalArgumentException();
468 }
469 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)470 bool Svx3DCubeObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
471 {
472     switch( pProperty->nWID )
473     {
474     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
475     {
476         // pack transformation to a homogeneous matrix
477         ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue );
478         break;
479     }
480     case OWN_ATTR_3D_VALUE_POSITION:
481     {
482         // pack position
483         const basegfx::B3DPoint& rPos = static_cast<E3dCubeObj*>(GetSdrObject())->GetCubePos();
484         drawing::Position3D aPos;
485 
486         aPos.PositionX = rPos.getX();
487         aPos.PositionY = rPos.getY();
488         aPos.PositionZ = rPos.getZ();
489 
490         rValue <<= aPos;
491         break;
492     }
493     case OWN_ATTR_3D_VALUE_SIZE:
494     {
495         // pack size
496         const basegfx::B3DVector& rSize = static_cast<E3dCubeObj*>(GetSdrObject())->GetCubeSize();
497         drawing::Direction3D aDir;
498 
499         aDir.DirectionX = rSize.getX();
500         aDir.DirectionY = rSize.getY();
501         aDir.DirectionZ = rSize.getZ();
502 
503         rValue <<= aDir;
504         break;
505     }
506     case OWN_ATTR_3D_VALUE_POS_IS_CENTER:
507     {
508         rValue <<= static_cast<E3dCubeObj*>(GetSdrObject())->GetPosIsCenter();
509         break;
510     }
511     default:
512         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
513     }
514 
515     return true;
516 }
517 
518 // css::lang::XServiceInfo
getSupportedServiceNames()519 uno::Sequence< OUString > SAL_CALL Svx3DCubeObject::getSupportedServiceNames()
520 {
521     return comphelper::concatSequences(
522         SvxShape::getSupportedServiceNames(),
523         std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D",
524                                           u"com.sun.star.drawing.Shape3DCube" });
525 }
526 
Svx3DSphereObject(SdrObject * pObj)527 Svx3DSphereObject::Svx3DSphereObject(SdrObject* pObj)
528     : SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DSPHEREOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DSPHEREOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
529 {
530 }
531 
~Svx3DSphereObject()532 Svx3DSphereObject::~Svx3DSphereObject() noexcept
533 {
534 }
535 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)536 bool Svx3DSphereObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
537 {
538     switch( pProperty->nWID )
539     {
540     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
541     {
542         // pack transformation matrix to the object
543         if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) )
544             return true;
545         break;
546     }
547 
548     case OWN_ATTR_3D_VALUE_POSITION:
549     {
550         // pack position to the object
551         drawing::Position3D aUnoPos;
552         if( rValue >>= aUnoPos )
553         {
554             basegfx::B3DPoint aPos(aUnoPos.PositionX, aUnoPos.PositionY, aUnoPos.PositionZ);
555             static_cast<E3dSphereObj*>(GetSdrObject())->SetCenter(aPos);
556             return true;
557         }
558         break;
559     }
560 
561     case OWN_ATTR_3D_VALUE_SIZE:
562     {
563         // pack size to the object
564         drawing::Direction3D aDir;
565         if( rValue >>= aDir )
566         {
567             basegfx::B3DVector aPos(aDir.DirectionX, aDir.DirectionY, aDir.DirectionZ);
568             static_cast<E3dSphereObj*>(GetSdrObject())->SetSize(aPos);
569             return true;
570         }
571         break;
572     }
573     default:
574         return SvxShape::setPropertyValueImpl( rName, pProperty, rValue );
575     }
576 
577     throw IllegalArgumentException();
578 }
579 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)580 bool Svx3DSphereObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
581 {
582     switch( pProperty->nWID )
583     {
584     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
585     {
586         // pack transformation to a homogeneous matrix
587         ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue );
588         break;
589     }
590     case OWN_ATTR_3D_VALUE_POSITION:
591     {
592         // pack position
593         const basegfx::B3DPoint& rPos = static_cast<E3dSphereObj*>(GetSdrObject())->Center();
594         drawing::Position3D aPos;
595 
596         aPos.PositionX = rPos.getX();
597         aPos.PositionY = rPos.getY();
598         aPos.PositionZ = rPos.getZ();
599 
600         rValue <<= aPos;
601         break;
602     }
603     case OWN_ATTR_3D_VALUE_SIZE:
604     {
605         // pack size
606         const basegfx::B3DVector& rSize = static_cast<E3dSphereObj*>(GetSdrObject())->Size();
607         drawing::Direction3D aDir;
608 
609         aDir.DirectionX = rSize.getX();
610         aDir.DirectionY = rSize.getY();
611         aDir.DirectionZ = rSize.getZ();
612 
613         rValue <<= aDir;
614         break;
615     }
616     default:
617         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
618     }
619 
620     return true;
621 }
622 
623 // css::lang::XServiceInfo
getSupportedServiceNames()624 uno::Sequence< OUString > SAL_CALL Svx3DSphereObject::getSupportedServiceNames()
625 {
626     return comphelper::concatSequences(
627         SvxShape::getSupportedServiceNames(),
628         std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D",
629                                           u"com.sun.star.drawing.Shape3DSphere" });
630 }
631 
Svx3DLatheObject(SdrObject * pObj)632 Svx3DLatheObject::Svx3DLatheObject(SdrObject* pObj)
633 :   SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DLATHEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DLATHEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
634 {
635 }
636 
~Svx3DLatheObject()637 Svx3DLatheObject::~Svx3DLatheObject() noexcept
638 {
639 }
640 
PolyPolygonShape3D_to_B3dPolyPolygon(const Any & rValue,basegfx::B3DPolyPolygon & rResultPolygon,bool bCorrectPolygon)641 static bool PolyPolygonShape3D_to_B3dPolyPolygon(
642     const Any& rValue,
643     basegfx::B3DPolyPolygon& rResultPolygon,
644     bool bCorrectPolygon)
645 {
646     drawing::PolyPolygonShape3D aSourcePolyPolygon;
647     if( !(rValue >>= aSourcePolyPolygon) )
648         return false;
649 
650     sal_Int32 nOuterSequenceCount = aSourcePolyPolygon.SequenceX.getLength();
651     if(nOuterSequenceCount != aSourcePolyPolygon.SequenceY.getLength() || nOuterSequenceCount != aSourcePolyPolygon.SequenceZ.getLength())
652         return false;
653 
654     drawing::DoubleSequence* pInnerSequenceX = aSourcePolyPolygon.SequenceX.getArray();
655     drawing::DoubleSequence* pInnerSequenceY = aSourcePolyPolygon.SequenceY.getArray();
656     drawing::DoubleSequence* pInnerSequenceZ = aSourcePolyPolygon.SequenceZ.getArray();
657     for(sal_Int32 a(0);a<nOuterSequenceCount;a++)
658     {
659         sal_Int32 nInnerSequenceCount = pInnerSequenceX->getLength();
660         if(nInnerSequenceCount != pInnerSequenceY->getLength() || nInnerSequenceCount != pInnerSequenceZ->getLength())
661         {
662             return false;
663         }
664         basegfx::B3DPolygon aNewPolygon;
665         double* pArrayX = pInnerSequenceX->getArray();
666         double* pArrayY = pInnerSequenceY->getArray();
667         double* pArrayZ = pInnerSequenceZ->getArray();
668         for(sal_Int32 b(0);b<nInnerSequenceCount;b++)
669         {
670             aNewPolygon.append(basegfx::B3DPoint(*pArrayX++,*pArrayY++,*pArrayZ++));
671         }
672         pInnerSequenceX++;
673         pInnerSequenceY++;
674         pInnerSequenceZ++;
675 
676         // #i101520# correction is needed for imported polygons of old format,
677         // see callers
678         if(bCorrectPolygon)
679         {
680             basegfx::utils::checkClosed(aNewPolygon);
681         }
682 
683         rResultPolygon.append(aNewPolygon);
684     }
685     return true;
686 }
687 
B3dPolyPolygon_to_PolyPolygonShape3D(const basegfx::B3DPolyPolygon & rSourcePolyPolygon,Any & rValue)688 static void B3dPolyPolygon_to_PolyPolygonShape3D( const basegfx::B3DPolyPolygon& rSourcePolyPolygon, Any& rValue )
689 {
690     drawing::PolyPolygonShape3D aRetval;
691     aRetval.SequenceX.realloc(rSourcePolyPolygon.count());
692     aRetval.SequenceY.realloc(rSourcePolyPolygon.count());
693     aRetval.SequenceZ.realloc(rSourcePolyPolygon.count());
694     drawing::DoubleSequence* pOuterSequenceX = aRetval.SequenceX.getArray();
695     drawing::DoubleSequence* pOuterSequenceY = aRetval.SequenceY.getArray();
696     drawing::DoubleSequence* pOuterSequenceZ = aRetval.SequenceZ.getArray();
697     for(sal_uInt32 a(0);a<rSourcePolyPolygon.count();a++)
698     {
699         const basegfx::B3DPolygon& aPoly(rSourcePolyPolygon.getB3DPolygon(a));
700         sal_Int32 nPointCount(aPoly.count());
701         if(aPoly.isClosed()) nPointCount++;
702         pOuterSequenceX->realloc(nPointCount);
703         pOuterSequenceY->realloc(nPointCount);
704         pOuterSequenceZ->realloc(nPointCount);
705         double* pInnerSequenceX = pOuterSequenceX->getArray();
706         double* pInnerSequenceY = pOuterSequenceY->getArray();
707         double* pInnerSequenceZ = pOuterSequenceZ->getArray();
708         for(sal_uInt32 b(0);b<aPoly.count();b++)
709         {
710             const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(b));
711             *pInnerSequenceX++ = aPoint.getX();
712             *pInnerSequenceY++ = aPoint.getY();
713             *pInnerSequenceZ++ = aPoint.getZ();
714         }
715         if(aPoly.isClosed())
716         {
717             const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(0));
718             *pInnerSequenceX++ = aPoint.getX();
719             *pInnerSequenceY++ = aPoint.getY();
720             *pInnerSequenceZ++ = aPoint.getZ();
721         }
722         pOuterSequenceX++;
723         pOuterSequenceY++;
724         pOuterSequenceZ++;
725     }
726     rValue <<= aRetval;
727 }
728 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)729 bool Svx3DLatheObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
730 {
731     switch( pProperty->nWID )
732     {
733     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
734     {
735         // pack transformation matrix to the object
736         if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) )
737             return true;
738         break;
739     }
740     case OWN_ATTR_3D_VALUE_POLYPOLYGON3D:
741     {
742         // pack polygon definition to the object
743         basegfx::B3DPolyPolygon aNewB3DPolyPolygon;
744 
745         // #i101520# Probably imported
746         if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, true ) )
747         {
748             // #105127# SetPolyPoly3D sets the Svx3DVerticalSegmentsItem to the number
749             // of points of the polygon. Thus, value gets lost. To avoid this, rescue
750             // item here and re-set after setting the polygon.
751             const sal_uInt32 nPrevVerticalSegs(static_cast<E3dLatheObj*>(GetSdrObject())->GetVerticalSegments());
752 
753             // set polygon
754             const basegfx::B3DHomMatrix aIdentity;
755             const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aNewB3DPolyPolygon, aIdentity));
756             static_cast<E3dLatheObj*>(GetSdrObject())->SetPolyPoly2D(aB2DPolyPolygon);
757             const sal_uInt32 nPostVerticalSegs(static_cast<E3dLatheObj*>(GetSdrObject())->GetVerticalSegments());
758 
759             if(nPrevVerticalSegs != nPostVerticalSegs)
760             {
761                 // restore the vertical segment count
762                 static_cast<E3dLatheObj*>(GetSdrObject())->SetMergedItem(makeSvx3DVerticalSegmentsItem(nPrevVerticalSegs));
763             }
764             return true;
765         }
766         break;
767     }
768     default:
769         return SvxShape::setPropertyValueImpl( rName, pProperty, rValue );
770     }
771 
772     throw IllegalArgumentException();
773 }
774 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)775 bool Svx3DLatheObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
776 {
777     switch( pProperty->nWID )
778     {
779     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
780     {
781         // pack transformation to a homogeneous matrix
782         drawing::HomogenMatrix aHomMat;
783         basegfx::B3DHomMatrix aMat = static_cast<E3dObject*>(GetSdrObject())->GetTransform();
784         basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aMat, aHomMat);
785         rValue <<= aHomMat;
786         break;
787     }
788     case OWN_ATTR_3D_VALUE_POLYPOLYGON3D:
789     {
790         const basegfx::B2DPolyPolygon& rPolyPoly = static_cast<E3dLatheObj*>(GetSdrObject())->GetPolyPoly2D();
791         const basegfx::B3DPolyPolygon aB3DPolyPolygon(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(rPolyPoly));
792 
793         B3dPolyPolygon_to_PolyPolygonShape3D(aB3DPolyPolygon, rValue);
794         break;
795     }
796     default:
797         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
798     }
799 
800     return true;
801 }
802 
803 // css::lang::XServiceInfo
getSupportedServiceNames()804 uno::Sequence< OUString > SAL_CALL Svx3DLatheObject::getSupportedServiceNames()
805 {
806     return comphelper::concatSequences(
807         SvxShape::getSupportedServiceNames(),
808         std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D",
809                                           u"com.sun.star.drawing.Shape3DLathe" });
810 }
811 
Svx3DExtrudeObject(SdrObject * pObj)812 Svx3DExtrudeObject::Svx3DExtrudeObject(SdrObject* pObj)
813 :   SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DEXTRUDEOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DEXTRUDEOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
814 {
815 }
816 
~Svx3DExtrudeObject()817 Svx3DExtrudeObject::~Svx3DExtrudeObject() noexcept
818 {
819 }
820 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)821 bool Svx3DExtrudeObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
822 {
823     switch( pProperty->nWID )
824     {
825     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
826     {
827         // pack transformation matrix to the object
828         if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) )
829             return true;
830         break;
831     }
832 
833     case OWN_ATTR_3D_VALUE_POLYPOLYGON3D:
834     {
835         // pack polygon definition to the object
836         basegfx::B3DPolyPolygon aNewB3DPolyPolygon;
837 
838         // #i101520# Probably imported
839         if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, true ) )
840         {
841             // set polygon
842             const basegfx::B3DHomMatrix aIdentity;
843             const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aNewB3DPolyPolygon, aIdentity));
844             static_cast<E3dExtrudeObj*>(GetSdrObject())->SetExtrudePolygon(aB2DPolyPolygon);
845             return true;
846         }
847         break;
848     }
849     default:
850         return SvxShape::setPropertyValueImpl( rName, pProperty, rValue );
851     }
852 
853     throw IllegalArgumentException();
854 }
855 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)856 bool Svx3DExtrudeObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
857 {
858     switch( pProperty->nWID )
859     {
860     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
861     {
862         // pack transformation to a homogeneous matrix
863         drawing::HomogenMatrix aHomMat;
864         basegfx::B3DHomMatrix aMat = static_cast<E3dObject*>(GetSdrObject())->GetTransform();
865         basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aMat, aHomMat);
866         rValue <<= aHomMat;
867         break;
868     }
869 
870     case OWN_ATTR_3D_VALUE_POLYPOLYGON3D:
871     {
872         // pack polygon definition
873         const basegfx::B2DPolyPolygon& rPolyPoly = static_cast<E3dExtrudeObj*>(GetSdrObject())->GetExtrudePolygon();
874         const basegfx::B3DPolyPolygon aB3DPolyPolygon(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(rPolyPoly));
875 
876         B3dPolyPolygon_to_PolyPolygonShape3D(aB3DPolyPolygon, rValue);
877         break;
878     }
879     default:
880         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
881     }
882 
883     return true;
884 }
885 
886 // css::lang::XServiceInfo
getSupportedServiceNames()887 uno::Sequence< OUString > SAL_CALL Svx3DExtrudeObject::getSupportedServiceNames()
888 {
889     return comphelper::concatSequences(
890         SvxShape::getSupportedServiceNames(),
891         std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D",
892                                           u"com.sun.star.drawing.Shape3DExtrude" });
893 }
894 
Svx3DPolygonObject(SdrObject * pObj)895 Svx3DPolygonObject::Svx3DPolygonObject(SdrObject* pObj)
896 :   SvxShape( pObj, getSvxMapProvider().GetMap(SVXMAP_3DPOLYGONOBJECT), getSvxMapProvider().GetPropertySet(SVXMAP_3DPOLYGONOBJECT, SdrObject::GetGlobalDrawObjectItemPool()) )
897 {
898 }
899 
~Svx3DPolygonObject()900 Svx3DPolygonObject::~Svx3DPolygonObject() noexcept
901 {
902 }
903 
setPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,const css::uno::Any & rValue)904 bool Svx3DPolygonObject::setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
905 {
906     switch( pProperty->nWID )
907     {
908     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
909     {
910         // pack transformation matrix to the object
911         if( ConvertHomogenMatrixToObject( static_cast< E3dObject* >( GetSdrObject() ), rValue ) )
912             return true;
913         break;
914     }
915 
916     case OWN_ATTR_3D_VALUE_POLYPOLYGON3D:
917     {
918         // pack polygon definition to the object
919         basegfx::B3DPolyPolygon aNewB3DPolyPolygon;
920 
921         // #i101520# Direct API data (e.g. from chart)
922         if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, false ) )
923         {
924             // set polygon
925             static_cast<E3dPolygonObj*>(GetSdrObject())->SetPolyPolygon3D(aNewB3DPolyPolygon);
926             return true;
927         }
928         break;
929     }
930     case OWN_ATTR_3D_VALUE_NORMALSPOLYGON3D:
931     {
932         // pack perpendicular definition to the object
933         basegfx::B3DPolyPolygon aNewB3DPolyPolygon;
934 
935         // #i101520# Direct API data (e.g. from chart)
936         if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, false ) )
937         {
938             // set polygon
939             static_cast<E3dPolygonObj*>(GetSdrObject())->SetPolyNormals3D(aNewB3DPolyPolygon);
940             return true;
941         }
942         break;
943     }
944     case OWN_ATTR_3D_VALUE_TEXTUREPOLYGON3D:
945     {
946         // pack texture definition to the object
947         basegfx::B3DPolyPolygon aNewB3DPolyPolygon;
948 
949         // #i101520# Direct API data (e.g. from chart)
950         if( PolyPolygonShape3D_to_B3dPolyPolygon( rValue, aNewB3DPolyPolygon, false ) )
951         {
952             // set polygon
953             const basegfx::B3DHomMatrix aIdentity;
954             const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aNewB3DPolyPolygon, aIdentity));
955             static_cast<E3dPolygonObj*>(GetSdrObject())->SetPolyTexture2D(aB2DPolyPolygon);
956             return true;
957         }
958         break;
959     }
960     case OWN_ATTR_3D_VALUE_LINEONLY:
961     {
962         bool bNew = false;
963         if( rValue >>= bNew )
964         {
965             static_cast<E3dPolygonObj*>(GetSdrObject())->SetLineOnly(bNew);
966             return true;
967         }
968         break;
969     }
970     default:
971         return SvxShape::setPropertyValueImpl( rName, pProperty, rValue );
972     }
973 
974     throw IllegalArgumentException();
975 }
976 
getPropertyValueImpl(const OUString & rName,const SfxItemPropertyMapEntry * pProperty,css::uno::Any & rValue)977 bool Svx3DPolygonObject::getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue )
978 {
979     switch( pProperty->nWID )
980     {
981     case OWN_ATTR_3D_VALUE_TRANSFORM_MATRIX:
982     {
983         ConvertObjectToHomogenMatric( static_cast< E3dObject* >( GetSdrObject() ), rValue );
984         break;
985     }
986 
987     case OWN_ATTR_3D_VALUE_POLYPOLYGON3D:
988     {
989         B3dPolyPolygon_to_PolyPolygonShape3D(static_cast<E3dPolygonObj*>(GetSdrObject())->GetPolyPolygon3D(),rValue);
990         break;
991     }
992 
993     case OWN_ATTR_3D_VALUE_NORMALSPOLYGON3D:
994     {
995         B3dPolyPolygon_to_PolyPolygonShape3D(static_cast<E3dPolygonObj*>(GetSdrObject())->GetPolyNormals3D(),rValue);
996         break;
997     }
998 
999     case OWN_ATTR_3D_VALUE_TEXTUREPOLYGON3D:
1000     {
1001         // pack texture definition
1002         const basegfx::B2DPolyPolygon& rPolyPoly = static_cast<E3dPolygonObj*>(GetSdrObject())->GetPolyTexture2D();
1003         const basegfx::B3DPolyPolygon aB3DPolyPolygon(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(rPolyPoly));
1004 
1005         B3dPolyPolygon_to_PolyPolygonShape3D(aB3DPolyPolygon,rValue);
1006         break;
1007     }
1008 
1009     case OWN_ATTR_3D_VALUE_LINEONLY:
1010     {
1011         rValue <<= static_cast<E3dPolygonObj*>(GetSdrObject())->GetLineOnly();
1012         break;
1013     }
1014 
1015     default:
1016         return SvxShape::getPropertyValueImpl( rName, pProperty, rValue );
1017     }
1018 
1019     return true;
1020 }
1021 
1022 // css::lang::XServiceInfo
getSupportedServiceNames()1023 uno::Sequence< OUString > SAL_CALL Svx3DPolygonObject::getSupportedServiceNames()
1024 {
1025     return comphelper::concatSequences(
1026         SvxShape::getSupportedServiceNames(),
1027         std::initializer_list<std::u16string_view>{ u"com.sun.star.drawing.Shape3D",
1028                                           u"com.sun.star.drawing.Shape3DPolygon" });
1029 }
1030 
1031 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1032