1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ShapeFactory.cxx,v $
10 * $Revision: 1.25.44.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "ShapeFactory.hxx"
34 #include "ViewDefines.hxx"
36 #include "CommonConverters.hxx"
38 #include "PropertyMapper.hxx"
39 #include <comphelper/InlineContainer.hxx>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/drawing/CircleKind.hpp>
42 #include <com/sun/star/drawing/DoubleSequence.hpp>
43 #include <com/sun/star/drawing/FlagSequence.hpp>
44 #include <com/sun/star/drawing/FillStyle.hpp>
45 #include <com/sun/star/drawing/LineStyle.hpp>
46 #include <com/sun/star/drawing/NormalsKind.hpp>
47 #include <com/sun/star/drawing/PointSequence.hpp>
48 #include <com/sun/star/drawing/PolygonKind.hpp>
49 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
50 #include <com/sun/star/drawing/ProjectionMode.hpp>
51 #include <com/sun/star/drawing/ShadeMode.hpp>
52 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
53 #include <com/sun/star/drawing/TextureProjectionMode.hpp>
54 #include <com/sun/star/text/XText.hpp>
55 #include <com/sun/star/uno/Any.hxx>
58 #include <svx/unoprnms.hxx>
59 #include <tools/color.hxx>
60 #include <tools/debug.hxx>
61 #include <rtl/math.hxx>
62 #include <svx/svdocirc.hxx>
63 #include <svx/svdopath.hxx>
65 #ifndef _BGFX_VECTOR_B2DPOINT_HXX
66 #include <basegfx/point/b2dpoint.hxx>
68 #include <basegfx/matrix/b3dhommatrix.hxx>
72 using namespace ::com::sun::star
;
74 //.............................................................................
77 //.............................................................................
79 //-----------------------------------------------------------------------------
80 //-----------------------------------------------------------------------------
81 // set a name/CID at a shape (is used for selection handling)
82 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
86 void ShapeFactory::setShapeName( const uno::Reference
< drawing::XShape
>& xShape
87 , const rtl::OUString
& rName
)
91 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
92 DBG_ASSERT(xProp
.is(), "shape offers no XPropertySet");
97 xProp
->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME
)
98 , uno::makeAny( rName
) );
100 catch( uno::Exception
& e
)
102 ASSERT_EXCEPTION( e
);
107 //-----------------------------------------------------------------------------
110 rtl::OUString
ShapeFactory::getShapeName( const uno::Reference
< drawing::XShape
>& xShape
)
114 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
115 DBG_ASSERT(xProp
.is(), "shape offers no XPropertySet");
120 xProp
->getPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME
) ) >>= aRet
;
122 catch( uno::Exception
& e
)
124 ASSERT_EXCEPTION( e
);
131 //-----------------------------------------------------------------------------
133 uno::Reference
< drawing::XShapes
> ShapeFactory::getChartRootShape(
134 const uno::Reference
< drawing::XDrawPage
>& xDrawPage
)
136 uno::Reference
< drawing::XShapes
> xRet
;
137 uno::Reference
< drawing::XShapes
> xShapes( xDrawPage
, uno::UNO_QUERY
);
140 sal_Int32 nCount
= xShapes
->getCount();
141 uno::Reference
< drawing::XShape
> xShape
;
142 for( sal_Int32 nN
= nCount
; nN
--; )
144 if( xShapes
->getByIndex( nN
) >>= xShape
)
146 if( ShapeFactory::getShapeName( xShape
).equals(C2U("com.sun.star.chart2.shapes")) )
148 xRet
= uno::Reference
< drawing::XShapes
>( xShape
, uno::UNO_QUERY
);
157 //-----------------------------------------------------------------------------
159 uno::Reference
< drawing::XShapes
> ShapeFactory::getOrCreateChartRootShape(
160 const uno::Reference
< drawing::XDrawPage
>& xDrawPage
)
162 uno::Reference
< drawing::XShapes
> xRet( ShapeFactory::getChartRootShape( xDrawPage
) );
165 //create the root shape
166 xRet
= this->createGroup2D(
167 uno::Reference
<drawing::XShapes
>( xDrawPage
, uno::UNO_QUERY
)
168 , C2U("com.sun.star.chart2.shapes") );
173 //-----------------------------------------------------------------------------
174 //-----------------------------------------------------------------------------
175 // diverse PolyPolygon create methods
176 //-----------------------------------------------------------------------------
177 //-----------------------------------------------------------------------------
179 uno::Any
createPolyPolygon_Cube(
180 const drawing::Direction3D
& rSize
, double fRoundedEdge
, bool bRounded
= true )
182 DBG_ASSERT(fRoundedEdge
>=0, "fRoundedEdge needs to be >= 0");
184 // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
185 if( fRoundedEdge
== 0.0 && bRounded
)
186 fRoundedEdge
= 0.4 / 200.0;
190 //fWidthH stands for Half Width
191 const double fWidthH
= rSize
.DirectionX
>=0.0? rSize
.DirectionX
/2.0 : -rSize
.DirectionX
/2.0;
192 const double fHeight
= rSize
.DirectionY
;
193 // const double fDepth = rSize.DirectionZ >=0.0? rSize.DirectionZ : -rSize.DirectionZ ;
195 const double fHeightSign
= fHeight
>= 0.0 ? 1.0 : -1.0;
197 const double fOffset
= (fWidthH
* fRoundedEdge
) * 1.05; // increase by 5% for safety
198 const bool bRoundEdges
= fRoundedEdge
&& fOffset
< fWidthH
&& 2.0 * fOffset
< fHeightSign
*fHeight
;
199 const sal_Int32 nPointCount
= bRoundEdges
? 13 : 5;
201 //--------------------------------------
202 drawing::PolyPolygonShape3D aPP
;
204 aPP
.SequenceX
.realloc(1);
205 aPP
.SequenceY
.realloc(1);
206 aPP
.SequenceZ
.realloc(1);
208 drawing::DoubleSequence
* pOuterSequenceX
= aPP
.SequenceX
.getArray();
209 drawing::DoubleSequence
* pOuterSequenceY
= aPP
.SequenceY
.getArray();
210 drawing::DoubleSequence
* pOuterSequenceZ
= aPP
.SequenceZ
.getArray();
212 pOuterSequenceX
->realloc(nPointCount
);
213 pOuterSequenceY
->realloc(nPointCount
);
214 pOuterSequenceZ
->realloc(nPointCount
);
216 double* pInnerSequenceX
= pOuterSequenceX
->getArray();
217 double* pInnerSequenceY
= pOuterSequenceY
->getArray();
218 double* pInnerSequenceZ
= pOuterSequenceZ
->getArray();
220 for(sal_Int32 nN
= nPointCount
; nN
--;)
221 *pInnerSequenceZ
++ = 0.0;
222 //*pInnerSequenceZ++ = -fDepth/2.0;
226 *pInnerSequenceY
++ = 0.0;
227 *pInnerSequenceY
++ = 0.0;
228 *pInnerSequenceY
++ = fHeight
;
229 *pInnerSequenceY
++ = fHeight
;
230 *pInnerSequenceY
++ = 0.0;
232 *pInnerSequenceX
++ = -fWidthH
;
233 *pInnerSequenceX
++ = fWidthH
;
234 *pInnerSequenceX
++ = fWidthH
;
235 *pInnerSequenceX
++ = -fWidthH
;
236 *pInnerSequenceX
++ = -fWidthH
;
240 *pInnerSequenceY
++ = 0.0;
241 *pInnerSequenceY
++ = 0.0;
242 *pInnerSequenceY
++ = 0.0;
243 *pInnerSequenceY
++ = fHeightSign
*fOffset
;
244 *pInnerSequenceY
++ = fHeight
- fHeightSign
*fOffset
;
245 *pInnerSequenceY
++ = fHeight
;
246 *pInnerSequenceY
++ = fHeight
;
247 *pInnerSequenceY
++ = fHeight
;
248 *pInnerSequenceY
++ = fHeight
;
249 *pInnerSequenceY
++ = fHeight
- fHeightSign
*fOffset
;
250 *pInnerSequenceY
++ = fHeightSign
*fOffset
;
251 *pInnerSequenceY
++ = 0.0;
252 *pInnerSequenceY
++ = 0.0;
254 *pInnerSequenceX
++ = -fWidthH
+ fOffset
;
255 *pInnerSequenceX
++ = fWidthH
- fOffset
;
256 *pInnerSequenceX
++ = fWidthH
;
257 *pInnerSequenceX
++ = fWidthH
;
258 *pInnerSequenceX
++ = fWidthH
;
259 *pInnerSequenceX
++ = fWidthH
;
260 *pInnerSequenceX
++ = fWidthH
- fOffset
;
261 *pInnerSequenceX
++ = -fWidthH
+ fOffset
;
262 *pInnerSequenceX
++ = -fWidthH
;
263 *pInnerSequenceX
++ = -fWidthH
;
264 *pInnerSequenceX
++ = -fWidthH
;
265 *pInnerSequenceX
++ = -fWidthH
;
266 *pInnerSequenceX
++ = -fWidthH
+ fOffset
;
268 return uno::Any( &aPP
, ::getCppuType((const drawing::PolyPolygonShape3D
*)0) );
271 uno::Any
createPolyPolygon_Cylinder(
274 , double fRoundedEdge
275 , sal_Int32
& nVerticalSegmentCount
)
277 //@todo consider offset if Height is negative
279 // DBG_ASSERT(fHeight>0, "The height of a cylinder needs to be > 0");
280 DBG_ASSERT(fRadius
>0, "The radius of a cylinder needs to be > 0");
281 DBG_ASSERT(fRoundedEdge
>=0, "fRoundedEdge needs to be >= 0");
283 // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
284 if( fRoundedEdge
== 0.0 )
285 fRoundedEdge
= 0.4 / 200.0;
287 // const double fWidth = fRadius;
290 const double fOffset
= (fRadius
* 2.0 * fRoundedEdge
) * 1.05; // increase by 5% for safety
291 const bool bRoundEdges
= fRoundedEdge
&& fOffset
< fRadius
&& 2.0 * fOffset
< fHeight
;
292 const sal_Int32 nPointCount
= bRoundEdges
? 8 : 4;
293 nVerticalSegmentCount
= nPointCount
-1;
295 //--------------------------------------
296 drawing::PolyPolygonShape3D aPP
;
298 aPP
.SequenceX
.realloc(1);
299 aPP
.SequenceY
.realloc(1);
300 aPP
.SequenceZ
.realloc(1);
302 drawing::DoubleSequence
* pOuterSequenceX
= aPP
.SequenceX
.getArray();
303 drawing::DoubleSequence
* pOuterSequenceY
= aPP
.SequenceY
.getArray();
304 drawing::DoubleSequence
* pOuterSequenceZ
= aPP
.SequenceZ
.getArray();
306 pOuterSequenceX
->realloc(nPointCount
);
307 pOuterSequenceY
->realloc(nPointCount
);
308 pOuterSequenceZ
->realloc(nPointCount
);
310 double* pInnerSequenceX
= pOuterSequenceX
->getArray();
311 double* pInnerSequenceY
= pOuterSequenceY
->getArray();
312 double* pInnerSequenceZ
= pOuterSequenceZ
->getArray();
314 for(sal_Int32 nN
= nPointCount
; nN
--;)
315 *pInnerSequenceZ
++ = 0.0;
319 *pInnerSequenceY
++ = 0.0;
320 *pInnerSequenceY
++ = 0.0;
321 *pInnerSequenceY
++ = fHeight
;
322 *pInnerSequenceY
++ = fHeight
;
324 *pInnerSequenceX
++ = 0.0;
325 *pInnerSequenceX
++ = fRadius
;
326 *pInnerSequenceX
++ = fRadius
;
327 *pInnerSequenceX
++ = 0.0;
331 *pInnerSequenceY
++ = 0.0; //1.
332 *pInnerSequenceY
++ = 0.0;
333 *pInnerSequenceY
++ = 0.0;
334 *pInnerSequenceY
++ = fOffset
;
335 *pInnerSequenceY
++ = fHeight
- fOffset
;
336 *pInnerSequenceY
++ = fHeight
; //6.
337 *pInnerSequenceY
++ = fHeight
;
338 *pInnerSequenceY
++ = fHeight
;
340 *pInnerSequenceX
++ = 0.0; //1.
341 *pInnerSequenceX
++ = fRadius
- fOffset
;
342 *pInnerSequenceX
++ = fRadius
;
343 *pInnerSequenceX
++ = fRadius
;
344 *pInnerSequenceX
++ = fRadius
;
345 *pInnerSequenceX
++ = fRadius
; //6.
346 *pInnerSequenceX
++ = fRadius
- fOffset
;
347 *pInnerSequenceX
++ = 0.0;
349 return uno::Any( &aPP
, ::getCppuType((const drawing::PolyPolygonShape3D
*)0) );
352 uno::Any
createPolyPolygon_Cone(
356 , double fRoundedEdge
357 , sal_Int32
& nVerticalSegmentCount
)
359 //@todo consider offset if Height is negative
361 DBG_ASSERT(fHeight>0, "The height of a cone needs to be > 0");
362 DBG_ASSERT(fTopHeight>=0, "The height of the cutted top of a cone needs to be >= 0");
365 DBG_ASSERT(fRadius
>0, "The radius of a cone needs to be > 0");
366 DBG_ASSERT(fRoundedEdge
>=0, "fRoundedEdge needs to be >= 0");
368 //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
369 //fTopHeight indicates the high of the cutted top only (not the full height)
371 // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
372 if( fRoundedEdge
== 0.0 )
373 fRoundedEdge
= 0.4 / 200.0;
377 // ::rtl::math::approxEqual cannot compare to 0.0
378 bool bTopless
= !::rtl::math::approxEqual( fHeight
, fHeight
+ fTopHeight
);
380 double r1
= 0.0, r2
= fRadius
;
382 // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
383 r1
= fRadius
* (fTopHeight
)/(fabs(fHeight
)+fTopHeight
);
385 const double fMinimumDimension
= ::std::min(r2
*2.0,fHeight
);
386 const double fOffset
= (fMinimumDimension
* fRoundedEdge
) * 1.05; // increase by 5% for safety
387 const bool bRoundEdges
= fRoundedEdge
&& fOffset
< r2
&& 2.0 * fOffset
< fHeight
388 && ( bTopless
? fOffset
< r1
: true );
389 sal_Int32 nPointCount
= 8;
402 nVerticalSegmentCount
= nPointCount
-1;
404 //--------------------------------------
405 drawing::PolyPolygonShape3D aPP
;
407 aPP
.SequenceX
.realloc(1);
408 aPP
.SequenceY
.realloc(1);
409 aPP
.SequenceZ
.realloc(1);
411 drawing::DoubleSequence
* pOuterSequenceX
= aPP
.SequenceX
.getArray();
412 drawing::DoubleSequence
* pOuterSequenceY
= aPP
.SequenceY
.getArray();
413 drawing::DoubleSequence
* pOuterSequenceZ
= aPP
.SequenceZ
.getArray();
415 pOuterSequenceX
->realloc(nPointCount
);
416 pOuterSequenceY
->realloc(nPointCount
);
417 pOuterSequenceZ
->realloc(nPointCount
);
419 double* pInnerSequenceX
= pOuterSequenceX
->getArray();
420 double* pInnerSequenceY
= pOuterSequenceY
->getArray();
421 double* pInnerSequenceZ
= pOuterSequenceZ
->getArray();
423 for(sal_Int32 nN
= nPointCount
; nN
--;)
424 *pInnerSequenceZ
++ = 0.0;
428 *pInnerSequenceY
++ = fHeight
; //1.
429 *pInnerSequenceX
++ = 0.0; //1.
433 *pInnerSequenceY
++ = fHeight
; //2.
434 *pInnerSequenceX
++ = r1
- fOffset
; //2.
438 *pInnerSequenceY
++ = fHeight
; //3.
439 *pInnerSequenceX
++ = r1
; //3.
443 *pInnerSequenceY
++ = fHeight
- fOffset
; //4.
444 *pInnerSequenceX
++ = r1
+ fOffset
; //4.
446 *pInnerSequenceY
++ = fOffset
; //5.
447 *pInnerSequenceX
++ = r2
- fOffset
; //5.
450 *pInnerSequenceY
++ = 0.0; //6.
451 *pInnerSequenceX
++ = r2
; //6.
455 *pInnerSequenceY
++ = 0.0; //7.
456 *pInnerSequenceX
++ = r2
- fOffset
; //7.
459 *pInnerSequenceY
++ = 0.0; //8.
460 *pInnerSequenceX
++ = 0.0; //8.
462 return uno::Any( &aPP
, ::getCppuType((const drawing::PolyPolygonShape3D
*)0) );
465 //-----------------------------------------------------------------------------
466 //-----------------------------------------------------------------------------
467 // methods for 3D shape creation
468 //-----------------------------------------------------------------------------
469 //-----------------------------------------------------------------------------
471 uno::Reference
<drawing::XShape
>
472 ShapeFactory::createCube(
473 const uno::Reference
<drawing::XShapes
>& xTarget
474 , const drawing::Position3D
& rPosition
, const drawing::Direction3D
& rSize
475 , sal_Int32 nRotateZAngleHundredthDegree
476 , const uno::Reference
< beans::XPropertySet
>& xSourceProp
477 , const tPropertyNameMap
& rPropertyNameMap
486 if( xSourceProp
.is() )
488 drawing::LineStyle aLineStyle
;
489 xSourceProp
->getPropertyValue( C2U( "BorderStyle" ) ) >>= aLineStyle
;
490 if( aLineStyle
== drawing::LineStyle_SOLID
)
494 catch( uno::Exception
& e
)
496 ASSERT_EXCEPTION( e
);
499 uno::Reference
<drawing::XShape
> xShape
= impl_createCube( xTarget
, rPosition
, rSize
, nRotateZAngleHundredthDegree
, bRounded
);
500 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
501 if( xSourceProp
.is())
502 PropertyMapper::setMappedProperties( xProp
, xSourceProp
, rPropertyNameMap
);
506 uno::Reference
<drawing::XShape
>
507 ShapeFactory::impl_createCube(
508 const uno::Reference
<drawing::XShapes
>& xTarget
509 , const drawing::Position3D
& rPosition
, const drawing::Direction3D
& rSize
510 , sal_Int32 nRotateZAngleHundredthDegree
517 uno::Reference
< drawing::XShape
> xShape(
518 m_xShapeFactory
->createInstance( C2U(
519 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY
);
520 xTarget
->add(xShape
);
523 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
524 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
530 double fDepth
= rSize
.DirectionZ
;
533 xProp
->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH
)
534 , uno::makeAny((sal_Int32
)fDepth
) );
537 sal_Int16 nPercentDiagonal
= bRounded
? 3 : 0;
538 xProp
->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL
)
539 , uno::makeAny( nPercentDiagonal
) );
542 xProp
->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D
)
543 , createPolyPolygon_Cube( rSize
, double(nPercentDiagonal
)/200.0,bRounded
) );
545 //Matrix for position
547 ::basegfx::B3DHomMatrix aM
;
548 if(nRotateZAngleHundredthDegree
!=0)
549 aM
.rotate(0.0,0.0,-nRotateZAngleHundredthDegree
/18000.00*F_PI
);
550 aM
.translate(rPosition
.PositionX
551 , rPosition
.PositionY
552 , rPosition
.PositionZ
- (fDepth
/2.0));
553 drawing::HomogenMatrix aHM
= B3DHomMatrixToHomogenMatrix(aM
);
554 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX
)
555 , uno::makeAny(aHM
) );
558 catch( uno::Exception
& e
)
560 ASSERT_EXCEPTION( e
);
566 uno::Reference
<drawing::XShape
>
567 ShapeFactory::createCylinder(
568 const uno::Reference
<drawing::XShapes
>& xTarget
569 , const drawing::Position3D
& rPosition
, const drawing::Direction3D
& rSize
570 , sal_Int32 nRotateZAngleHundredthDegree
)
572 return impl_createConeOrCylinder(
573 xTarget
, rPosition
, rSize
, 0.0, nRotateZAngleHundredthDegree
, CHART_3DOBJECT_SEGMENTCOUNT
, true );
576 uno::Reference
<drawing::XShape
>
577 ShapeFactory::createPyramid(
578 const uno::Reference
<drawing::XShapes
>& xTarget
579 , const drawing::Position3D
& rPosition
, const drawing::Direction3D
& rSize
580 , double fTopHeight
, sal_Int32 nRotateZAngleHundredthDegree
)
582 return impl_createConeOrCylinder( xTarget
, rPosition
, rSize
, fTopHeight
, nRotateZAngleHundredthDegree
, 4 );
585 uno::Reference
<drawing::XShape
>
586 ShapeFactory::createCone(
587 const uno::Reference
<drawing::XShapes
>& xTarget
588 , const drawing::Position3D
& rPosition
, const drawing::Direction3D
& rSize
589 , double fTopHeight
, sal_Int32 nRotateZAngleHundredthDegree
)
591 return impl_createConeOrCylinder( xTarget
, rPosition
, rSize
, fTopHeight
, nRotateZAngleHundredthDegree
, CHART_3DOBJECT_SEGMENTCOUNT
);
594 uno::Reference
<drawing::XShape
>
595 ShapeFactory::impl_createConeOrCylinder(
596 const uno::Reference
<drawing::XShapes
>& xTarget
597 , const drawing::Position3D
& rPosition
, const drawing::Direction3D
& rSize
598 , double fTopHeight
, sal_Int32 nRotateZAngleHundredthDegree
599 , sal_Int32 nSegments
606 uno::Reference
< drawing::XShape
> xShape(
607 m_xShapeFactory
->createInstance( C2U(
608 "com.sun.star.drawing.Shape3DLatheObject") ), uno::UNO_QUERY
);
609 xTarget
->add(xShape
);
612 double fYRotateAnglePi
= -ZDIRECTION
*(F_PI
/2.0 - F_PI
/(double)nSegments
); // alwayas rotate edge to front (important for pyramids)
613 //or: ZDIRECTION*(F_PI/2.0 - F_PI/(double)nSegments); // rotate edge to front for even segment count otherwise rotate corner to front
614 double fAngle
= fYRotateAnglePi
;
618 while(fAngle
>F_PI
/2.0)
621 double fWidth
= rSize
.DirectionX
/2.0; //The depth will be corrrected within Matrix
622 double fRadius
= fWidth
; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
623 // double fRadius = fWidth/cos(fAngle); llllllllllllllllllll
624 double fHeight
= rSize
.DirectionY
;
627 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
628 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
634 sal_Int16 nPercentDiagonal
= 5;
635 xProp
->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL
)
636 , uno::makeAny( nPercentDiagonal
) );
639 sal_Int32 nVerticalSegmentCount
= 0;
640 uno::Any aPPolygon
= bCylinder
? createPolyPolygon_Cylinder(
641 fHeight
, fRadius
, double(nPercentDiagonal
)/200.0, nVerticalSegmentCount
)
642 : createPolyPolygon_Cone(
643 fHeight
, fRadius
, fTopHeight
, double(nPercentDiagonal
)/200.0, nVerticalSegmentCount
);
644 xProp
->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D
), aPPolygon
);
646 //Matrix for position
648 ::basegfx::B3DHomMatrix aM
;
649 //aM.RotateY( fYRotateAnglePi );
650 if(nRotateZAngleHundredthDegree
!=0)
651 aM
.rotate(0.0,0.0,-nRotateZAngleHundredthDegree
/18000.00*F_PI
);
652 //stretch the symmetric objects to given depth
653 aM
.scale(1.0,1.0,rSize
.DirectionZ
/rSize
.DirectionX
);
654 aM
.translate(rPosition
.PositionX
, rPosition
.PositionY
, rPosition
.PositionZ
);
655 drawing::HomogenMatrix aHM
= B3DHomMatrixToHomogenMatrix(aM
);
656 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX
)
657 , uno::makeAny(aHM
) );
661 xProp
->setPropertyValue( C2U( UNO_NAME_3D_HORZ_SEGS
)
662 , uno::makeAny(nSegments
) );
663 xProp
->setPropertyValue( C2U( UNO_NAME_3D_VERT_SEGS
)
664 , uno::makeAny((sal_Int32
)nVerticalSegmentCount
) );//depends on point count of the used polygon
667 xProp
->setPropertyValue( C2U( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
)
668 , uno::makeAny((sal_Bool
)sal_True
) );
670 catch( uno::Exception
& e
)
672 ASSERT_EXCEPTION( e
);
678 //------------------------------------------------------------------------------------------------------------
679 //------------------------------------------------------------------------------------------------------------
680 //------------------------------------------------------------------------------------------------------------
682 void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords
& rReturn
, const drawing::PolyPolygonBezierCoords
& rAdd
, sal_Bool bAppendInverse
)
684 if(!rAdd
.Coordinates
.getLength())
686 sal_Int32 nAddCount
= rAdd
.Coordinates
[0].getLength();
690 sal_Int32 nOldCount
= rReturn
.Coordinates
[0].getLength();
692 rReturn
.Coordinates
[0].realloc(nOldCount
+nAddCount
+1);
693 rReturn
.Flags
[0].realloc(nOldCount
+nAddCount
+1);
695 for(sal_Int32 nN
=0;nN
<nAddCount
; nN
++ )
697 sal_Int32 nAdd
= bAppendInverse
? (nAddCount
-1-nN
) : nN
;
698 rReturn
.Coordinates
[0][nOldCount
+nN
] = rAdd
.Coordinates
[0][nAdd
];
699 rReturn
.Flags
[0][nOldCount
+nN
] = rAdd
.Flags
[0][nAdd
];
703 rReturn
.Coordinates
[0][nOldCount
+nAddCount
] = rReturn
.Coordinates
[0][0];
704 rReturn
.Flags
[0][nOldCount
+nAddCount
] = rReturn
.Flags
[0][0];
707 //------------------------------------------------------------------------------------------------------------
709 drawing::PolyPolygonBezierCoords
getCircularArcBezierCoords(
710 double fStartAngleRadian
, double fWidthAngleRadian
, double fUnitRadius
711 , const ::basegfx::B2DHomMatrix
& rTransformationFromUnitCircle
712 , const double fAngleSubdivisionRadian
)
714 //at least one polygon is created using two normal and two control points
715 //if the angle is larger it is separated into multiple sub angles
717 drawing::PolyPolygonBezierCoords aReturn
= drawing::PolyPolygonBezierCoords();
718 sal_Int32 nSegmentCount
= static_cast< sal_Int32
>( fWidthAngleRadian
/fAngleSubdivisionRadian
);
719 if( fWidthAngleRadian
> fAngleSubdivisionRadian
*nSegmentCount
)
722 double fFirstSegmentAngle
= fAngleSubdivisionRadian
;
723 double fLastSegmentAngle
= fAngleSubdivisionRadian
;
726 fFirstSegmentAngle
= fWidthAngleRadian
;
727 fLastSegmentAngle
= 0.0;
731 double fFirstAngleOnSubDevision
= (static_cast<sal_Int32
>(fStartAngleRadian
/fAngleSubdivisionRadian
)+1)*fAngleSubdivisionRadian
;
732 if( !::rtl::math::approxEqual( fStartAngleRadian
, fFirstAngleOnSubDevision
) )
733 fFirstSegmentAngle
= fFirstAngleOnSubDevision
-fStartAngleRadian
;
737 fLastSegmentAngle
= fWidthAngleRadian
-fFirstSegmentAngle
-fAngleSubdivisionRadian
*(nSegmentCount
-2);
738 if( fLastSegmentAngle
<0 )
740 if( fLastSegmentAngle
>fAngleSubdivisionRadian
)
742 fLastSegmentAngle
-=fAngleSubdivisionRadian
;
748 sal_Int32 nPointCount
= 1 + 3*nSegmentCount
; //first point of next segment equals last point of former segment
750 aReturn
.Coordinates
= drawing::PointSequenceSequence(1);
751 aReturn
.Flags
= drawing::FlagSequenceSequence(1);
753 drawing::PointSequence
aPoints(nPointCount
);
754 drawing::FlagSequence
aFlags(nPointCount
);
758 //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
759 ::basegfx::B2DPoint P0
,P1
,P2
,P3
;
760 ::basegfx::B2DPoint POrigin
= rTransformationFromUnitCircle
* ::basegfx::B2DPoint(0.0, 0.0);
763 double fCurrentRotateAngle
= fStartAngleRadian
;
764 for(sal_Int32 nSegment
=0; nSegment
<nSegmentCount
; nSegment
++)
766 double fCurrentSegmentAngle
= fAngleSubdivisionRadian
;
767 if(nSegment
==0)//first segment gets only a smaller peace until the next subdevision
768 fCurrentSegmentAngle
= fFirstSegmentAngle
;
769 else if(nSegment
==(nSegmentCount
-1)) //the last segment gets the rest angle that does not fit into equal pieces
770 fCurrentSegmentAngle
= fLastSegmentAngle
;
772 //first create untransformed points for a unit circle arc:
773 const double fCos
= cos(fCurrentSegmentAngle
/2.0);
774 const double fSin
= sin(fCurrentSegmentAngle
/2.0);
780 P1
.setX((4.0-fCos
)/3.0);
782 P1
.setY((1.0-fCos
)*(fCos
-3.0)/(3.0*fSin
));
784 //transform thus startangle equals NULL
785 ::basegfx::B2DHomMatrix aStart
;
786 aStart
.rotate(fCurrentSegmentAngle
/2.0 + fCurrentRotateAngle
);
787 fCurrentRotateAngle
+=fCurrentSegmentAngle
;
789 aStart
.scale( fUnitRadius
, fUnitRadius
);
791 //apply given transformation to get final points
792 P0
= rTransformationFromUnitCircle
*(aStart
*P0
);
793 P1
= rTransformationFromUnitCircle
*(aStart
*P1
);
794 P2
= rTransformationFromUnitCircle
*(aStart
*P2
);
795 P3
= rTransformationFromUnitCircle
*(aStart
*P3
);
797 aPoints
[nPoint
].X
= static_cast< sal_Int32
>( P0
.getX());
798 aPoints
[nPoint
].Y
= static_cast< sal_Int32
>( P0
.getY());
799 aFlags
[nPoint
++] = drawing::PolygonFlags_NORMAL
;
801 aPoints
[nPoint
].X
= static_cast< sal_Int32
>( P1
.getX());
802 aPoints
[nPoint
].Y
= static_cast< sal_Int32
>( P1
.getY());
803 aFlags
[nPoint
++] = drawing::PolygonFlags_CONTROL
;
805 aPoints
[nPoint
].X
= static_cast< sal_Int32
>( P2
.getX());
806 aPoints
[nPoint
].Y
= static_cast< sal_Int32
>( P2
.getY());
807 aFlags
[nPoint
++] = drawing::PolygonFlags_CONTROL
;
809 if(nSegment
==(nSegmentCount
-1))
811 aPoints
[nPoint
].X
= static_cast< sal_Int32
>( P3
.getX());
812 aPoints
[nPoint
].Y
= static_cast< sal_Int32
>( P3
.getY());
813 aFlags
[nPoint
++] = drawing::PolygonFlags_NORMAL
;
817 aReturn
.Coordinates
[0] = aPoints
;
818 aReturn
.Flags
[0] = aFlags
;
823 //------------------------------------------------------------------------------------------------------------
825 drawing::PolyPolygonBezierCoords
getRingBezierCoords(
826 double fUnitCircleInnerRadius
827 , double fUnitCircleOuterRadius
828 , double fStartAngleRadian
, double fWidthAngleRadian
829 , ::basegfx::B2DHomMatrix aTransformationFromUnitCircle
830 , const double fAngleSubdivisionRadian
)
832 drawing::PolyPolygonBezierCoords aReturn
= drawing::PolyPolygonBezierCoords();
834 aReturn
.Coordinates
= drawing::PointSequenceSequence(1);
835 aReturn
.Flags
= drawing::FlagSequenceSequence(1);
837 drawing::PolyPolygonBezierCoords aOuterArc
= getCircularArcBezierCoords(
838 fStartAngleRadian
, fWidthAngleRadian
, fUnitCircleOuterRadius
, aTransformationFromUnitCircle
, fAngleSubdivisionRadian
);
839 aReturn
.Coordinates
[0] = aOuterArc
.Coordinates
[0];
840 aReturn
.Flags
[0] = aOuterArc
.Flags
[0];
842 drawing::PolyPolygonBezierCoords aInnerArc
= getCircularArcBezierCoords(
843 fStartAngleRadian
, fWidthAngleRadian
, fUnitCircleInnerRadius
, aTransformationFromUnitCircle
, fAngleSubdivisionRadian
);
844 appendAndCloseBezierCoords( aReturn
, aInnerArc
, sal_True
);
846 //fill rMarkHandlePoints
849 rMarkHandlePoints.realloc(1);
850 rMarkHandlePoints[0].realloc(6);
851 sal_Int32 nHandleCount=0;
852 sal_Int32 nOuterArcCount = aOuterArc.Coordinates[0].getLength();
854 rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][0];
856 rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][nOuterArcCount-1];
857 sal_Int32 nInnerArcCount = aInnerArc.Coordinates[0].getLength();
859 rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][0];
861 rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][nInnerArcCount-1];
862 rMarkHandlePoints[0].realloc(nHandleCount);
869 //------------------------------------------------------------------------------------------------------------
871 uno::Reference
< drawing::XShape
>
872 ShapeFactory::createPieSegment2D(
873 const uno::Reference
< drawing::XShapes
>& xTarget
874 , double fUnitCircleStartAngleDegree
, double fUnitCircleWidthAngleDegree
875 , double fUnitCircleInnerRadius
, double fUnitCircleOuterRadius
876 , const drawing::Direction3D
& rOffset
877 , const drawing::HomogenMatrix
& rUnitCircleToScene
)
882 while(fUnitCircleWidthAngleDegree
>360)
883 fUnitCircleWidthAngleDegree
-= 360.0;
884 while(fUnitCircleWidthAngleDegree
<0)
885 fUnitCircleWidthAngleDegree
+= 360.0;
888 uno::Reference
< drawing::XShape
> xShape(
889 m_xShapeFactory
->createInstance(
890 C2U("com.sun.star.drawing.ClosedBezierShape") ), uno::UNO_QUERY
);
891 xTarget
->add(xShape
); //need to add the shape before setting of properties
894 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
895 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
900 ::basegfx::B2DHomMatrix
aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene
) ) );
901 aTransformationFromUnitCircle
.translate(rOffset
.DirectionX
,rOffset
.DirectionY
);
903 const double fAngleSubdivisionRadian
= F_PI
/10.0;
905 drawing::PolyPolygonBezierCoords aCoords
= getRingBezierCoords(
906 fUnitCircleInnerRadius
, fUnitCircleOuterRadius
907 , fUnitCircleStartAngleDegree
*F_PI
/180.0, fUnitCircleWidthAngleDegree
*F_PI
/180.0
908 , aTransformationFromUnitCircle
, fAngleSubdivisionRadian
);
910 xProp
->setPropertyValue( C2U( "PolyPolygonBezier" ), uno::makeAny( aCoords
) );
912 //add shape for markhandles
914 drawing::PointSequenceSequence aMarkHandlePoints(1); to be filled within getRingBezierCoords
917 VLineProperties aHandleLineProperties;
918 aHandleLineProperties.LineStyle = uno::makeAny( drawing::LineStyle_NONE );
919 uno::Reference< drawing::XShape > xHandleShape =
920 this->createLine2D( xGroup, aMarkHandlePoints, &aHandleLineProperties );
921 this->setShapeName( xHandleShape, C2U("HandlesOnly") );
925 catch( uno::Exception
& e
)
927 ASSERT_EXCEPTION( e
);
934 //------------------------------------------------------------------------------------------------------------
936 uno::Reference
< drawing::XShape
>
937 ShapeFactory::createPieSegment(
938 const uno::Reference
< drawing::XShapes
>& xTarget
939 , double fUnitCircleStartAngleDegree
, double fUnitCircleWidthAngleDegree
940 , double fUnitCircleInnerRadius
, double fUnitCircleOuterRadius
941 , const drawing::Direction3D
& rOffset
942 , const drawing::HomogenMatrix
& rUnitCircleToScene
948 while(fUnitCircleWidthAngleDegree
>360)
949 fUnitCircleWidthAngleDegree
-= 360.0;
950 while(fUnitCircleWidthAngleDegree
<0)
951 fUnitCircleWidthAngleDegree
+= 360.0;
954 uno::Reference
< drawing::XShape
> xShape(
955 m_xShapeFactory
->createInstance( C2U(
956 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY
);
957 xTarget
->add(xShape
); //need to add the shape before setting of properties
960 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
961 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
966 ::basegfx::B2DHomMatrix
aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene
) ) );
967 aTransformationFromUnitCircle
.translate(rOffset
.DirectionX
,rOffset
.DirectionY
);
969 const double fAngleSubdivisionRadian
= F_PI
/32.0;
971 drawing::PolyPolygonBezierCoords aCoords
= getRingBezierCoords(
972 fUnitCircleInnerRadius
, fUnitCircleOuterRadius
973 , fUnitCircleStartAngleDegree
*F_PI
/180.0, fUnitCircleWidthAngleDegree
*F_PI
/180.0
974 , aTransformationFromUnitCircle
, fAngleSubdivisionRadian
);
977 xProp
->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH
)
978 , uno::makeAny((sal_Int32
)fDepth
) );
981 sal_Int16 nPercentDiagonal
= 0;
982 xProp
->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL
)
983 , uno::makeAny( nPercentDiagonal
) );
986 drawing::PolyPolygonShape3D
aPoly( BezierToPoly(aCoords
) );
987 ShapeFactory::closePolygon( aPoly
);
988 xProp
->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D
)
989 , uno::makeAny( aPoly
) );
992 xProp
->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED
)
993 , uno::makeAny( (sal_Bool
)true) );
996 xProp
->setPropertyValue( C2U( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
)
997 , uno::makeAny((sal_Bool
)sal_True
) );
999 //TextureProjectionMode
1000 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_Y
)
1001 , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC
) );
1003 //TextureProjectionMode
1004 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_X
)
1005 , uno::makeAny( drawing::TextureProjectionMode_PARALLEL
) );
1006 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_Y
)
1007 , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC
) );
1009 catch( uno::Exception
& e
)
1011 ASSERT_EXCEPTION( e
);
1017 //------------------------------------------------------------------------------------------------------------
1018 //------------------------------------------------------------------------------------------------------------
1019 //------------------------------------------------------------------------------------------------------------
1021 uno::Reference
< drawing::XShape
>
1022 ShapeFactory::createStripe( const uno::Reference
< drawing::XShapes
>& xTarget
1023 , const Stripe
& rStripe
1024 , const uno::Reference
< beans::XPropertySet
>& xSourceProp
1025 , const tPropertyNameMap
& rPropertyNameMap
1026 , sal_Bool bDoubleSided
1027 , bool bRotatedTexture
)
1033 uno::Reference
< drawing::XShape
> xShape(
1034 m_xShapeFactory
->createInstance( C2U(
1035 "com.sun.star.drawing.Shape3DPolygonObject" ) ), uno::UNO_QUERY
);
1036 xTarget
->add(xShape
);
1039 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1040 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1046 xProp
->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D
)
1047 , rStripe
.getPolyPolygonShape3D() );
1050 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TEXTUREPOLYGON3D
)
1051 , rStripe
.getTexturePolygon( bRotatedTexture
) );
1055 xProp
->setPropertyValue( C2U( UNO_NAME_3D_NORMALSPOLYGON3D
)
1056 , rStripe
.getNormalsPolygon() );
1059 xProp
->setPropertyValue( C2U( UNO_NAME_3D_NORMALS_KIND
)
1060 , uno::makeAny( drawing::NormalsKind_FLAT
) );
1063 xProp
->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY
)
1064 , uno::makeAny( (sal_Bool
)false) );
1067 xProp
->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED
)
1068 , uno::makeAny(bDoubleSided
) );
1070 if( xSourceProp
.is())
1071 PropertyMapper::setMappedProperties( xProp
, xSourceProp
, rPropertyNameMap
);
1073 catch( uno::Exception
& e
)
1075 ASSERT_EXCEPTION( e
);
1081 uno::Reference
< drawing::XShape
>
1082 ShapeFactory::createArea3D( const uno::Reference
< drawing::XShapes
>& xTarget
1083 , const drawing::PolyPolygonShape3D
& rPolyPolygon
1089 if( !rPolyPolygon
.SequenceX
.getLength())
1093 uno::Reference
< drawing::XShape
> xShape(
1094 m_xShapeFactory
->createInstance( C2U(
1095 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY
);
1096 xTarget
->add(xShape
);
1099 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1100 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1106 xProp
->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH
)
1107 , uno::makeAny((sal_Int32
)fDepth
) );
1110 sal_Int16 nPercentDiagonal
= 0;
1111 xProp
->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL
)
1112 , uno::makeAny( nPercentDiagonal
) );
1115 xProp
->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D
)
1116 , uno::makeAny( rPolyPolygon
) );
1119 xProp
->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED
)
1120 , uno::makeAny( (sal_Bool
)true) );
1122 //the z component of the polygon is now ignored by the drawing layer,
1123 //so we nned to translate the object via transformation matrix
1125 //Matrix for position
1126 if( rPolyPolygon
.SequenceZ
.getLength()&& rPolyPolygon
.SequenceZ
[0].getLength() )
1128 ::basegfx::B3DHomMatrix aM
;
1131 , rPolyPolygon
.SequenceZ
[0][0] );
1132 drawing::HomogenMatrix aHM
= B3DHomMatrixToHomogenMatrix(aM
);
1133 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX
)
1134 , uno::makeAny(aHM
) );
1137 catch( uno::Exception
& e
)
1139 ASSERT_EXCEPTION( e
);
1145 uno::Reference
< drawing::XShape
>
1146 ShapeFactory::createArea2D( const uno::Reference
< drawing::XShapes
>& xTarget
1147 , const drawing::PolyPolygonShape3D
& rPolyPolygon
)
1153 uno::Reference
< drawing::XShape
> xShape(
1154 m_xShapeFactory
->createInstance( C2U(
1155 "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY
);
1156 xTarget
->add(xShape
);
1159 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1160 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1165 //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
1166 drawing::PointSequenceSequence
aPoints( PolyToPointSequence(rPolyPolygon
) );
1169 xProp
->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON
)
1170 , uno::makeAny( aPoints
) );
1173 //an area should always be behind other shapes
1174 xProp
->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_ZORDER
)
1175 , uno::makeAny( sal_Int32(0) ) );
1177 catch( uno::Exception
& e
)
1179 ASSERT_EXCEPTION( e
);
1185 enum SymbolType
{ SYMBOL_SQUARE
=0
1189 , SYMBOL_ARROW_RIGHT
1196 sal_Int32
ShapeFactory::getSymbolCount()
1198 return SYMBOL_COUNT
;
1201 drawing::PolyPolygonShape3D
createPolyPolygon_Symbol( const drawing::Position3D
& rPos
1202 , const drawing::Direction3D
& rSize
1203 , sal_Int32 nStandardSymbol
)
1205 if(nStandardSymbol
<0)
1206 nStandardSymbol
*=-1;
1207 nStandardSymbol
= nStandardSymbol
%ShapeFactory::getSymbolCount();
1208 SymbolType eSymbolType
=static_cast<SymbolType
>(nStandardSymbol
);
1210 const double& fX
= rPos
.PositionX
;
1211 const double& fY
= rPos
.PositionY
;
1213 const double fWidthH
= rSize
.DirectionX
/2.0; //fWidthH stands for Half Width
1214 const double fHeightH
= rSize
.DirectionY
/2.0; //fHeightH stands for Half Height
1216 sal_Int32 nPointCount
= 4; //all arrow symbols only need 4 points
1217 switch( eSymbolType
)
1220 case SYMBOL_DIAMOND
:
1222 case SYMBOL_SANDGLASS
:
1229 //--------------------------------------
1230 drawing::PolyPolygonShape3D aPP
;
1232 aPP
.SequenceX
.realloc(1);
1233 aPP
.SequenceY
.realloc(1);
1234 aPP
.SequenceZ
.realloc(1);
1236 drawing::DoubleSequence
* pOuterSequenceX
= aPP
.SequenceX
.getArray();
1237 drawing::DoubleSequence
* pOuterSequenceY
= aPP
.SequenceY
.getArray();
1238 drawing::DoubleSequence
* pOuterSequenceZ
= aPP
.SequenceZ
.getArray();
1240 pOuterSequenceX
->realloc(nPointCount
);
1241 pOuterSequenceY
->realloc(nPointCount
);
1242 pOuterSequenceZ
->realloc(nPointCount
);
1244 double* pInnerSequenceX
= pOuterSequenceX
->getArray();
1245 double* pInnerSequenceY
= pOuterSequenceY
->getArray();
1246 double* pInnerSequenceZ
= pOuterSequenceZ
->getArray();
1248 for(sal_Int32 nN
= nPointCount
; nN
--;)
1249 *pInnerSequenceZ
++ = 0.0;
1253 case SYMBOL_ARROW_UP
:
1255 *pInnerSequenceX
++ = fX
-fWidthH
;
1256 *pInnerSequenceY
++ = fY
+fHeightH
;
1258 *pInnerSequenceX
++ = fX
+fWidthH
;
1259 *pInnerSequenceY
++ = fY
+fHeightH
;
1261 *pInnerSequenceX
++ = fX
;
1262 *pInnerSequenceY
++ = fY
-fHeightH
;
1264 *pInnerSequenceX
++ = fX
-fWidthH
;
1265 *pInnerSequenceY
++ = fY
+fHeightH
;
1268 case SYMBOL_ARROW_DOWN
:
1270 *pInnerSequenceX
++ = fX
-fWidthH
;
1271 *pInnerSequenceY
++ = fY
-fHeightH
;
1273 *pInnerSequenceX
++ = fX
;
1274 *pInnerSequenceY
++ = fY
+fHeightH
;
1276 *pInnerSequenceX
++ = fX
+fWidthH
;
1277 *pInnerSequenceY
++ = fY
-fHeightH
;
1279 *pInnerSequenceX
++ = fX
-fWidthH
;
1280 *pInnerSequenceY
++ = fY
-fHeightH
;
1283 case SYMBOL_ARROW_RIGHT
:
1285 *pInnerSequenceX
++ = fX
-fWidthH
;
1286 *pInnerSequenceY
++ = fY
-fHeightH
;
1288 *pInnerSequenceX
++ = fX
-fWidthH
;
1289 *pInnerSequenceY
++ = fY
+fHeightH
;
1291 *pInnerSequenceX
++ = fX
+fWidthH
;
1292 *pInnerSequenceY
++ = fY
;
1294 *pInnerSequenceX
++ = fX
-fWidthH
;
1295 *pInnerSequenceY
++ = fY
-fHeightH
;
1298 case SYMBOL_ARROW_LEFT
:
1300 *pInnerSequenceX
++ = fX
-fWidthH
;
1301 *pInnerSequenceY
++ = fY
;
1303 *pInnerSequenceX
++ = fX
+fWidthH
;
1304 *pInnerSequenceY
++ = fY
+fHeightH
;
1306 *pInnerSequenceX
++ = fX
+fWidthH
;
1307 *pInnerSequenceY
++ = fY
-fHeightH
;
1309 *pInnerSequenceX
++ = fX
-fWidthH
;
1310 *pInnerSequenceY
++ = fY
;
1315 *pInnerSequenceX
++ = fX
-fWidthH
;
1316 *pInnerSequenceY
++ = fY
-fHeightH
;
1318 *pInnerSequenceX
++ = fX
-fWidthH
;
1319 *pInnerSequenceY
++ = fY
+fHeightH
;
1321 *pInnerSequenceX
++ = fX
+fWidthH
;
1322 *pInnerSequenceY
++ = fY
-fHeightH
;
1324 *pInnerSequenceX
++ = fX
+fWidthH
;
1325 *pInnerSequenceY
++ = fY
+fHeightH
;
1327 *pInnerSequenceX
++ = fX
-fWidthH
;
1328 *pInnerSequenceY
++ = fY
-fHeightH
;
1331 case SYMBOL_SANDGLASS
:
1333 *pInnerSequenceX
++ = fX
-fWidthH
;
1334 *pInnerSequenceY
++ = fY
+fHeightH
;
1336 *pInnerSequenceX
++ = fX
+fWidthH
;
1337 *pInnerSequenceY
++ = fY
+fHeightH
;
1339 *pInnerSequenceX
++ = fX
-fWidthH
;
1340 *pInnerSequenceY
++ = fY
-fHeightH
;
1343 *pInnerSequenceX
++ = fX
+fWidthH
;
1344 *pInnerSequenceY
++ = fY
-fHeightH
;
1346 *pInnerSequenceX
++ = fX
-fWidthH
;
1347 *pInnerSequenceY
++ = fY
+fHeightH
;
1350 case SYMBOL_DIAMOND
:
1352 *pInnerSequenceX
++ = fX
-fWidthH
;
1353 *pInnerSequenceY
++ = fY
;
1355 *pInnerSequenceX
++ = fX
;
1356 *pInnerSequenceY
++ = fY
+fHeightH
;
1358 *pInnerSequenceX
++ = fX
+fWidthH
;
1359 *pInnerSequenceY
++ = fY
;
1361 *pInnerSequenceX
++ = fX
;
1362 *pInnerSequenceY
++ = fY
-fHeightH
;
1364 *pInnerSequenceX
++ = fX
-fWidthH
;
1365 *pInnerSequenceY
++ = fY
;
1368 default: //case SYMBOL_SQUARE:
1370 *pInnerSequenceX
++ = fX
-fWidthH
;
1371 *pInnerSequenceY
++ = fY
-fHeightH
;
1373 *pInnerSequenceX
++ = fX
-fWidthH
;
1374 *pInnerSequenceY
++ = fY
+fHeightH
;
1376 *pInnerSequenceX
++ = fX
+fWidthH
;
1377 *pInnerSequenceY
++ = fY
+fHeightH
;
1379 *pInnerSequenceX
++ = fX
+fWidthH
;
1380 *pInnerSequenceY
++ = fY
-fHeightH
;
1382 *pInnerSequenceX
++ = fX
-fWidthH
;
1383 *pInnerSequenceY
++ = fY
-fHeightH
;
1387 //return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
1391 uno::Reference
< drawing::XShape
>
1392 ShapeFactory::createSymbol2D(
1393 const uno::Reference
< drawing::XShapes
>& xTarget
1394 , const drawing::Position3D
& rPosition
1395 , const drawing::Direction3D
& rSize
1396 , sal_Int32 nStandardSymbol
1397 , sal_Int32 nBorderColor
1398 , sal_Int32 nFillColor
)
1404 uno::Reference
< drawing::XShape
> xShape(
1405 m_xShapeFactory
->createInstance( C2U(
1406 "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY
);
1407 xTarget
->add(xShape
);
1410 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1411 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1416 drawing::PointSequenceSequence
aPoints( PolyToPointSequence(
1417 createPolyPolygon_Symbol( rPosition
, rSize
, nStandardSymbol
) ));
1420 xProp
->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON
)
1421 , uno::makeAny( aPoints
) );
1424 xProp
->setPropertyValue( C2U( UNO_NAME_LINECOLOR
)
1425 , uno::makeAny( nBorderColor
) );
1428 xProp
->setPropertyValue( C2U( UNO_NAME_FILLCOLOR
)
1429 , uno::makeAny( nFillColor
) );
1431 catch( uno::Exception
& e
)
1433 ASSERT_EXCEPTION( e
);
1439 uno::Reference
< drawing::XShape
>
1440 ShapeFactory::createGraphic2D(
1441 const uno::Reference
< drawing::XShapes
>& xTarget
1442 , const drawing::Position3D
& rPosition
1443 , const drawing::Direction3D
& rSize
1444 , const uno::Reference
< graphic::XGraphic
>& xGraphic
)
1446 if( !xTarget
.is() || !xGraphic
.is() )
1449 // @todo: change this to a rectangle shape with a fill bitmap for
1450 // performance reasons (ask AW, said CL)
1453 uno::Reference
< drawing::XShape
> xShape(
1454 m_xShapeFactory
->createInstance( C2U(
1455 "com.sun.star.drawing.GraphicObjectShape") ), uno::UNO_QUERY
);
1456 xTarget
->add(xShape
);
1460 // assume position is upper left corner. Transform to center.
1461 drawing::Position3D
aCenterPosition(
1462 rPosition
.PositionX
- (rSize
.DirectionX
/ 2.0),
1463 rPosition
.PositionY
- (rSize
.DirectionY
/ 2.0),
1464 rPosition
.PositionZ
);
1465 xShape
->setPosition( Position3DToAWTPoint( aCenterPosition
));
1466 xShape
->setSize( Direction3DToAWTSize( rSize
));
1468 catch( const uno::Exception
& e
)
1470 ASSERT_EXCEPTION( e
);
1472 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1473 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1478 xProp
->setPropertyValue( C2U("Graphic"), uno::makeAny( xGraphic
));
1480 catch( uno::Exception
& e
)
1482 ASSERT_EXCEPTION( e
);
1488 uno::Reference
< drawing::XShapes
>
1489 ShapeFactory::createGroup2D( const uno::Reference
< drawing::XShapes
>& xTarget
1490 , ::rtl::OUString aName
)
1496 //create and add to target
1497 uno::Reference
< drawing::XShape
> xShape(
1498 m_xShapeFactory
->createInstance( C2U(
1499 "com.sun.star.drawing.GroupShape" ) ), uno::UNO_QUERY
);
1500 xTarget
->add(xShape
);
1503 if(aName
.getLength())
1504 setShapeName( xShape
, aName
);
1507 //need this null size as otherwise empty group shapes where painted with a gray border
1508 xShape
->setSize(awt::Size(0,0));
1512 uno::Reference
< drawing::XShapes
> xShapes
=
1513 uno::Reference
<drawing::XShapes
>( xShape
, uno::UNO_QUERY
);
1516 catch( uno::Exception
& e
)
1518 ASSERT_EXCEPTION( e
);
1523 uno::Reference
< drawing::XShapes
>
1524 ShapeFactory::createGroup3D( const uno::Reference
< drawing::XShapes
>& xTarget
1525 , ::rtl::OUString aName
)
1532 uno::Reference
< drawing::XShape
> xShape(
1533 m_xShapeFactory
->createInstance( C2U(
1534 "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY
);
1536 xTarget
->add(xShape
);
1538 //it is necessary to set the transform matrix to initialize the scene properly (bug #106316#)
1539 //otherwise all objects which are placed into this Group will not be visible
1540 //the following should be unnecessary after a the bug is fixed
1543 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1544 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1549 ::basegfx::B3DHomMatrix aM
;
1550 xProp
->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX
)
1551 , uno::makeAny(B3DHomMatrixToHomogenMatrix(aM
)) );
1553 catch( uno::Exception
& e
)
1555 ASSERT_EXCEPTION( e
);
1561 if(aName
.getLength())
1562 setShapeName( xShape
, aName
);
1565 uno::Reference
< drawing::XShapes
> xShapes
=
1566 uno::Reference
<drawing::XShapes
>( xShape
, uno::UNO_QUERY
);
1569 catch( uno::Exception
& e
)
1571 ASSERT_EXCEPTION( e
);
1576 uno::Reference
< drawing::XShape
>
1577 ShapeFactory::createCircle2D( const uno::Reference
< drawing::XShapes
>& xTarget
1578 , const drawing::Position3D
& rPosition
1579 , const drawing::Direction3D
& rSize
)
1585 uno::Reference
< drawing::XShape
> xShape(
1586 m_xShapeFactory
->createInstance( C2U(
1587 "com.sun.star.drawing.EllipseShape") ), uno::UNO_QUERY
);
1588 xTarget
->add(xShape
);
1592 drawing::Position3D
aCenterPosition(
1593 rPosition
.PositionX
- (rSize
.DirectionX
/ 2.0),
1594 rPosition
.PositionY
- (rSize
.DirectionY
/ 2.0),
1595 rPosition
.PositionZ
);
1596 xShape
->setPosition( Position3DToAWTPoint( aCenterPosition
));
1597 xShape
->setSize( Direction3DToAWTSize( rSize
));
1599 catch( const uno::Exception
& e
)
1601 ASSERT_EXCEPTION( e
);
1605 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1606 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1611 drawing::CircleKind eKind
= drawing::CircleKind_FULL
;
1612 xProp
->setPropertyValue( C2U( UNO_NAME_CIRCKIND
)
1613 , uno::makeAny( eKind
) );
1615 catch( uno::Exception
& e
)
1617 ASSERT_EXCEPTION( e
);
1623 uno::Reference
< drawing::XShape
>
1624 ShapeFactory::createLine3D( const uno::Reference
< drawing::XShapes
>& xTarget
1625 , const drawing::PolyPolygonShape3D
& rPoints
1626 , const VLineProperties
& rLineProperties
)
1631 if(!rPoints
.SequenceX
.getLength())
1635 uno::Reference
< drawing::XShape
> xShape(
1636 m_xShapeFactory
->createInstance( C2U(
1637 "com.sun.star.drawing.Shape3DPolygonObject") ), uno::UNO_QUERY
);
1638 xTarget
->add(xShape
);
1641 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1642 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1648 xProp
->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D
)
1649 , uno::makeAny( rPoints
) );
1652 xProp
->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY
)
1653 , uno::makeAny( (sal_Bool
)true ) );
1656 if(rLineProperties
.Transparence
.hasValue())
1657 xProp
->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE
)
1658 , rLineProperties
.Transparence
);
1661 if(rLineProperties
.LineStyle
.hasValue())
1662 xProp
->setPropertyValue( C2U( UNO_NAME_LINESTYLE
)
1663 , rLineProperties
.LineStyle
);
1666 if(rLineProperties
.Width
.hasValue())
1667 xProp
->setPropertyValue( C2U( UNO_NAME_LINEWIDTH
)
1668 , rLineProperties
.Width
);
1671 if(rLineProperties
.Color
.hasValue())
1672 xProp
->setPropertyValue( C2U( UNO_NAME_LINECOLOR
)
1673 , rLineProperties
.Color
);
1674 //, uno::makeAny( sal_Int32( Color(COL_RED).GetColor()) ) );
1676 catch( uno::Exception
& e
)
1678 ASSERT_EXCEPTION( e
);
1684 uno::Reference
< drawing::XShape
>
1685 ShapeFactory::createLine2D( const uno::Reference
< drawing::XShapes
>& xTarget
1686 , const drawing::PointSequenceSequence
& rPoints
1687 , const VLineProperties
* pLineProperties
)
1692 if(!rPoints
.getLength())
1696 uno::Reference
< drawing::XShape
> xShape(
1697 m_xShapeFactory
->createInstance( C2U(
1698 //"com.sun.star.drawing.LineShape") ), uno::UNO_QUERY );
1699 "com.sun.star.drawing.PolyLineShape") ), uno::UNO_QUERY
);
1700 //"com.sun.star.drawing.PolyLinePathShape") ), uno::UNO_QUERY );
1701 //"com.sun.star.drawing.PolyPolygonPathShape") ), uno::UNO_QUERY );
1702 //"com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
1703 xTarget
->add(xShape
);
1706 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1707 DBG_ASSERT(xProp
.is(), "created shape offers no XPropertySet");
1713 xProp
->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON
)
1714 , uno::makeAny( rPoints
) );
1719 if(pLineProperties
->Transparence
.hasValue())
1720 xProp
->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE
)
1721 , pLineProperties
->Transparence
);
1724 if(pLineProperties
->LineStyle
.hasValue())
1725 xProp
->setPropertyValue( C2U( UNO_NAME_LINESTYLE
)
1726 , pLineProperties
->LineStyle
);
1729 if(pLineProperties
->Width
.hasValue())
1730 xProp
->setPropertyValue( C2U( UNO_NAME_LINEWIDTH
)
1731 , pLineProperties
->Width
);
1734 if(pLineProperties
->Color
.hasValue())
1735 xProp
->setPropertyValue( C2U( UNO_NAME_LINECOLOR
)
1736 , pLineProperties
->Color
);
1739 if(pLineProperties
->DashName
.hasValue())
1740 xProp
->setPropertyValue( C2U( "LineDashName" )
1741 , pLineProperties
->DashName
);
1744 catch( uno::Exception
& e
)
1746 ASSERT_EXCEPTION( e
);
1752 uno::Any
ShapeFactory::makeTransformation( const awt::Point
& rScreenPosition2D
, double fRotationAnglePi
)
1754 ::basegfx::B2DHomMatrix aM
;
1755 //As autogrow is active the rectangle is automatically expanded to that side
1756 //to which the text is not adjusted.
1757 // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
1758 aM
.rotate( fRotationAnglePi
);
1759 aM
.translate( rScreenPosition2D
.X
, rScreenPosition2D
.Y
);
1760 uno::Any aATransformation
= uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM
) );
1761 return aATransformation
;
1764 void ShapeFactory::makeShapeInvisible( const uno::Reference
< drawing::XShape
>& xShape
)
1766 uno::Reference
< beans::XPropertySet
> xShapeProp( xShape
, uno::UNO_QUERY
);
1767 DBG_ASSERT(xShapeProp
.is(), "created shape offers no XPropertySet");
1768 if( xShapeProp
.is())
1772 xShapeProp
->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE
));
1773 xShapeProp
->setPropertyValue( C2U("FillStyle"), uno::makeAny( drawing::FillStyle_NONE
));
1775 catch( uno::Exception
& e
)
1777 ASSERT_EXCEPTION( e
);
1782 uno::Reference
< drawing::XShape
> ShapeFactory::createInvisibleRectangle(
1783 const uno::Reference
< drawing::XShapes
>& xTarget
1784 , const awt::Size
& rSize
)
1791 uno::Reference
< drawing::XShape
> xShape( m_xShapeFactory
->createInstance(
1792 C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY
);
1793 if( xTarget
.is() && xShape
.is())
1795 xTarget
->add( xShape
);
1796 ShapeFactory::makeShapeInvisible( xShape
);
1797 xShape
->setSize( rSize
);
1801 catch( uno::Exception
& ex
)
1803 ASSERT_EXCEPTION( ex
);
1808 uno::Reference
< drawing::XShape
>
1809 ShapeFactory::createText( const uno::Reference
< drawing::XShapes
>& xTarget
1810 , const ::rtl::OUString
& rText
1811 , const tNameSequence
& rPropNames
1812 , const tAnySequence
& rPropValues
1813 , const uno::Any
& rATransformation
)
1818 if(!rText
.getLength())
1821 //create shape and add to page
1822 uno::Reference
< drawing::XShape
> xShape(
1823 m_xShapeFactory
->createInstance( C2U(
1824 "com.sun.star.drawing.TextShape" ) ), uno::UNO_QUERY
);
1825 xTarget
->add(xShape
);
1828 uno::Reference
< text::XTextRange
> xTextRange( xShape
, uno::UNO_QUERY
);
1829 if( xTextRange
.is() )
1830 xTextRange
->setString( rText
);
1832 uno::Reference
< beans::XPropertySet
> xProp( xShape
, uno::UNO_QUERY
);
1836 PropertyMapper::setMultiProperties( rPropNames
, rPropValues
, xProp
);
1838 //set position matrix
1839 //the matrix needs to be set at the end behind autogrow and such position influencing properties
1842 xProp
->setPropertyValue( C2U( "Transformation" ), rATransformation
);
1844 catch( uno::Exception
& e
)
1846 ASSERT_EXCEPTION( e
);
1853 rtl::OUString
ShapeFactory::getStackedString( const rtl::OUString
& rString
, bool bStacked
)
1855 sal_Int32 nLen
= rString
.getLength();
1856 if(!bStacked
|| !nLen
)
1859 rtl::OUStringBuffer aStackStr
;
1860 rtl::OUStringBuffer
aSource(rString
);
1862 //add a newline after each letter
1863 //as we do not no letters here add a newline after each char
1864 for( sal_Int32 nPosSrc
=0; nPosSrc
< nLen
; nPosSrc
++ )
1867 aStackStr
.append( sal_Unicode('\r') );
1868 aStackStr
.append( aSource
.charAt( nPosSrc
) );
1870 return aStackStr
.makeStringAndClear();
1874 bool ShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D
& rPoly
)
1876 // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
1877 for( sal_Int32 nIdx
= 0, nCount
= rPoly
.SequenceX
.getLength(); nIdx
< nCount
; ++nIdx
)
1878 if( rPoly
.SequenceX
[ nIdx
].getLength() > 1 )
1884 bool ShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D
& rPoly
)
1886 // true, if empty polypolygon or one polygon with one point
1887 return (rPoly
.SequenceX
.getLength() == 0) ||
1888 ((rPoly
.SequenceX
.getLength() == 1) && (rPoly
.SequenceX
[0].getLength() <= 1));
1892 void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D
& rPoly
)
1894 DBG_ASSERT( rPoly
.SequenceX
.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
1895 //add a last point == first point
1896 if(isPolygonEmptyOrSinglePoint(rPoly
))
1898 drawing::Position3D
aFirst(rPoly
.SequenceX
[0][0],rPoly
.SequenceY
[0][0],rPoly
.SequenceZ
[0][0]);
1899 AddPointToPoly( rPoly
, aFirst
);
1903 awt::Size
ShapeFactory::calculateNewSizeRespectingAspectRatio(
1904 const awt::Size
& rTargetSize
1905 , const awt::Size
& rSourceSizeWithCorrectAspectRatio
)
1909 double fFactorWidth
= double(rTargetSize
.Width
)/double(rSourceSizeWithCorrectAspectRatio
.Width
);
1910 double fFactorHeight
= double(rTargetSize
.Height
)/double(rSourceSizeWithCorrectAspectRatio
.Height
);
1911 double fFactor
= std::min(fFactorWidth
,fFactorHeight
);
1912 aNewSize
.Width
=static_cast<sal_Int32
>(fFactor
*rSourceSizeWithCorrectAspectRatio
.Width
);
1913 aNewSize
.Height
=static_cast<sal_Int32
>(fFactor
*rSourceSizeWithCorrectAspectRatio
.Height
);
1919 awt::Point
ShapeFactory::calculateTopLeftPositionToCenterObject(
1920 const awt::Point
& rTargetAreaPosition
1921 , const awt::Size
& rTargetAreaSize
1922 , const awt::Size
& rObjectSize
)
1924 awt::Point
aNewPosition(rTargetAreaPosition
);
1925 aNewPosition
.X
+= static_cast<sal_Int32
>(double(rTargetAreaSize
.Width
-rObjectSize
.Width
)/2.0);
1926 aNewPosition
.Y
+= static_cast<sal_Int32
>(double(rTargetAreaSize
.Height
-rObjectSize
.Height
)/2.0);
1927 return aNewPosition
;
1931 ::basegfx::B2IRectangle
ShapeFactory::getRectangleOfShape(
1932 const uno::Reference
< drawing::XShape
>& xShape
)
1934 ::basegfx::B2IRectangle aRet
;
1938 awt::Point aPos
= xShape
->getPosition();
1939 awt::Size aSize
= xShape
->getSize();
1940 aRet
= BaseGFXHelper::makeRectangle(aPos
,aSize
);
1947 awt::Size
ShapeFactory::getSizeAfterRotation(
1948 const uno::Reference
< drawing::XShape
>& xShape
, double fRotationAngleDegree
)
1950 awt::Size
aRet(0,0);
1953 const awt::Size
aSize( xShape
->getSize() );
1955 if( ::rtl::math::approxEqual( fRotationAngleDegree
, 0.0 ) )
1959 while(fRotationAngleDegree
>=360.0)
1960 fRotationAngleDegree
-=360.0;
1961 while(fRotationAngleDegree
<0.0)
1962 fRotationAngleDegree
+=360.0;
1963 if(fRotationAngleDegree
>270.0)
1964 fRotationAngleDegree
=360.0-fRotationAngleDegree
;
1965 else if(fRotationAngleDegree
>180.0)
1966 fRotationAngleDegree
=fRotationAngleDegree
-180.0;
1967 else if(fRotationAngleDegree
>90.0)
1968 fRotationAngleDegree
=180.0-fRotationAngleDegree
;
1970 const double fAnglePi
= fRotationAngleDegree
*F_PI
/180.0;
1972 aRet
.Height
= static_cast<sal_Int32
>(
1973 aSize
.Width
*rtl::math::sin( fAnglePi
)
1974 + aSize
.Height
*rtl::math::cos( fAnglePi
));
1975 aRet
.Width
= static_cast<sal_Int32
>(
1976 aSize
.Width
*rtl::math::cos( fAnglePi
)
1977 + aSize
.Height
*rtl::math::sin( fAnglePi
));
1983 void ShapeFactory::removeSubShapes( const uno::Reference
< drawing::XShapes
>& xShapes
)
1987 sal_Int32 nSubCount
= xShapes
->getCount();
1988 uno::Reference
< drawing::XShape
> xShape
;
1989 for( sal_Int32 nS
= nSubCount
; nS
--; )
1991 if( xShapes
->getByIndex( nS
) >>= xShape
)
1992 xShapes
->remove( xShape
);
1997 //.............................................................................
1999 //.............................................................................