Bump version to 6.4-15
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShapeEngine.cxx
bloba7b08f99afc4724c0f85ca9e2e8c3407607dce92
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/uno/Reference.h>
21 #include <com/sun/star/uno/RuntimeException.hpp>
22 #include <com/sun/star/uno/XComponentContext.hpp>
23 #include <com/sun/star/awt/Rectangle.hpp>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
26 #include <com/sun/star/lang/XInitialization.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
29 #include <rtl/ref.hxx>
30 #include <svx/EnhancedCustomShape2d.hxx>
31 #include "EnhancedCustomShape3d.hxx"
32 #include "EnhancedCustomShapeFontWork.hxx"
33 #include "EnhancedCustomShapeHandle.hxx"
34 #include <svx/EnhancedCustomShapeGeometry.hxx>
35 #include <svx/unoshape.hxx>
36 #include <svx/unopage.hxx>
37 #include <svx/unoapi.hxx>
38 #include <svx/svdobj.hxx>
39 #include <svx/svdoashp.hxx>
40 #include <svx/svdogrp.hxx>
41 #include <svx/svdorect.hxx>
42 #include <editeng/outlobj.hxx>
43 #include <editeng/outliner.hxx>
44 #include <svx/svdoutl.hxx>
45 #include <svl/itemset.hxx>
46 #include <svx/svdopath.hxx>
47 #include <svx/svdpage.hxx>
48 #include <svx/svdmodel.hxx>
49 #include <svx/svditer.hxx>
50 #include <svx/xfillit0.hxx>
51 #include <svx/xlineit0.hxx>
52 #include <uno/mapping.hxx>
53 #include <basegfx/polygon/b2dpolypolygontools.hxx>
54 #include <com/sun/star/document/XActionLockable.hpp>
55 #include <cppuhelper/implbase.hxx>
56 #include <cppuhelper/supportsservice.hxx>
58 using namespace css;
59 using namespace css::uno;
61 class SdrObject;
62 class SdrObjCustomShape;
64 namespace {
66 class EnhancedCustomShapeEngine : public cppu::WeakImplHelper
68 css::lang::XInitialization,
69 css::lang::XServiceInfo,
70 css::drawing::XCustomShapeEngine
73 css::uno::Reference< css::drawing::XShape > mxShape;
74 bool mbForceGroupWithText;
76 std::unique_ptr<SdrObject, SdrObjectFreeOp> ImplForceGroupWithText(
77 const SdrObjCustomShape& rSdrObjCustomShape,
78 std::unique_ptr<SdrObject, SdrObjectFreeOp> pRenderedShape);
80 public:
81 EnhancedCustomShapeEngine();
83 // XInterface
84 virtual void SAL_CALL acquire() throw() override;
85 virtual void SAL_CALL release() throw() override;
87 // XInitialization
88 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
90 // XServiceInfo
91 virtual OUString SAL_CALL getImplementationName() override;
92 virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override;
93 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
95 // XCustomShapeEngine
96 virtual css::uno::Reference< css::drawing::XShape > SAL_CALL render() override;
97 virtual css::awt::Rectangle SAL_CALL getTextBounds() override;
98 virtual css::drawing::PolyPolygonBezierCoords SAL_CALL getLineGeometry() override;
99 virtual css::uno::Sequence< css::uno::Reference< css::drawing::XCustomShapeHandle > > SAL_CALL getInteraction() override;
102 EnhancedCustomShapeEngine::EnhancedCustomShapeEngine() :
103 mbForceGroupWithText ( false )
107 // XInterface
108 void SAL_CALL EnhancedCustomShapeEngine::acquire() throw()
110 OWeakObject::acquire();
112 void SAL_CALL EnhancedCustomShapeEngine::release() throw()
114 OWeakObject::release();
117 // XInitialization
118 void SAL_CALL EnhancedCustomShapeEngine::initialize( const Sequence< Any >& aArguments )
120 Sequence< beans::PropertyValue > aParameter;
121 for ( const auto& rArgument : aArguments )
123 if ( rArgument >>= aParameter )
124 break;
126 for ( const beans::PropertyValue& rProp : std::as_const(aParameter) )
128 if ( rProp.Name == "CustomShape" )
129 rProp.Value >>= mxShape;
130 else if ( rProp.Name == "ForceGroupWithText" )
131 rProp.Value >>= mbForceGroupWithText;
135 // XServiceInfo
136 OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName()
138 return "com.sun.star.drawing.EnhancedCustomShapeEngine";
140 sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const OUString& rServiceName )
142 return cppu::supportsService(this, rServiceName);
144 Sequence< OUString > SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames()
146 Sequence<OUString> aRet { "com.sun.star.drawing.CustomShapeEngine" };
147 return aRet;
150 // XCustomShapeEngine
151 std::unique_ptr<SdrObject, SdrObjectFreeOp> EnhancedCustomShapeEngine::ImplForceGroupWithText(
152 const SdrObjCustomShape& rSdrObjCustomShape,
153 std::unique_ptr<SdrObject, SdrObjectFreeOp> pRenderedShape)
155 const bool bHasText(rSdrObjCustomShape.HasText());
157 if ( pRenderedShape || bHasText )
159 // applying shadow
160 const SdrObject* pShadowGeometry(rSdrObjCustomShape.GetSdrObjectShadowFromCustomShape());
162 if ( pShadowGeometry )
164 if ( pRenderedShape )
166 if ( dynamic_cast<const SdrObjGroup*>( pRenderedShape.get() ) == nullptr )
168 auto pTmp = std::move(pRenderedShape);
169 pRenderedShape.reset(new SdrObjGroup(rSdrObjCustomShape.getSdrModelFromSdrObject()));
170 static_cast<SdrObjGroup*>(pRenderedShape.get())->GetSubList()->NbcInsertObject( pTmp.release() );
173 static_cast<SdrObjGroup*>(pRenderedShape.get())->GetSubList()->NbcInsertObject(
174 pShadowGeometry->CloneSdrObject(pShadowGeometry->getSdrModelFromSdrObject()),
177 else
179 pRenderedShape.reset( pShadowGeometry->CloneSdrObject(pShadowGeometry->getSdrModelFromSdrObject()) );
183 // apply text
184 if ( bHasText )
186 // #i37011# also create a text object and add at rPos + 1
187 std::unique_ptr<SdrObject, SdrObjectFreeOp> pTextObj( SdrObjFactory::MakeNewObject(
188 rSdrObjCustomShape.getSdrModelFromSdrObject(),
189 rSdrObjCustomShape.GetObjInventor(),
190 OBJ_TEXT) );
192 // Copy text content
193 OutlinerParaObject* pParaObj(rSdrObjCustomShape.GetOutlinerParaObject());
195 if( pParaObj )
196 pTextObj->NbcSetOutlinerParaObject( std::make_unique<OutlinerParaObject>(*pParaObj) );
198 // copy all attributes
199 SfxItemSet aTargetItemSet(rSdrObjCustomShape.GetMergedItemSet());
201 // clear fill and line style
202 aTargetItemSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
203 aTargetItemSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
205 // get the text bounds and set at text object
206 tools::Rectangle aTextBounds(rSdrObjCustomShape.GetSnapRect());
207 const bool bIsSdrObjCustomShape(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(mxShape)));
209 if(bIsSdrObjCustomShape)
211 SdrObjCustomShape& rSdrObjCustomShape2(
212 static_cast< SdrObjCustomShape& >(
213 *GetSdrObjectFromXShape(mxShape)));
214 EnhancedCustomShape2d aCustomShape2d(rSdrObjCustomShape2);
215 aTextBounds = aCustomShape2d.GetTextRect();
218 pTextObj->SetSnapRect( aTextBounds );
220 // if rotated, copy GeoStat, too.
221 const GeoStat& rSourceGeo(rSdrObjCustomShape.GetGeoStat());
222 if ( rSourceGeo.nRotationAngle )
224 pTextObj->NbcRotate(
225 rSdrObjCustomShape.GetSnapRect().Center(),
226 rSourceGeo.nRotationAngle,
227 rSourceGeo.nSin,
228 rSourceGeo.nCos);
231 // set modified ItemSet at text object
232 pTextObj->SetMergedItemSet(aTargetItemSet);
234 if ( pRenderedShape )
236 if ( dynamic_cast<const SdrObjGroup*>( pRenderedShape.get() ) == nullptr )
238 auto pTmp = std::move(pRenderedShape);
239 pRenderedShape.reset(new SdrObjGroup(rSdrObjCustomShape.getSdrModelFromSdrObject()));
240 static_cast<SdrObjGroup*>(pRenderedShape.get())->GetSubList()->NbcInsertObject( pTmp.release() );
242 static_cast<SdrObjGroup*>(pRenderedShape.get())->GetSubList()->NbcInsertObject( pTextObj.release() );
244 else
245 pRenderedShape = std::move(pTextObj);
248 // force group
249 if ( pRenderedShape )
251 if ( dynamic_cast<const SdrObjGroup*>( pRenderedShape.get() ) == nullptr )
253 auto pTmp = std::move(pRenderedShape);
254 pRenderedShape.reset(new SdrObjGroup(rSdrObjCustomShape.getSdrModelFromSdrObject()));
255 static_cast<SdrObjGroup*>(pRenderedShape.get())->GetSubList()->NbcInsertObject( pTmp.release() );
260 return pRenderedShape;
263 void SetTemporary( uno::Reference< drawing::XShape > const & xShape )
265 if ( xShape.is() )
267 SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
268 if ( pShape )
269 pShape->TakeSdrObjectOwnership();
273 Reference< drawing::XShape > SAL_CALL EnhancedCustomShapeEngine::render()
275 const bool bIsSdrObjCustomShape(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(mxShape)));
277 if(!bIsSdrObjCustomShape)
279 return Reference< drawing::XShape >();
282 SdrObjCustomShape& rSdrObjCustomShape(
283 static_cast< SdrObjCustomShape& >(
284 *GetSdrObjectFromXShape(mxShape)));
286 // retrieving the TextPath property to check if feature is enabled
287 const SdrCustomShapeGeometryItem& rGeometryItem(rSdrObjCustomShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
288 bool bTextPathOn = false;
289 const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "TextPath", "TextPath" );
290 if ( pAny )
291 *pAny >>= bTextPathOn;
293 EnhancedCustomShape2d aCustomShape2d(rSdrObjCustomShape);
294 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
296 bool bFlipV = aCustomShape2d.IsFlipVert();
297 bool bFlipH = aCustomShape2d.IsFlipHorz();
298 bool bLineGeometryNeededOnly = bTextPathOn;
300 std::unique_ptr<SdrObject, SdrObjectFreeOp> xRenderedShape(aCustomShape2d.CreateObject(bLineGeometryNeededOnly));
301 if (xRenderedShape)
303 if ( bTextPathOn )
305 std::unique_ptr<SdrObject, SdrObjectFreeOp> xRenderedFontWork(
306 EnhancedCustomShapeFontWork::CreateFontWork(
307 xRenderedShape.get(),
308 rSdrObjCustomShape));
310 if (xRenderedFontWork)
312 xRenderedShape = std::move(xRenderedFontWork);
315 std::unique_ptr<SdrObject, SdrObjectFreeOp> xRenderedShape3d(EnhancedCustomShape3d::Create3DObject(xRenderedShape.get(), rSdrObjCustomShape));
316 if (xRenderedShape3d)
318 bFlipV = bFlipH = false;
319 nRotateAngle = 0;
320 xRenderedShape = std::move(xRenderedShape3d);
323 tools::Rectangle aRect(rSdrObjCustomShape.GetSnapRect());
324 const GeoStat& rGeoStat(rSdrObjCustomShape.GetGeoStat());
326 if ( rGeoStat.nShearAngle )
328 long nShearAngle = rGeoStat.nShearAngle;
329 double nTan = rGeoStat.nTan;
330 if (bFlipV != bFlipH)
332 nShearAngle = -nShearAngle;
333 nTan = -nTan;
336 xRenderedShape->Shear(rSdrObjCustomShape.GetSnapRect().Center(), nShearAngle, nTan, false);
338 if(nRotateAngle )
340 double a = nRotateAngle * F_PI18000;
342 xRenderedShape->NbcRotate(rSdrObjCustomShape.GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ));
344 if ( bFlipV )
346 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
347 Point aRight( aLeft.X() + 1000, aLeft.Y() );
348 xRenderedShape->NbcMirror( aLeft, aRight );
350 if ( bFlipH )
352 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
353 Point aBottom( aTop.X(), aTop.Y() + 1000 );
354 xRenderedShape->NbcMirror( aTop, aBottom );
357 xRenderedShape->NbcSetStyleSheet(rSdrObjCustomShape.GetStyleSheet(), true);
358 xRenderedShape->RecalcSnapRect();
361 if ( mbForceGroupWithText )
363 xRenderedShape = ImplForceGroupWithText(
364 rSdrObjCustomShape,
365 std::move(xRenderedShape));
368 Reference< drawing::XShape > xShape;
370 if (xRenderedShape)
372 aCustomShape2d.ApplyGluePoints(xRenderedShape.get());
373 SdrObject* pRenderedShape = xRenderedShape.release();
374 xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(),
375 pRenderedShape->GetObjInventor(), pRenderedShape );
378 SetTemporary( xShape );
380 return xShape;
383 awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds()
385 awt::Rectangle aTextRect;
386 const bool bIsSdrObjCustomShape(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(mxShape)));
388 if(bIsSdrObjCustomShape)
390 SdrObjCustomShape& rSdrObjCustomShape(static_cast< SdrObjCustomShape& >(*GetSdrObjectFromXShape(mxShape)));
391 uno::Reference< document::XActionLockable > xLockable( mxShape, uno::UNO_QUERY );
393 if(xLockable.is() && !xLockable->isActionLocked())
395 EnhancedCustomShape2d aCustomShape2d(rSdrObjCustomShape);
396 tools::Rectangle aRect( aCustomShape2d.GetTextRect() );
397 aTextRect.X = aRect.Left();
398 aTextRect.Y = aRect.Top();
399 aTextRect.Width = aRect.GetWidth();
400 aTextRect.Height = aRect.GetHeight();
404 return aTextRect;
407 drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry()
409 drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
410 const bool bIsSdrObjCustomShape(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(mxShape)));
412 if(bIsSdrObjCustomShape)
414 SdrObjCustomShape& rSdrObjCustomShape(
415 static_cast< SdrObjCustomShape& >(
416 *GetSdrObjectFromXShape(mxShape)));
417 EnhancedCustomShape2d aCustomShape2d(rSdrObjCustomShape);
418 SdrObject* pObj = aCustomShape2d.CreateLineGeometry();
420 if ( pObj )
422 tools::Rectangle aRect(rSdrObjCustomShape.GetSnapRect());
423 bool bFlipV = aCustomShape2d.IsFlipVert();
424 bool bFlipH = aCustomShape2d.IsFlipHorz();
425 const GeoStat& rGeoStat(rSdrObjCustomShape.GetGeoStat());
427 if ( rGeoStat.nShearAngle )
429 long nShearAngle = rGeoStat.nShearAngle;
430 double nTan = rGeoStat.nTan;
431 if (bFlipV != bFlipH)
433 nShearAngle = -nShearAngle;
434 nTan = -nTan;
436 pObj->Shear( aRect.Center(), nShearAngle, nTan, false);
438 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
439 if( nRotateAngle )
441 double a = nRotateAngle * F_PI18000;
442 pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) );
444 if ( bFlipH )
446 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
447 Point aBottom( aTop.X(), aTop.Y() + 1000 );
448 pObj->NbcMirror( aTop, aBottom );
450 if ( bFlipV )
452 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
453 Point aRight( aLeft.X() + 1000, aLeft.Y() );
454 pObj->NbcMirror( aLeft, aRight );
457 basegfx::B2DPolyPolygon aPolyPolygon;
458 SdrObjListIter aIter( *pObj, SdrIterMode::DeepWithGroups );
460 while ( aIter.IsMore() )
462 basegfx::B2DPolyPolygon aPP;
463 const SdrObject* pNext = aIter.Next();
465 if ( auto pPathObj = dynamic_cast<const SdrPathObj*>(pNext) )
467 aPP = pPathObj->GetPathPoly();
469 else
471 SdrObjectUniquePtr pNewObj = pNext->ConvertToPolyObj( false, false );
472 SdrPathObj* pPath = dynamic_cast<SdrPathObj*>( pNewObj.get() );
473 if ( pPath )
474 aPP = pPath->GetPathPoly();
477 if ( aPP.count() )
478 aPolyPolygon.append(aPP);
480 SdrObject::Free( pObj );
481 basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( aPolyPolygon,
482 aPolyPolygonBezierCoords );
486 return aPolyPolygonBezierCoords;
489 Sequence< Reference< drawing::XCustomShapeHandle > > SAL_CALL EnhancedCustomShapeEngine::getInteraction()
491 sal_uInt32 i, nHdlCount = 0;
492 const bool bIsSdrObjCustomShape(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(mxShape)));
494 if(bIsSdrObjCustomShape)
496 SdrObjCustomShape& rSdrObjCustomShape(
497 static_cast< SdrObjCustomShape& >(
498 *GetSdrObjectFromXShape(mxShape)));
499 EnhancedCustomShape2d aCustomShape2d(rSdrObjCustomShape);
500 nHdlCount = aCustomShape2d.GetHdlCount();
503 Sequence< Reference< drawing::XCustomShapeHandle > > aSeq( nHdlCount );
505 for ( i = 0; i < nHdlCount; i++ )
506 aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i );
507 return aSeq;
512 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
513 com_sun_star_drawing_EnhancedCustomShapeEngine_get_implementation(
514 css::uno::XComponentContext *,
515 css::uno::Sequence<css::uno::Any> const &)
517 return cppu::acquire(new EnhancedCustomShapeEngine);
520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */