Update ooo320-m1
[ooovba.git] / chart2 / source / view / main / ShapeFactory.cxx
blob6563e31cc40950d44a67bdbf6f266122ac11b90f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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"
35 #include "Stripe.hxx"
36 #include "CommonConverters.hxx"
37 #include "macros.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>
67 #endif
68 #include <basegfx/matrix/b3dhommatrix.hxx>
70 #include <algorithm>
72 using namespace ::com::sun::star;
74 //.............................................................................
75 namespace chart
77 //.............................................................................
79 //-----------------------------------------------------------------------------
80 //-----------------------------------------------------------------------------
81 // set a name/CID at a shape (is used for selection handling)
82 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
85 //static
86 void ShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
87 , const rtl::OUString& rName )
89 if(!xShape.is())
90 return;
91 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
92 DBG_ASSERT(xProp.is(), "shape offers no XPropertySet");
93 if( xProp.is())
95 try
97 xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME )
98 , uno::makeAny( rName ) );
100 catch( uno::Exception& e )
102 ASSERT_EXCEPTION( e );
107 //-----------------------------------------------------------------------------
109 //static
110 rtl::OUString ShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
112 rtl::OUString aRet;
114 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
115 DBG_ASSERT(xProp.is(), "shape offers no XPropertySet");
116 if( xProp.is())
120 xProp->getPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ) ) >>= aRet;
122 catch( uno::Exception& e )
124 ASSERT_EXCEPTION( e );
128 return aRet;
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 );
138 if( xShapes.is() )
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 );
149 break;
154 return xRet;
157 //-----------------------------------------------------------------------------
159 uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape(
160 const uno::Reference< drawing::XDrawPage>& xDrawPage )
162 uno::Reference< drawing::XShapes > xRet( ShapeFactory::getChartRootShape( xDrawPage ) );
163 if( !xRet.is() )
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") );
170 return xRet;
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;
187 else if(!bRounded)
188 fRoundedEdge = 0.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;
224 if(nPointCount == 5)
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;
238 else
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(
272 double fHeight
273 , double fRadius
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;
289 fRoundedEdge = 0.0;
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;
317 if(nPointCount == 4)
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;
329 else
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(
353 double fHeight
354 , double fRadius
355 , double fTopHeight
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;
375 fRoundedEdge = 0.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;
381 if(bTopless)
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;
390 if(bTopless)
392 if(!bRoundEdges)
393 nPointCount = 4;
395 else
397 if(bRoundEdges)
398 nPointCount = 6;
399 else
400 nPointCount = 3;
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;
426 if(bTopless)
428 *pInnerSequenceY++ = fHeight; //1.
429 *pInnerSequenceX++ = 0.0; //1.
431 if(bRoundEdges)
433 *pInnerSequenceY++ = fHeight; //2.
434 *pInnerSequenceX++ = r1 - fOffset; //2.
438 *pInnerSequenceY++ = fHeight; //3.
439 *pInnerSequenceX++ = r1; //3.
441 if(bRoundEdges)
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.
453 if(bRoundEdges)
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
478 , bool bRounded )
480 if( !xTarget.is() )
481 return 0;
482 if( bRounded )
486 if( xSourceProp.is() )
488 drawing::LineStyle aLineStyle;
489 xSourceProp->getPropertyValue( C2U( "BorderStyle" ) ) >>= aLineStyle;
490 if( aLineStyle == drawing::LineStyle_SOLID )
491 bRounded = false;
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 );
503 return xShape;
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
511 , bool bRounded )
513 if( !xTarget.is() )
514 return 0;
516 //create shape
517 uno::Reference< drawing::XShape > xShape(
518 m_xShapeFactory->createInstance( C2U(
519 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
520 xTarget->add(xShape);
522 //set properties
523 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
524 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
525 if( xProp.is())
529 //depth
530 double fDepth = rSize.DirectionZ;
531 if(fDepth<0)
532 fDepth*=-1.0;
533 xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
534 , uno::makeAny((sal_Int32)fDepth) );
536 //PercentDiagonal
537 sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
538 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
539 , uno::makeAny( nPercentDiagonal ) );
541 //Polygon
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 );
563 return xShape;
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
600 , bool bCylinder )
602 if( !xTarget.is() )
603 return 0;
605 //create shape
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;
616 while(fAngle<0.0)
617 fAngle+=F_PI/2.0;
618 while(fAngle>F_PI/2.0)
619 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;
626 //set properties
627 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
628 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
629 if( xProp.is())
633 //PercentDiagonal
634 sal_Int16 nPercentDiagonal = 5;
635 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
636 , uno::makeAny( nPercentDiagonal ) );
638 //Polygon
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) );
660 //Segments
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
666 //Reduced lines
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 );
675 return xShape;
678 //------------------------------------------------------------------------------------------------------------
679 //------------------------------------------------------------------------------------------------------------
680 //------------------------------------------------------------------------------------------------------------
682 void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, sal_Bool bAppendInverse )
684 if(!rAdd.Coordinates.getLength())
685 return;
686 sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
687 if(!nAddCount)
688 return;
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];
702 //close
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 )
720 nSegmentCount++;
722 double fFirstSegmentAngle = fAngleSubdivisionRadian;
723 double fLastSegmentAngle = fAngleSubdivisionRadian;
724 if(nSegmentCount==1)
726 fFirstSegmentAngle = fWidthAngleRadian;
727 fLastSegmentAngle = 0.0;
729 else
731 double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
732 if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) )
733 fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian;
735 if(nSegmentCount>1)
737 fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
738 if( fLastSegmentAngle<0 )
739 nSegmentCount--;
740 if( fLastSegmentAngle>fAngleSubdivisionRadian )
742 fLastSegmentAngle-=fAngleSubdivisionRadian;
743 nSegmentCount++;
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);
762 sal_Int32 nPoint=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);
775 P0.setX(fCos);
776 P3.setX(fCos);
777 P0.setY(-fSin);
778 P3.setY(-P0.getY());
780 P1.setX((4.0-fCos)/3.0);
781 P2.setX(P1.getX());
782 P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
783 P2.setY(-P1.getY());
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;
820 return aReturn;
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();
853 if(nOuterArcCount>0)
854 rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][0];
855 if(nOuterArcCount>1)
856 rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][nOuterArcCount-1];
857 sal_Int32 nInnerArcCount = aInnerArc.Coordinates[0].getLength();
858 if(nInnerArcCount>0)
859 rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][0];
860 if(nInnerArcCount>1)
861 rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][nInnerArcCount-1];
862 rMarkHandlePoints[0].realloc(nHandleCount);
866 return aReturn;
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 )
879 if( !xTarget.is() )
880 return 0;
882 while(fUnitCircleWidthAngleDegree>360)
883 fUnitCircleWidthAngleDegree -= 360.0;
884 while(fUnitCircleWidthAngleDegree<0)
885 fUnitCircleWidthAngleDegree += 360.0;
887 //create shape
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
893 //set properties
894 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
895 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
896 if( xProp.is())
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
915 if( xGroup.is() )
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 );
931 return xShape;
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
943 , double fDepth )
945 if( !xTarget.is() )
946 return 0;
948 while(fUnitCircleWidthAngleDegree>360)
949 fUnitCircleWidthAngleDegree -= 360.0;
950 while(fUnitCircleWidthAngleDegree<0)
951 fUnitCircleWidthAngleDegree += 360.0;
953 //create shape
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
959 //set properties
960 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
961 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
962 if( xProp.is())
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 );
976 //depth
977 xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
978 , uno::makeAny((sal_Int32)fDepth) );
980 //PercentDiagonal
981 sal_Int16 nPercentDiagonal = 0;
982 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
983 , uno::makeAny( nPercentDiagonal ) );
985 //Polygon
986 drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
987 ShapeFactory::closePolygon( aPoly );
988 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
989 , uno::makeAny( aPoly ) );
991 //DoubleSided
992 xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
993 , uno::makeAny( (sal_Bool)true) );
995 //Reduced lines
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 );
1014 return xShape;
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 )
1029 if( !xTarget.is() )
1030 return 0;
1032 //create shape
1033 uno::Reference< drawing::XShape > xShape(
1034 m_xShapeFactory->createInstance( C2U(
1035 "com.sun.star.drawing.Shape3DPolygonObject" ) ), uno::UNO_QUERY );
1036 xTarget->add(xShape);
1038 //set properties
1039 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1040 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1041 if( xProp.is())
1045 //Polygon
1046 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
1047 , rStripe.getPolyPolygonShape3D() );
1049 //TexturePolygon
1050 xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTUREPOLYGON3D )
1051 , rStripe.getTexturePolygon( bRotatedTexture ) );
1054 //Normals Polygon
1055 xProp->setPropertyValue( C2U( UNO_NAME_3D_NORMALSPOLYGON3D )
1056 , rStripe.getNormalsPolygon() );
1058 //NormalsKind
1059 xProp->setPropertyValue( C2U( UNO_NAME_3D_NORMALS_KIND )
1060 , uno::makeAny( drawing::NormalsKind_FLAT ) );
1062 //LineOnly
1063 xProp->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY )
1064 , uno::makeAny( (sal_Bool)false) );
1066 //DoubleSided
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 );
1078 return xShape;
1081 uno::Reference< drawing::XShape >
1082 ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget
1083 , const drawing::PolyPolygonShape3D& rPolyPolygon
1084 , double fDepth )
1086 if( !xTarget.is() )
1087 return 0;
1089 if( !rPolyPolygon.SequenceX.getLength())
1090 return 0;
1092 //create shape
1093 uno::Reference< drawing::XShape > xShape(
1094 m_xShapeFactory->createInstance( C2U(
1095 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
1096 xTarget->add(xShape);
1098 //set properties
1099 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1100 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1101 if( xProp.is())
1105 //depth
1106 xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
1107 , uno::makeAny((sal_Int32)fDepth) );
1109 //PercentDiagonal
1110 sal_Int16 nPercentDiagonal = 0;
1111 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
1112 , uno::makeAny( nPercentDiagonal ) );
1114 //Polygon
1115 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
1116 , uno::makeAny( rPolyPolygon ) );
1118 //DoubleSided
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;
1129 aM.translate( 0
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 );
1142 return xShape;
1145 uno::Reference< drawing::XShape >
1146 ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget
1147 , const drawing::PolyPolygonShape3D& rPolyPolygon )
1149 if( !xTarget.is() )
1150 return 0;
1152 //create shape
1153 uno::Reference< drawing::XShape > xShape(
1154 m_xShapeFactory->createInstance( C2U(
1155 "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
1156 xTarget->add(xShape);
1158 //set properties
1159 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1160 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1161 if( xProp.is())
1165 //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
1166 drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) );
1168 //Polygon
1169 xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
1170 , uno::makeAny( aPoints ) );
1172 //ZOrder
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 );
1182 return xShape;
1185 enum SymbolType { SYMBOL_SQUARE=0
1186 , SYMBOL_DIAMOND
1187 , SYMBOL_ARROW_DOWN
1188 , SYMBOL_ARROW_UP
1189 , SYMBOL_ARROW_RIGHT
1190 , SYMBOL_ARROW_LEFT
1191 , SYMBOL_BOWTIE
1192 , SYMBOL_SANDGLASS
1193 , SYMBOL_COUNT
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 )
1219 case SYMBOL_SQUARE:
1220 case SYMBOL_DIAMOND:
1221 case SYMBOL_BOWTIE:
1222 case SYMBOL_SANDGLASS:
1223 nPointCount = 5;
1224 break;
1225 default:
1226 break;
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;
1251 switch(eSymbolType)
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;
1266 break;
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;
1281 break;
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;
1296 break;
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;
1311 break;
1313 case SYMBOL_BOWTIE:
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;
1329 break;
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;
1348 break;
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;
1366 break;
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;
1384 break;
1387 //return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
1388 return aPP;
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 )
1400 if( !xTarget.is() )
1401 return 0;
1403 //create shape
1404 uno::Reference< drawing::XShape > xShape(
1405 m_xShapeFactory->createInstance( C2U(
1406 "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
1407 xTarget->add(xShape);
1409 //set properties
1410 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1411 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1412 if( xProp.is())
1416 drawing::PointSequenceSequence aPoints( PolyToPointSequence(
1417 createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) ));
1419 //Polygon
1420 xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
1421 , uno::makeAny( aPoints ) );
1423 //LineColor
1424 xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
1425 , uno::makeAny( nBorderColor ) );
1427 //FillColor
1428 xProp->setPropertyValue( C2U( UNO_NAME_FILLCOLOR )
1429 , uno::makeAny( nFillColor ) );
1431 catch( uno::Exception& e )
1433 ASSERT_EXCEPTION( e );
1436 return xShape;
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() )
1447 return 0;
1449 // @todo: change this to a rectangle shape with a fill bitmap for
1450 // performance reasons (ask AW, said CL)
1452 //create shape
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");
1474 if( xProp.is())
1478 xProp->setPropertyValue( C2U("Graphic"), uno::makeAny( xGraphic ));
1480 catch( uno::Exception& e )
1482 ASSERT_EXCEPTION( e );
1485 return xShape;
1488 uno::Reference< drawing::XShapes >
1489 ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget
1490 , ::rtl::OUString aName )
1492 if( !xTarget.is() )
1493 return 0;
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);
1502 //set name
1503 if(aName.getLength())
1504 setShapeName( xShape , aName );
1506 {//workaround
1507 //need this null size as otherwise empty group shapes where painted with a gray border
1508 xShape->setSize(awt::Size(0,0));
1511 //return
1512 uno::Reference< drawing::XShapes > xShapes =
1513 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1514 return xShapes;
1516 catch( uno::Exception& e )
1518 ASSERT_EXCEPTION( e );
1520 return 0;
1523 uno::Reference< drawing::XShapes >
1524 ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget
1525 , ::rtl::OUString aName )
1527 if( !xTarget.is() )
1528 return 0;
1531 //create shape
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
1542 //set properties
1543 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1544 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1545 if( xProp.is())
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 );
1560 //set name
1561 if(aName.getLength())
1562 setShapeName( xShape , aName );
1564 //return
1565 uno::Reference< drawing::XShapes > xShapes =
1566 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1567 return xShapes;
1569 catch( uno::Exception& e )
1571 ASSERT_EXCEPTION( e );
1573 return 0;
1576 uno::Reference< drawing::XShape >
1577 ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget
1578 , const drawing::Position3D& rPosition
1579 , const drawing::Direction3D& rSize )
1581 if( !xTarget.is() )
1582 return 0;
1584 //create shape
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 );
1604 //set properties
1605 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1606 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1607 if( xProp.is())
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 );
1620 return xShape;
1623 uno::Reference< drawing::XShape >
1624 ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget
1625 , const drawing::PolyPolygonShape3D& rPoints
1626 , const VLineProperties& rLineProperties )
1628 if( !xTarget.is() )
1629 return 0;
1631 if(!rPoints.SequenceX.getLength())
1632 return NULL;
1634 //create shape
1635 uno::Reference< drawing::XShape > xShape(
1636 m_xShapeFactory->createInstance( C2U(
1637 "com.sun.star.drawing.Shape3DPolygonObject") ), uno::UNO_QUERY );
1638 xTarget->add(xShape);
1640 //set properties
1641 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1642 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1643 if( xProp.is())
1647 //Polygon
1648 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
1649 , uno::makeAny( rPoints ) );
1651 //LineOnly
1652 xProp->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY )
1653 , uno::makeAny( (sal_Bool)true ) );
1655 //Transparency
1656 if(rLineProperties.Transparence.hasValue())
1657 xProp->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE )
1658 , rLineProperties.Transparence );
1660 //LineStyle
1661 if(rLineProperties.LineStyle.hasValue())
1662 xProp->setPropertyValue( C2U( UNO_NAME_LINESTYLE )
1663 , rLineProperties.LineStyle );
1665 //LineWidth
1666 if(rLineProperties.Width.hasValue())
1667 xProp->setPropertyValue( C2U( UNO_NAME_LINEWIDTH )
1668 , rLineProperties.Width );
1670 //LineColor
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 );
1681 return xShape;
1684 uno::Reference< drawing::XShape >
1685 ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget
1686 , const drawing::PointSequenceSequence& rPoints
1687 , const VLineProperties* pLineProperties )
1689 if( !xTarget.is() )
1690 return 0;
1692 if(!rPoints.getLength())
1693 return NULL;
1695 //create shape
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);
1705 //set properties
1706 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1707 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1708 if( xProp.is())
1712 //Polygon
1713 xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
1714 , uno::makeAny( rPoints ) );
1716 if(pLineProperties)
1718 //Transparency
1719 if(pLineProperties->Transparence.hasValue())
1720 xProp->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE )
1721 , pLineProperties->Transparence );
1723 //LineStyle
1724 if(pLineProperties->LineStyle.hasValue())
1725 xProp->setPropertyValue( C2U( UNO_NAME_LINESTYLE )
1726 , pLineProperties->LineStyle );
1728 //LineWidth
1729 if(pLineProperties->Width.hasValue())
1730 xProp->setPropertyValue( C2U( UNO_NAME_LINEWIDTH )
1731 , pLineProperties->Width );
1733 //LineColor
1734 if(pLineProperties->Color.hasValue())
1735 xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
1736 , pLineProperties->Color );
1738 //LineDashName
1739 if(pLineProperties->DashName.hasValue())
1740 xProp->setPropertyValue( C2U( "LineDashName" )
1741 , pLineProperties->DashName );
1744 catch( uno::Exception& e )
1746 ASSERT_EXCEPTION( e );
1749 return xShape;
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 )
1788 if(!xTarget.is())
1789 return 0;
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 );
1799 return xShape;
1801 catch( uno::Exception & ex )
1803 ASSERT_EXCEPTION( ex );
1805 return 0;
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 )
1815 if( !xTarget.is() )
1816 return 0;
1818 if(!rText.getLength())
1819 return 0;
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);
1827 //set text
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 );
1833 if( xProp.is() )
1835 //set properties
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 );
1849 return xShape;
1852 //static
1853 rtl::OUString ShapeFactory::getStackedString( const rtl::OUString& rString, bool bStacked )
1855 sal_Int32 nLen = rString.getLength();
1856 if(!bStacked || !nLen)
1857 return rString;
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++ )
1866 if( nPosSrc )
1867 aStackStr.append( sal_Unicode('\r') );
1868 aStackStr.append( aSource.charAt( nPosSrc ) );
1870 return aStackStr.makeStringAndClear();
1873 //static
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 )
1879 return true;
1880 return false;
1883 //static
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));
1891 //static
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))
1897 return;
1898 drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
1899 AddPointToPoly( rPoly, aFirst );
1902 //static
1903 awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
1904 const awt::Size& rTargetSize
1905 , const awt::Size& rSourceSizeWithCorrectAspectRatio )
1907 awt::Size aNewSize;
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);
1915 return aNewSize;
1918 //static
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;
1930 //static
1931 ::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape(
1932 const uno::Reference< drawing::XShape >& xShape )
1934 ::basegfx::B2IRectangle aRet;
1936 if( xShape.is() )
1938 awt::Point aPos = xShape->getPosition();
1939 awt::Size aSize = xShape->getSize();
1940 aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
1942 return aRet;
1946 //static
1947 awt::Size ShapeFactory::getSizeAfterRotation(
1948 const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
1950 awt::Size aRet(0,0);
1951 if(xShape.is())
1953 const awt::Size aSize( xShape->getSize() );
1955 if( ::rtl::math::approxEqual( fRotationAngleDegree, 0.0 ) )
1956 aRet = aSize;
1957 else
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 ));
1980 return aRet;
1983 void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
1985 if( xShapes.is() )
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 //.............................................................................
1998 } //namespace chart
1999 //.............................................................................