fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / view / main / ShapeFactory.cxx
blob1251eafbfb491baefa98febd798f1bb228e86b1f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ShapeFactory.hxx"
21 #include "ViewDefines.hxx"
22 #include "Stripe.hxx"
23 #include "CommonConverters.hxx"
24 #include "macros.hxx"
25 #include "RelativeSizeHelper.hxx"
26 #include "PropertyMapper.hxx"
27 #include <comphelper/InlineContainer.hxx>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/drawing/CircleKind.hpp>
30 #include <com/sun/star/drawing/DoubleSequence.hpp>
31 #include <com/sun/star/drawing/FlagSequence.hpp>
32 #include <com/sun/star/drawing/FillStyle.hpp>
33 #include <com/sun/star/drawing/LineStyle.hpp>
34 #include <com/sun/star/drawing/NormalsKind.hpp>
35 #include <com/sun/star/drawing/PointSequence.hpp>
36 #include <com/sun/star/drawing/PolygonKind.hpp>
37 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
38 #include <com/sun/star/drawing/ProjectionMode.hpp>
39 #include <com/sun/star/drawing/ShadeMode.hpp>
40 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
41 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
42 #include <com/sun/star/drawing/TextureProjectionMode.hpp>
43 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
44 #include <com/sun/star/text/XText.hpp>
45 #include <com/sun/star/uno/Any.hxx>
47 #include <editeng/unoprnms.hxx>
48 #include <rtl/math.hxx>
49 #include <svx/svdocirc.hxx>
50 #include <svx/svdopath.hxx>
52 #include <basegfx/point/b2dpoint.hxx>
53 #include <basegfx/matrix/b3dhommatrix.hxx>
55 #include <algorithm>
57 using namespace ::com::sun::star;
58 using ::com::sun::star::uno::Reference;
60 namespace chart
63 uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape(
64 const uno::Reference< drawing::XDrawPage>& xDrawPage )
66 uno::Reference<drawing::XShapes> xRet = ShapeFactory::getChartRootShape(xDrawPage);
67 if (xRet.is())
68 return xRet;
70 // Create a new root shape and set it to the bottom of the page. The root
71 // shape is identified by having the name com.sun.star.chart2.shapes.
72 uno::Reference<drawing::XShape> xShape(
73 m_xShapeFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY);
74 uno::Reference<drawing::XShapes2> xShapes2(xDrawPage, uno::UNO_QUERY_THROW);
75 xShapes2->addBottom(xShape);
77 setShapeName(xShape, "com.sun.star.chart2.shapes");
78 xShape->setSize(awt::Size(0,0));
80 xRet = uno::Reference<drawing::XShapes>(xShape, uno::UNO_QUERY);
81 return xRet;
84 void ShapeFactory::setPageSize(uno::Reference< drawing::XShapes >, const awt::Size& )
88 // diverse tools::PolyPolygon create methods
90 uno::Any createPolyPolygon_Cube(
91 const drawing::Direction3D& rSize, double fRoundedEdge, bool bRounded = true )
93 OSL_PRECOND(fRoundedEdge>=0, "fRoundedEdge needs to be >= 0");
95 // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
96 if( fRoundedEdge == 0.0 && bRounded)
97 fRoundedEdge = 0.4 / 200.0;
98 else if(!bRounded)
99 fRoundedEdge = 0.0;
101 //fWidthH stands for Half Width
102 const double fWidthH = rSize.DirectionX >=0.0? rSize.DirectionX/2.0 : -rSize.DirectionX/2.0;
103 const double fHeight = rSize.DirectionY;
105 const double fHeightSign = fHeight >= 0.0 ? 1.0 : -1.0;
107 const double fOffset = (fWidthH * fRoundedEdge) * 1.05; // increase by 5% for safety
108 const bool bRoundEdges = fRoundedEdge && fOffset < fWidthH && 2.0 * fOffset < fHeightSign*fHeight;
109 const sal_Int32 nPointCount = bRoundEdges ? 13 : 5;
111 drawing::PolyPolygonShape3D aPP;
113 aPP.SequenceX.realloc(1);
114 aPP.SequenceY.realloc(1);
115 aPP.SequenceZ.realloc(1);
117 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
118 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
119 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
121 pOuterSequenceX->realloc(nPointCount);
122 pOuterSequenceY->realloc(nPointCount);
123 pOuterSequenceZ->realloc(nPointCount);
125 double* pInnerSequenceX = pOuterSequenceX->getArray();
126 double* pInnerSequenceY = pOuterSequenceY->getArray();
127 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
129 for(sal_Int32 nN = nPointCount; nN--;)
130 *pInnerSequenceZ++ = 0.0;
132 if(nPointCount == 5)
134 *pInnerSequenceY++ = 0.0;
135 *pInnerSequenceY++ = 0.0;
136 *pInnerSequenceY++ = fHeight;
137 *pInnerSequenceY++ = fHeight;
138 *pInnerSequenceY++ = 0.0;
140 *pInnerSequenceX++ = -fWidthH;
141 *pInnerSequenceX++ = fWidthH;
142 *pInnerSequenceX++ = fWidthH;
143 *pInnerSequenceX++ = -fWidthH;
144 *pInnerSequenceX++ = -fWidthH;
146 else
148 *pInnerSequenceY++ = 0.0;
149 *pInnerSequenceY++ = 0.0;
150 *pInnerSequenceY++ = 0.0;
151 *pInnerSequenceY++ = fHeightSign*fOffset;
152 *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
153 *pInnerSequenceY++ = fHeight;
154 *pInnerSequenceY++ = fHeight;
155 *pInnerSequenceY++ = fHeight;
156 *pInnerSequenceY++ = fHeight;
157 *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
158 *pInnerSequenceY++ = fHeightSign*fOffset;
159 *pInnerSequenceY++ = 0.0;
160 *pInnerSequenceY++ = 0.0;
162 *pInnerSequenceX++ = -fWidthH + fOffset;
163 *pInnerSequenceX++ = fWidthH - fOffset;
164 *pInnerSequenceX++ = fWidthH;
165 *pInnerSequenceX++ = fWidthH;
166 *pInnerSequenceX++ = fWidthH;
167 *pInnerSequenceX++ = fWidthH;
168 *pInnerSequenceX++ = fWidthH - fOffset;
169 *pInnerSequenceX++ = -fWidthH + fOffset;
170 *pInnerSequenceX++ = -fWidthH;
171 *pInnerSequenceX++ = -fWidthH;
172 *pInnerSequenceX++ = -fWidthH;
173 *pInnerSequenceX++ = -fWidthH;
174 *pInnerSequenceX++ = -fWidthH + fOffset;
176 return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
179 uno::Any createPolyPolygon_Cylinder(
180 double fHeight
181 , double fRadius
182 , sal_Int32& nVerticalSegmentCount )
184 //fHeight may be negative
185 OSL_PRECOND(fRadius>0, "The radius of a cylinder needs to be > 0");
187 drawing::PolyPolygonShape3D aPP;
189 nVerticalSegmentCount=1;
191 aPP.SequenceX.realloc(3);
192 aPP.SequenceY.realloc(3);
193 aPP.SequenceZ.realloc(3);
195 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
196 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
197 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
199 pOuterSequenceX->realloc(2);
200 pOuterSequenceY->realloc(2);
201 pOuterSequenceZ->realloc(2);
203 double* pInnerSequenceX = pOuterSequenceX->getArray();
204 double* pInnerSequenceY = pOuterSequenceY->getArray();
205 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
207 double fY1 = 0.0;
208 double fY2 = fHeight;
210 if( fHeight<0.0 )
211 ::std::swap(fY1,fY2);
213 for(sal_Int32 nN = 2; nN--;)
214 *pInnerSequenceZ++ = 0.0;
216 *pInnerSequenceX++ = 0.0;
217 *pInnerSequenceY++ = fY1;
219 *pInnerSequenceX++ = fRadius;
220 *pInnerSequenceY++ = fY1;
222 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
223 pOuterSequenceX->realloc(2);
224 pOuterSequenceY->realloc(2);
225 pOuterSequenceZ->realloc(2);
227 pInnerSequenceX = pOuterSequenceX->getArray();
228 pInnerSequenceY = pOuterSequenceY->getArray();
229 pInnerSequenceZ = pOuterSequenceZ->getArray();
231 for(sal_Int32 nN = 2; nN--;)
232 *pInnerSequenceZ++ = 0.0;
234 *pInnerSequenceX++ = fRadius;
235 *pInnerSequenceY++ = fY1;
237 *pInnerSequenceX++ = fRadius;
238 *pInnerSequenceY++ = fY2;
240 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
241 pOuterSequenceX->realloc(2);
242 pOuterSequenceY->realloc(2);
243 pOuterSequenceZ->realloc(2);
245 pInnerSequenceX = pOuterSequenceX->getArray();
246 pInnerSequenceY = pOuterSequenceY->getArray();
247 pInnerSequenceZ = pOuterSequenceZ->getArray();
249 for(sal_Int32 nN = 2; nN--;)
250 *pInnerSequenceZ++ = 0.0;
252 *pInnerSequenceX++ = fRadius;
253 *pInnerSequenceY++ = fY2;
255 *pInnerSequenceX++ = 0.0;
256 *pInnerSequenceY++ = fY2;
258 return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
261 uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double fTopHeight
262 , sal_Int32& nVerticalSegmentCount )
264 OSL_PRECOND(fRadius>0, "The radius of a cone needs to be > 0");
266 //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
267 //fTopHeight indicates the high of the cutted top only (not the full height)
268 bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight );
270 double r1= 0.0, r2 = fRadius;
271 if(bTopless)
272 // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
273 r1 = fRadius * (fTopHeight)/(fabs(fHeight)+fTopHeight);
275 nVerticalSegmentCount=1;
276 drawing::PolyPolygonShape3D aPP;
278 aPP.SequenceX.realloc(2);
279 aPP.SequenceY.realloc(2);
280 aPP.SequenceZ.realloc(2);
282 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
283 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
284 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
286 pOuterSequenceX->realloc(2);
287 pOuterSequenceY->realloc(2);
288 pOuterSequenceZ->realloc(2);
290 double* pInnerSequenceX = pOuterSequenceX->getArray();
291 double* pInnerSequenceY = pOuterSequenceY->getArray();
292 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
294 double fX1 = 0.0;
295 double fX2 = r2;
296 double fX3 = r1;
298 double fY1 = 0.0;
299 double fY2 = 0.0;
300 double fY3 = fHeight;
302 if( fHeight<0.0 )
304 ::std::swap(fX1,fX3);
305 ::std::swap(fY1,fY3);
308 for(sal_Int32 nN = 2; nN--;)
309 *pInnerSequenceZ++ = 0.0;
311 *pInnerSequenceY++ = fY1;
312 *pInnerSequenceX++ = fX1;
314 *pInnerSequenceY++ = fY2;
315 *pInnerSequenceX++ = fX2;
317 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
318 pOuterSequenceX->realloc(2);
319 pOuterSequenceY->realloc(2);
320 pOuterSequenceZ->realloc(2);
322 pInnerSequenceX = pOuterSequenceX->getArray();
323 pInnerSequenceY = pOuterSequenceY->getArray();
324 pInnerSequenceZ = pOuterSequenceZ->getArray();
326 for(sal_Int32 nN = 2; nN--;)
327 *pInnerSequenceZ++ = 0.0;
329 *pInnerSequenceY++ = fY2;
330 *pInnerSequenceX++ = fX2;
332 *pInnerSequenceY++ = fY3;
333 *pInnerSequenceX++ = fX3;
335 return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
338 // methods for 3D shape creation
340 uno::Reference<drawing::XShape>
341 ShapeFactory::createCube(
342 const uno::Reference<drawing::XShapes>& xTarget
343 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
344 , sal_Int32 nRotateZAngleHundredthDegree
345 , const uno::Reference< beans::XPropertySet >& xSourceProp
346 , const tPropertyNameMap& rPropertyNameMap
347 , bool bRounded )
349 if( !xTarget.is() )
350 return 0;
351 if( bRounded )
355 if( xSourceProp.is() )
357 drawing::LineStyle aLineStyle;
358 xSourceProp->getPropertyValue( "BorderStyle" ) >>= aLineStyle;
359 if( aLineStyle == drawing::LineStyle_SOLID )
360 bRounded = false;
363 catch( const uno::Exception& e )
365 ASSERT_EXCEPTION( e );
368 uno::Reference<drawing::XShape> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded );
369 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
370 if( xSourceProp.is())
371 PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
372 return xShape;
375 uno::Reference<drawing::XShape>
376 ShapeFactory::impl_createCube(
377 const uno::Reference<drawing::XShapes>& xTarget
378 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
379 , sal_Int32 nRotateZAngleHundredthDegree
380 , bool bRounded )
382 if( !xTarget.is() )
383 return 0;
385 //create shape
386 uno::Reference< drawing::XShape > xShape(
387 m_xShapeFactory->createInstance(
388 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
389 xTarget->add(xShape);
391 //set properties
392 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
393 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
394 if( xProp.is())
398 //depth
399 double fDepth = rSize.DirectionZ;
400 if(fDepth<0)
401 fDepth*=-1.0;
402 xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
403 , uno::makeAny((sal_Int32)fDepth) );
405 //PercentDiagonal
406 sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
407 xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
408 , uno::makeAny( nPercentDiagonal ) );
410 //Polygon
411 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
412 , createPolyPolygon_Cube( rSize, double(nPercentDiagonal)/200.0,bRounded) );
414 //Matrix for position
416 ::basegfx::B3DHomMatrix aM;
417 if(nRotateZAngleHundredthDegree!=0)
418 aM.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
419 aM.translate(rPosition.PositionX
420 , rPosition.PositionY
421 , rPosition.PositionZ - (fDepth/2.0));
422 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
423 xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
424 , uno::makeAny(aHM) );
427 catch( const uno::Exception& e )
429 ASSERT_EXCEPTION( e );
432 return xShape;
435 uno::Reference<drawing::XShape>
436 ShapeFactory::createCylinder(
437 const uno::Reference<drawing::XShapes>& xTarget
438 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
439 , sal_Int32 nRotateZAngleHundredthDegree )
441 return impl_createConeOrCylinder(
442 xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true );
445 uno::Reference<drawing::XShape>
446 ShapeFactory::createPyramid(
447 const uno::Reference<drawing::XShapes>& xTarget
448 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
449 , double fTopHeight, bool bRotateZ
450 , const uno::Reference< beans::XPropertySet >& xSourceProp
451 , const tPropertyNameMap& rPropertyNameMap )
453 if( !xTarget.is() )
454 return 0;
456 Reference< drawing::XShapes > xGroup( ShapeFactory::createGroup3D( xTarget, OUString() ) );
458 bool bDoubleSided = false;
459 short nRotatedTexture = 0;
461 const double fWidth = rSize.DirectionX;
462 const double fDepth = rSize.DirectionZ;
463 const double fHeight = rSize.DirectionY;
465 drawing::Position3D aBottomP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth/2.0 );
466 if(bRotateZ)
467 aBottomP1.PositionY -= fWidth/2.0;
468 else
469 aBottomP1.PositionX -= fWidth/2.0;
470 drawing::Position3D aBottomP2( aBottomP1 );
471 if(bRotateZ)
472 aBottomP2.PositionY += fWidth;
473 else
474 aBottomP2.PositionX += fWidth;
475 drawing::Position3D aBottomP3( aBottomP2 );
476 drawing::Position3D aBottomP4( aBottomP1 );
477 aBottomP3.PositionZ += fDepth;
478 aBottomP4.PositionZ += fDepth;
480 const double fTopFactor = (fTopHeight)/(fabs(fHeight)+fTopHeight);
481 drawing::Position3D aTopP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth*fTopFactor/2.0 );
482 if(bRotateZ)
484 aTopP1.PositionY -= fWidth*fTopFactor/2.0;
485 aTopP1.PositionX += fHeight;
487 else
489 aTopP1.PositionX -= fWidth*fTopFactor/2.0;
490 aTopP1.PositionY += fHeight;
492 drawing::Position3D aTopP2( aTopP1 );
493 if(bRotateZ)
494 aTopP2.PositionY += fWidth*fTopFactor;
495 else
496 aTopP2.PositionX += fWidth*fTopFactor;
497 drawing::Position3D aTopP3( aTopP2 );
498 drawing::Position3D aTopP4( aTopP1 );
499 aTopP3.PositionZ += fDepth*fTopFactor;
500 aTopP4.PositionZ += fDepth*fTopFactor;
502 Stripe aStripeBottom( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
504 drawing::Position3D aNormalsBottomP1( aBottomP1 );
505 drawing::Position3D aNormalsBottomP2( aBottomP2 );
506 drawing::Position3D aNormalsBottomP3( aBottomP3 );
507 drawing::Position3D aNormalsBottomP4( aBottomP4 );
508 drawing::Position3D aNormalsTopP1( aBottomP1 );
509 drawing::Position3D aNormalsTopP2( aBottomP2 );
510 drawing::Position3D aNormalsTopP3( aBottomP3 );
511 drawing::Position3D aNormalsTopP4( aBottomP4 );
512 if( bRotateZ )
514 aNormalsTopP1.PositionX += fHeight;
515 aNormalsTopP2.PositionX += fHeight;
516 aNormalsTopP3.PositionX += fHeight;
517 aNormalsTopP4.PositionX += fHeight;
519 else
521 aNormalsTopP1.PositionY += fHeight;
522 aNormalsTopP2.PositionY += fHeight;
523 aNormalsTopP3.PositionY += fHeight;
524 aNormalsTopP4.PositionY += fHeight;
527 bool bInvertPolygon = false;
528 bool bInvertNormals = false;
530 if(bRotateZ)
532 //bars
533 if(fHeight>=0.0)
535 nRotatedTexture = 2;
536 bInvertNormals = true;
537 aStripeBottom = Stripe( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
539 else
541 bInvertPolygon = true;
542 nRotatedTexture = 1;
543 aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
546 else
548 //columns
549 if(fHeight>=0.0)
551 bInvertPolygon = true;
552 nRotatedTexture = 2;
553 aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
555 else
557 nRotatedTexture = 3;
558 bInvertNormals = true;
559 aStripeBottom = Stripe( aBottomP4, aBottomP3, aBottomP2, aBottomP1 );
562 aStripeBottom.InvertNormal(true);
564 Stripe aStripe1( aTopP2, aTopP1, aBottomP1, aBottomP2 );
565 Stripe aStripe2( aTopP3, aTopP2, aBottomP2, aBottomP3 );
566 Stripe aStripe3( aTopP4, aTopP3, aBottomP3, aBottomP4 );
567 Stripe aStripe4( aTopP1, aTopP4, aBottomP4, aBottomP1 );
569 if( bInvertPolygon )
571 aStripe1 = Stripe( aBottomP1, aTopP1, aTopP2, aBottomP2 );
572 aStripe2 = Stripe( aBottomP2, aTopP2, aTopP3, aBottomP3 );
573 aStripe3 = Stripe( aBottomP3, aTopP3, aTopP4, aBottomP4 );
574 aStripe4 = Stripe( aBottomP4, aTopP4, aTopP1, aBottomP1 );
577 Stripe aNormalsStripe1( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP2, aNormalsTopP2 );
578 Stripe aNormalsStripe2( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP3, aNormalsTopP3 );
579 Stripe aNormalsStripe3( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP4, aNormalsTopP4 );
580 Stripe aNormalsStripe4( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP1, aNormalsTopP1 );
582 if( bInvertNormals )
584 aNormalsStripe1 = Stripe( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP1, aNormalsTopP1 );
585 aNormalsStripe2 = Stripe( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP2, aNormalsTopP2 );
586 aNormalsStripe3 = Stripe( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP3, aNormalsTopP3 );
587 aNormalsStripe4 = Stripe( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP4, aNormalsTopP4 );
590 aStripe1.SetManualNormal( aNormalsStripe1.getNormal() );
591 aStripe2.SetManualNormal( aNormalsStripe2.getNormal() );
592 aStripe3.SetManualNormal( aNormalsStripe3.getNormal() );
593 aStripe4.SetManualNormal( aNormalsStripe4.getNormal() );
595 const bool bFlatNormals = false;
596 ShapeFactory::createStripe( xGroup, aStripe1, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
597 ShapeFactory::createStripe( xGroup, aStripe2, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
598 ShapeFactory::createStripe( xGroup, aStripe3, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
599 ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
600 ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
602 return Reference< drawing::XShape >( xGroup, uno::UNO_QUERY );
605 uno::Reference<drawing::XShape>
606 ShapeFactory::createCone(
607 const uno::Reference<drawing::XShapes>& xTarget
608 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
609 , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree )
611 return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree );
614 uno::Reference<drawing::XShape>
615 ShapeFactory::impl_createConeOrCylinder(
616 const uno::Reference<drawing::XShapes>& xTarget
617 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
618 , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
619 , bool bCylinder )
621 if( !xTarget.is() )
622 return 0;
624 //create shape
625 uno::Reference< drawing::XShape > xShape(
626 m_xShapeFactory->createInstance(
627 "com.sun.star.drawing.Shape3DLatheObject" ), uno::UNO_QUERY );
628 xTarget->add(xShape);
630 double fWidth = rSize.DirectionX/2.0; //The depth will be corrrected within Matrix
631 double fRadius = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
632 double fHeight = rSize.DirectionY;
634 //set properties
635 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
636 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
637 if( xProp.is())
641 //PercentDiagonal
642 sal_Int16 nPercentDiagonal = 5;
643 xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
644 , uno::makeAny( nPercentDiagonal ) );
646 //Polygon
647 sal_Int32 nVerticalSegmentCount = 0;
648 uno::Any aPPolygon = bCylinder ? createPolyPolygon_Cylinder(
649 fHeight, fRadius, nVerticalSegmentCount)
650 : createPolyPolygon_Cone(
651 fHeight, fRadius, fTopHeight, nVerticalSegmentCount);
652 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D, aPPolygon );
654 //Matrix for position
656 ::basegfx::B3DHomMatrix aM;
657 if(nRotateZAngleHundredthDegree!=0)
658 aM.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
659 //stretch the symmetric objects to given depth
660 aM.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX);
661 aM.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ);
662 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
663 xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
664 , uno::makeAny(aHM) );
667 //Segments
668 xProp->setPropertyValue( UNO_NAME_3D_HORZ_SEGS
669 , uno::makeAny(CHART_3DOBJECT_SEGMENTCOUNT) );
670 xProp->setPropertyValue( UNO_NAME_3D_VERT_SEGS
671 , uno::makeAny((sal_Int32)nVerticalSegmentCount) );//depends on point count of the used polygon
673 //Reduced lines
674 xProp->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
675 , uno::makeAny(true) );
677 catch( const uno::Exception& e )
679 ASSERT_EXCEPTION( e );
682 return xShape;
685 void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, bool bAppendInverse )
687 if(!rAdd.Coordinates.getLength())
688 return;
689 sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
690 if(!nAddCount)
691 return;
693 sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
695 rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1);
696 rReturn.Flags[0].realloc(nOldCount+nAddCount+1);
698 for(sal_Int32 nN=0;nN<nAddCount; nN++ )
700 sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
701 rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd];
702 rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd];
705 //close
706 rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0];
707 rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0];
710 drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
711 double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
712 , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
713 , const double fAngleSubdivisionRadian )
715 //at least one polygon is created using two normal and two control points
716 //if the angle is larger it is separated into multiple sub angles
718 drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
719 sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
720 if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
721 nSegmentCount++;
723 double fFirstSegmentAngle = fAngleSubdivisionRadian;
724 double fLastSegmentAngle = fAngleSubdivisionRadian;
725 if(nSegmentCount==1)
727 fFirstSegmentAngle = fWidthAngleRadian;
728 fLastSegmentAngle = 0.0;
730 else
732 double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
733 if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) )
734 fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian;
736 if(nSegmentCount>1)
738 fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
739 if( fLastSegmentAngle<0 )
740 nSegmentCount--;
741 if( fLastSegmentAngle>fAngleSubdivisionRadian )
743 fLastSegmentAngle-=fAngleSubdivisionRadian;
744 nSegmentCount++;
749 sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
751 aReturn.Coordinates = drawing::PointSequenceSequence(1);
752 aReturn.Flags = drawing::FlagSequenceSequence(1);
754 drawing::PointSequence aPoints(nPointCount);
755 drawing::FlagSequence aFlags(nPointCount);
757 //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
758 ::basegfx::B2DPoint P0,P1,P2,P3;
760 sal_Int32 nPoint=0;
761 double fCurrentRotateAngle = fStartAngleRadian;
762 for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
764 double fCurrentSegmentAngle = fAngleSubdivisionRadian;
765 if(nSegment==0)//first segment gets only a smaller peace until the next subdevision
766 fCurrentSegmentAngle = fFirstSegmentAngle;
767 else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
768 fCurrentSegmentAngle = fLastSegmentAngle;
770 //first create untransformed points for a unit circle arc:
771 const double fCos = cos(fCurrentSegmentAngle/2.0);
772 const double fSin = sin(fCurrentSegmentAngle/2.0);
773 P0.setX(fCos);
774 P3.setX(fCos);
775 P0.setY(-fSin);
776 P3.setY(-P0.getY());
778 P1.setX((4.0-fCos)/3.0);
779 P2.setX(P1.getX());
780 P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
781 P2.setY(-P1.getY());
782 //transform thus startangle equals NULL
783 ::basegfx::B2DHomMatrix aStart;
784 aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
785 fCurrentRotateAngle+=fCurrentSegmentAngle;
787 aStart.scale( fUnitRadius, fUnitRadius );
789 //apply given transformation to get final points
790 P0 = rTransformationFromUnitCircle*(aStart*P0);
791 P1 = rTransformationFromUnitCircle*(aStart*P1);
792 P2 = rTransformationFromUnitCircle*(aStart*P2);
793 P3 = rTransformationFromUnitCircle*(aStart*P3);
795 aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
796 aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
797 aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
799 aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
800 aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
801 aFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
803 aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
804 aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
805 aFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
807 if(nSegment==(nSegmentCount-1))
809 aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
810 aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
811 aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
815 aReturn.Coordinates[0] = aPoints;
816 aReturn.Flags[0] = aFlags;
818 return aReturn;
821 drawing::PolyPolygonBezierCoords getRingBezierCoords(
822 double fUnitCircleInnerRadius
823 , double fUnitCircleOuterRadius
824 , double fStartAngleRadian, double fWidthAngleRadian
825 , ::basegfx::B2DHomMatrix aTransformationFromUnitCircle
826 , const double fAngleSubdivisionRadian )
828 drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
830 aReturn.Coordinates = drawing::PointSequenceSequence(1);
831 aReturn.Flags = drawing::FlagSequenceSequence(1);
833 drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
834 fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
835 aReturn.Coordinates[0] = aOuterArc.Coordinates[0];
836 aReturn.Flags[0] = aOuterArc.Flags[0];
838 drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
839 fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
840 appendAndCloseBezierCoords( aReturn, aInnerArc, true );
842 return aReturn;
845 uno::Reference< drawing::XShape >
846 ShapeFactory::createPieSegment2D(
847 const uno::Reference< drawing::XShapes >& xTarget
848 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
849 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
850 , const drawing::Direction3D& rOffset
851 , const drawing::HomogenMatrix& rUnitCircleToScene )
853 if( !xTarget.is() )
854 return 0;
856 while(fUnitCircleWidthAngleDegree>360)
857 fUnitCircleWidthAngleDegree -= 360.0;
858 while(fUnitCircleWidthAngleDegree<0)
859 fUnitCircleWidthAngleDegree += 360.0;
861 //create shape
862 uno::Reference< drawing::XShape > xShape(
863 m_xShapeFactory->createInstance(
864 "com.sun.star.drawing.ClosedBezierShape" ), uno::UNO_QUERY );
865 xTarget->add(xShape); //need to add the shape before setting of properties
867 //set properties
868 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
869 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
870 if( xProp.is())
874 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
875 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
877 const double fAngleSubdivisionRadian = F_PI/10.0;
879 drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
880 fUnitCircleInnerRadius, fUnitCircleOuterRadius
881 , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
882 , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
884 xProp->setPropertyValue( "PolyPolygonBezier", uno::makeAny( aCoords ) );
886 catch( const uno::Exception& e )
888 ASSERT_EXCEPTION( e );
892 return xShape;
895 uno::Reference< drawing::XShape >
896 ShapeFactory::createPieSegment(
897 const uno::Reference< drawing::XShapes >& xTarget
898 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
899 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
900 , const drawing::Direction3D& rOffset
901 , const drawing::HomogenMatrix& rUnitCircleToScene
902 , double fDepth )
904 if( !xTarget.is() )
905 return 0;
907 while(fUnitCircleWidthAngleDegree>360)
908 fUnitCircleWidthAngleDegree -= 360.0;
909 while(fUnitCircleWidthAngleDegree<0)
910 fUnitCircleWidthAngleDegree += 360.0;
912 //create shape
913 uno::Reference< drawing::XShape > xShape(
914 m_xShapeFactory->createInstance(
915 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
916 xTarget->add(xShape); //need to add the shape before setting of properties
918 //set properties
919 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
920 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
921 if( xProp.is())
925 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
926 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
928 const double fAngleSubdivisionRadian = F_PI/32.0;
930 drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
931 fUnitCircleInnerRadius, fUnitCircleOuterRadius
932 , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
933 , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
935 //depth
936 xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
937 , uno::makeAny((sal_Int32)fDepth) );
939 //PercentDiagonal
940 sal_Int16 nPercentDiagonal = 0;
941 xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
942 , uno::makeAny( nPercentDiagonal ) );
944 //Polygon
945 drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
946 ShapeFactory::closePolygon( aPoly );
947 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
948 , uno::makeAny( aPoly ) );
950 //DoubleSided
951 xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
952 , uno::makeAny( true ) );
954 //Reduced lines
955 xProp->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
956 , uno::makeAny( true ) );
958 //TextureProjectionMode
959 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
960 , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
962 //TextureProjectionMode
963 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X
964 , uno::makeAny( drawing::TextureProjectionMode_PARALLEL ) );
965 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
966 , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
968 catch( const uno::Exception& e )
970 ASSERT_EXCEPTION( e );
973 return xShape;
976 uno::Reference< drawing::XShape >
977 ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& xTarget
978 , const Stripe& rStripe
979 , const uno::Reference< beans::XPropertySet >& xSourceProp
980 , const tPropertyNameMap& rPropertyNameMap
981 , bool bDoubleSided
982 , short nRotatedTexture
983 , bool bFlatNormals )
985 if( !xTarget.is() )
986 return 0;
988 //create shape
989 uno::Reference< drawing::XShape > xShape(
990 m_xShapeFactory->createInstance(
991 "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY );
992 xTarget->add(xShape);
994 //set properties
995 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
996 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
997 if( xProp.is())
1001 //Polygon
1002 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
1003 , rStripe.getPolyPolygonShape3D() );
1005 //TexturePolygon
1006 xProp->setPropertyValue( UNO_NAME_3D_TEXTUREPOLYGON3D
1007 , Stripe::getTexturePolygon( nRotatedTexture ) );
1009 //Normals Polygon
1010 xProp->setPropertyValue( UNO_NAME_3D_NORMALSPOLYGON3D
1011 , rStripe.getNormalsPolygon() );
1012 //NormalsKind
1013 if(bFlatNormals)
1014 xProp->setPropertyValue( UNO_NAME_3D_NORMALS_KIND
1015 , uno::makeAny( drawing::NormalsKind_FLAT ) );
1017 //LineOnly
1018 xProp->setPropertyValue( UNO_NAME_3D_LINEONLY
1019 , uno::makeAny( false) );
1021 //DoubleSided
1022 xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
1023 , uno::makeAny(bDoubleSided) );
1025 if( xSourceProp.is())
1026 PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
1028 catch( const uno::Exception& e )
1030 ASSERT_EXCEPTION( e );
1033 return xShape;
1036 uno::Reference< drawing::XShape >
1037 ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget
1038 , const drawing::PolyPolygonShape3D& rPolyPolygon
1039 , double fDepth )
1041 if( !xTarget.is() )
1042 return 0;
1044 if( !rPolyPolygon.SequenceX.getLength())
1045 return 0;
1047 //create shape
1048 uno::Reference< drawing::XShape > xShape(
1049 m_xShapeFactory->createInstance(
1050 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
1051 xTarget->add(xShape);
1053 //set properties
1054 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1055 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1056 if( xProp.is())
1060 //depth
1061 xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
1062 , uno::makeAny((sal_Int32)fDepth) );
1064 //PercentDiagonal
1065 sal_Int16 nPercentDiagonal = 0;
1066 xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
1067 , uno::makeAny( nPercentDiagonal ) );
1069 //Polygon
1070 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
1071 , uno::makeAny( rPolyPolygon ) );
1073 //DoubleSided
1074 xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
1075 , uno::makeAny( true) );
1077 //the z component of the polygon is now ignored by the drawing layer,
1078 //so we nned to translate the object via transformation matrix
1080 //Matrix for position
1081 if( rPolyPolygon.SequenceZ.getLength()&& rPolyPolygon.SequenceZ[0].getLength() )
1083 ::basegfx::B3DHomMatrix aM;
1084 aM.translate( 0
1086 , rPolyPolygon.SequenceZ[0][0] );
1087 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
1088 xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
1089 , uno::makeAny(aHM) );
1092 catch( const uno::Exception& e )
1094 ASSERT_EXCEPTION( e );
1097 return xShape;
1100 uno::Reference< drawing::XShape >
1101 ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget
1102 , const drawing::PolyPolygonShape3D& rPolyPolygon )
1104 if( !xTarget.is() )
1105 return 0;
1107 //create shape
1108 uno::Reference< drawing::XShape > xShape(
1109 m_xShapeFactory->createInstance(
1110 "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY );
1111 xTarget->add(xShape);
1113 //set properties
1114 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1115 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1116 if( xProp.is())
1120 //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
1121 drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) );
1123 //Polygon
1124 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1125 , uno::makeAny( aPoints ) );
1127 //ZOrder
1128 //an area should always be behind other shapes
1129 xProp->setPropertyValue( UNO_NAME_MISC_OBJ_ZORDER
1130 , uno::makeAny( sal_Int32(0) ) );
1132 catch( const uno::Exception& e )
1134 ASSERT_EXCEPTION( e );
1137 return xShape;
1140 drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Position3D& rPos
1141 , const drawing::Direction3D& rSize
1142 , sal_Int32 nStandardSymbol )
1144 if(nStandardSymbol<0)
1145 nStandardSymbol*=-1;
1146 nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
1147 SymbolEnum eSymbolType=static_cast<SymbolEnum>(nStandardSymbol);
1149 const double& fX = rPos.PositionX;
1150 const double& fY = rPos.PositionY;
1152 const double fWidthH = rSize.DirectionX/2.0; //fWidthH stands for Half Width
1153 const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
1155 const sal_Int32 nQuarterCount = 35; // points inside a quadrant, used in case circle
1157 sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
1158 switch( eSymbolType )
1160 case Symbol_Square:
1161 case Symbol_Diamond:
1162 case Symbol_Bowtie:
1163 case Symbol_Sandglass:
1164 case Symbol_HorizontalBar:
1165 case Symbol_VerticalBar:
1166 nPointCount = 5;
1167 break;
1168 case Symbol_X:
1169 nPointCount = 13;
1170 break;
1171 case Symbol_Plus:
1172 nPointCount = 13;
1173 break;
1174 case Symbol_Star:
1175 nPointCount = 9;
1176 break;
1177 case Symbol_Asterisk:
1178 nPointCount = 19;
1179 break;
1180 case Symbol_Circle:
1181 nPointCount = 5 + 4 * nQuarterCount;
1182 break;
1183 default:
1184 break;
1187 drawing::PolyPolygonShape3D aPP;
1189 aPP.SequenceX.realloc(1);
1190 aPP.SequenceY.realloc(1);
1191 aPP.SequenceZ.realloc(1);
1193 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
1194 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
1195 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
1197 pOuterSequenceX->realloc(nPointCount);
1198 pOuterSequenceY->realloc(nPointCount);
1199 pOuterSequenceZ->realloc(nPointCount);
1201 double* pInnerSequenceX = pOuterSequenceX->getArray();
1202 double* pInnerSequenceY = pOuterSequenceY->getArray();
1203 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
1205 for(sal_Int32 nN = nPointCount; nN--;)
1206 *pInnerSequenceZ++ = 0.0;
1208 switch(eSymbolType)
1210 case Symbol_Square:
1212 *pInnerSequenceX++ = fX-fWidthH;
1213 *pInnerSequenceY++ = fY-fHeightH;
1215 *pInnerSequenceX++ = fX-fWidthH;
1216 *pInnerSequenceY++ = fY+fHeightH;
1218 *pInnerSequenceX++ = fX+fWidthH;
1219 *pInnerSequenceY++ = fY+fHeightH;
1221 *pInnerSequenceX++ = fX+fWidthH;
1222 *pInnerSequenceY++ = fY-fHeightH;
1224 *pInnerSequenceX++ = fX-fWidthH;
1225 *pInnerSequenceY++ = fY-fHeightH;
1226 break;
1228 case Symbol_UpArrow:
1230 *pInnerSequenceX++ = fX-fWidthH;
1231 *pInnerSequenceY++ = fY+fHeightH;
1233 *pInnerSequenceX++ = fX+fWidthH;
1234 *pInnerSequenceY++ = fY+fHeightH;
1236 *pInnerSequenceX++ = fX;
1237 *pInnerSequenceY++ = fY-fHeightH;
1239 *pInnerSequenceX++ = fX-fWidthH;
1240 *pInnerSequenceY++ = fY+fHeightH;
1241 break;
1243 case Symbol_DownArrow:
1245 *pInnerSequenceX++ = fX-fWidthH;
1246 *pInnerSequenceY++ = fY-fHeightH;
1248 *pInnerSequenceX++ = fX;
1249 *pInnerSequenceY++ = fY+fHeightH;
1251 *pInnerSequenceX++ = fX+fWidthH;
1252 *pInnerSequenceY++ = fY-fHeightH;
1254 *pInnerSequenceX++ = fX-fWidthH;
1255 *pInnerSequenceY++ = fY-fHeightH;
1256 break;
1258 case Symbol_RightArrow:
1260 *pInnerSequenceX++ = fX-fWidthH;
1261 *pInnerSequenceY++ = fY-fHeightH;
1263 *pInnerSequenceX++ = fX-fWidthH;
1264 *pInnerSequenceY++ = fY+fHeightH;
1266 *pInnerSequenceX++ = fX+fWidthH;
1267 *pInnerSequenceY++ = fY;
1269 *pInnerSequenceX++ = fX-fWidthH;
1270 *pInnerSequenceY++ = fY-fHeightH;
1271 break;
1273 case Symbol_LeftArrow:
1275 *pInnerSequenceX++ = fX-fWidthH;
1276 *pInnerSequenceY++ = fY;
1278 *pInnerSequenceX++ = fX+fWidthH;
1279 *pInnerSequenceY++ = fY+fHeightH;
1281 *pInnerSequenceX++ = fX+fWidthH;
1282 *pInnerSequenceY++ = fY-fHeightH;
1284 *pInnerSequenceX++ = fX-fWidthH;
1285 *pInnerSequenceY++ = fY;
1286 break;
1288 case Symbol_Bowtie:
1290 *pInnerSequenceX++ = fX-fWidthH;
1291 *pInnerSequenceY++ = fY-fHeightH;
1293 *pInnerSequenceX++ = fX-fWidthH;
1294 *pInnerSequenceY++ = fY+fHeightH;
1296 *pInnerSequenceX++ = fX+fWidthH;
1297 *pInnerSequenceY++ = fY-fHeightH;
1299 *pInnerSequenceX++ = fX+fWidthH;
1300 *pInnerSequenceY++ = fY+fHeightH;
1302 *pInnerSequenceX++ = fX-fWidthH;
1303 *pInnerSequenceY++ = fY-fHeightH;
1304 break;
1306 case Symbol_Sandglass:
1308 *pInnerSequenceX++ = fX-fWidthH;
1309 *pInnerSequenceY++ = fY+fHeightH;
1311 *pInnerSequenceX++ = fX+fWidthH;
1312 *pInnerSequenceY++ = fY+fHeightH;
1314 *pInnerSequenceX++ = fX-fWidthH;
1315 *pInnerSequenceY++ = fY-fHeightH;
1317 *pInnerSequenceX++ = fX+fWidthH;
1318 *pInnerSequenceY++ = fY-fHeightH;
1320 *pInnerSequenceX++ = fX-fWidthH;
1321 *pInnerSequenceY++ = fY+fHeightH;
1322 break;
1324 case Symbol_Diamond:
1326 *pInnerSequenceX++ = fX-fWidthH;
1327 *pInnerSequenceY++ = fY;
1329 *pInnerSequenceX++ = fX;
1330 *pInnerSequenceY++ = fY+fHeightH;
1332 *pInnerSequenceX++ = fX+fWidthH;
1333 *pInnerSequenceY++ = fY;
1335 *pInnerSequenceX++ = fX;
1336 *pInnerSequenceY++ = fY-fHeightH;
1338 *pInnerSequenceX++ = fX-fWidthH;
1339 *pInnerSequenceY++ = fY;
1340 break;
1342 case Symbol_HorizontalBar:
1344 *pInnerSequenceX++ = fX-fWidthH;
1345 *pInnerSequenceY++ = fY-0.2*fHeightH;
1347 *pInnerSequenceX++ = fX+fWidthH;
1348 *pInnerSequenceY++ = fY-0.2*fHeightH;
1350 *pInnerSequenceX++ = fX+fWidthH;
1351 *pInnerSequenceY++ = fY+0.2*fHeightH;
1353 *pInnerSequenceX++ = fX-fWidthH;
1354 *pInnerSequenceY++ = fY+0.2*fHeightH;
1356 *pInnerSequenceX++ = fX-fWidthH;
1357 *pInnerSequenceY++ = fY-0.2*fHeightH;
1358 break;
1360 case Symbol_VerticalBar:
1362 *pInnerSequenceX++ = fX-0.2*fWidthH;
1363 *pInnerSequenceY++ = fY-fHeightH;
1365 *pInnerSequenceX++ = fX+0.2*fWidthH;
1366 *pInnerSequenceY++ = fY-fHeightH;
1368 *pInnerSequenceX++ = fX+0.2*fWidthH;
1369 *pInnerSequenceY++ = fY+fHeightH;
1371 *pInnerSequenceX++ = fX-0.2*fWidthH;
1372 *pInnerSequenceY++ = fY+fHeightH;
1374 *pInnerSequenceX++ = fX-0.2*fWidthH;
1375 *pInnerSequenceY++ = fY-fHeightH;
1377 break;
1379 case Symbol_Circle:
1381 double fOmega = 1.5707963267948966192 / (nQuarterCount + 1.0);
1382 // one point in the middle of each edge to get full size bounding rectangle
1383 *pInnerSequenceX++ = fX + fWidthH;
1384 *pInnerSequenceY++ = fY;
1385 // 0 to PI/2
1386 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1388 *pInnerSequenceX++ = fX + fWidthH * cos( i * fOmega );
1389 *pInnerSequenceY++ = fY - fHeightH * sin( i * fOmega );
1391 // PI/2 to PI
1392 *pInnerSequenceX++ = fX;
1393 *pInnerSequenceY++ = fY - fHeightH;
1394 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1396 *pInnerSequenceX++ = fX - fWidthH * sin( i * fOmega);
1397 *pInnerSequenceY++ = fY - fHeightH * cos( i * fOmega);
1399 // PI to 3/2*PI
1400 *pInnerSequenceX++ = fX - fWidthH;
1401 *pInnerSequenceY++ = fY;
1402 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1404 *pInnerSequenceX++ = fX - fWidthH * cos( i * fOmega);
1405 *pInnerSequenceY++ = fY + fHeightH * sin( i * fOmega);
1407 // 3/2*PI to 2*PI
1408 *pInnerSequenceX++ = fX;
1409 *pInnerSequenceY++ = fY + fHeightH;
1410 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1412 *pInnerSequenceX++ = fX + fWidthH * sin(i * fOmega);
1413 *pInnerSequenceY++ = fY + fHeightH * cos(i * fOmega);
1415 // close polygon
1416 *pInnerSequenceX++ = fX + fWidthH;
1417 *pInnerSequenceY++ = fY;
1418 break;
1420 case Symbol_Star:
1422 *pInnerSequenceX++ = fX;
1423 *pInnerSequenceY++ = fY-fHeightH;
1425 *pInnerSequenceX++ = fX+0.2*fWidthH;
1426 *pInnerSequenceY++ = fY-0.2*fHeightH;
1428 *pInnerSequenceX++ = fX+fWidthH;
1429 *pInnerSequenceY++ = fY;
1431 *pInnerSequenceX++ = fX+0.2*fWidthH;
1432 *pInnerSequenceY++ = fY+0.2*fHeightH;
1434 *pInnerSequenceX++ = fX;
1435 *pInnerSequenceY++ = fY+fHeightH;
1437 *pInnerSequenceX++ = fX-0.2*fWidthH;
1438 *pInnerSequenceY++ = fY+0.2*fHeightH;
1440 *pInnerSequenceX++ = fX-fWidthH;
1441 *pInnerSequenceY++ = fY;
1443 *pInnerSequenceX++ = fX-0.2*fWidthH;
1444 *pInnerSequenceY++ = fY-0.2*fHeightH;
1446 *pInnerSequenceX++ = fX;
1447 *pInnerSequenceY++ = fY-fHeightH;
1448 break;
1450 case Symbol_X:
1452 const double fScaleX = fWidthH / 128.0;
1453 const double fScaleY = fHeightH / 128.0;
1454 const double fSmall = sqrt(200.0);
1455 const double fLarge = 128.0 - fSmall;
1457 *pInnerSequenceX++ = fX;
1458 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1460 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1461 *pInnerSequenceY++ = fY - fHeightH;
1463 *pInnerSequenceX++ = fX - fWidthH;
1464 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1466 *pInnerSequenceX++ = fX - fScaleX * fSmall;
1467 *pInnerSequenceY++ = fY;
1469 *pInnerSequenceX++ = fX - fWidthH;
1470 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1472 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1473 *pInnerSequenceY++ = fY + fHeightH;
1475 *pInnerSequenceX++ = fX;
1476 *pInnerSequenceY++ = fY + fScaleY * fSmall;
1478 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1479 *pInnerSequenceY++ = fY + fHeightH;
1481 *pInnerSequenceX++ = fX + fWidthH;
1482 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1484 *pInnerSequenceX++ = fX + fScaleX * fSmall;
1485 *pInnerSequenceY++ = fY;
1487 *pInnerSequenceX++ = fX + fWidthH;
1488 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1490 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1491 *pInnerSequenceY++ = fY - fHeightH;
1493 *pInnerSequenceX++ = fX;
1494 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1495 break;
1498 case Symbol_Plus:
1500 const double fScaleX = fWidthH / 128.0;
1501 const double fScaleY = fHeightH / 128.0;
1502 const double fHalf = 10.0; //half line width on 256 size square
1503 const double fdX = fScaleX * fHalf;
1504 const double fdY = fScaleY * fHalf;
1506 *pInnerSequenceX++ = fX-fdX;
1507 *pInnerSequenceY++ = fY-fHeightH;
1509 *pInnerSequenceX++ = fX-fdX;
1510 *pInnerSequenceY++ = fY-fdY;
1512 *pInnerSequenceX++ = fX-fWidthH;
1513 *pInnerSequenceY++ = fY-fdY;
1515 *pInnerSequenceX++ = fX-fWidthH;
1516 *pInnerSequenceY++ = fY+fdY;
1518 *pInnerSequenceX++ = fX-fdX;
1519 *pInnerSequenceY++ = fY+fdY;
1521 *pInnerSequenceX++ = fX-fdX;
1522 *pInnerSequenceY++ = fY+fHeightH;
1524 *pInnerSequenceX++ = fX+fdX;
1525 *pInnerSequenceY++ = fY+fHeightH;
1527 *pInnerSequenceX++ = fX+fdX;
1528 *pInnerSequenceY++ = fY+fdY;
1530 *pInnerSequenceX++ = fX+fWidthH;
1531 *pInnerSequenceY++ = fY+fdY;
1533 *pInnerSequenceX++ = fX+fWidthH;
1534 *pInnerSequenceY++ = fY-fdY;
1536 *pInnerSequenceX++ = fX+fdX;
1537 *pInnerSequenceY++ = fY-fdY;
1539 *pInnerSequenceX++ = fX+fdY;
1540 *pInnerSequenceY++ = fY-fHeightH;
1542 *pInnerSequenceX++ = fX-fdX;
1543 *pInnerSequenceY++ = fY-fHeightH;
1544 break;
1547 case Symbol_Asterisk:
1549 const double fHalf = 10.0; // half line width on 256 size square
1550 const double fTwoY = fHalf * sqrt(3.0);
1551 const double fFourY = (128.0 - 2.0 * fHalf ) / sqrt(3.0);
1552 const double fThreeX = 128.0 - fHalf;
1553 const double fThreeY = fHalf * sqrt(3.0) + fFourY;
1554 const double fFiveX = 2.0 * fHalf;
1556 const double fScaleX = fWidthH / 128.0;
1557 const double fScaleY = fHeightH / 128.0;
1560 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1561 *pInnerSequenceY++ = fY-fHeightH;
1563 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1564 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1566 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1567 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1569 *pInnerSequenceX++ = fX-fWidthH;
1570 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1572 *pInnerSequenceX++ = fX-fScaleX * fFiveX;
1573 *pInnerSequenceY++ = fY;
1574 //6 as 4
1575 *pInnerSequenceX++ = fX-fWidthH;
1576 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1577 //7 as 3
1578 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1579 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1580 //8 as 2
1581 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1582 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1583 //9 as 1
1584 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1585 *pInnerSequenceY++ = fY+fHeightH;
1586 //10 as 1
1587 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1588 *pInnerSequenceY++ = fY+fHeightH;
1589 //11 as 2
1590 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1591 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1592 //12 as 3
1593 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1594 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1595 //13 as 4
1596 *pInnerSequenceX++ = fX+fWidthH;
1597 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1598 //14 as 5
1599 *pInnerSequenceX++ = fX+fScaleX * fFiveX;
1600 *pInnerSequenceY++ = fY;
1601 //15 as 4
1602 *pInnerSequenceX++ = fX+fWidthH;
1603 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1604 //16 as 3
1605 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1606 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1607 //17 as 2
1608 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1609 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1610 // 18 as 1
1611 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1612 *pInnerSequenceY++ = fY-fHeightH;
1613 // 19 = 1, closing
1614 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1615 *pInnerSequenceY++ = fY-fHeightH;
1616 break;
1618 default: //case Symbol_Square:
1620 *pInnerSequenceX++ = fX-fWidthH;
1621 *pInnerSequenceY++ = fY-fHeightH;
1623 *pInnerSequenceX++ = fX-fWidthH;
1624 *pInnerSequenceY++ = fY+fHeightH;
1626 *pInnerSequenceX++ = fX+fWidthH;
1627 *pInnerSequenceY++ = fY+fHeightH;
1629 *pInnerSequenceX++ = fX+fWidthH;
1630 *pInnerSequenceY++ = fY-fHeightH;
1632 *pInnerSequenceX++ = fX-fWidthH;
1633 *pInnerSequenceY++ = fY-fHeightH;
1634 break;
1638 return aPP;
1641 uno::Reference< drawing::XShape >
1642 ShapeFactory::createSymbol2D(
1643 const uno::Reference< drawing::XShapes >& xTarget
1644 , const drawing::Position3D& rPosition
1645 , const drawing::Direction3D& rSize
1646 , sal_Int32 nStandardSymbol
1647 , sal_Int32 nBorderColor
1648 , sal_Int32 nFillColor )
1650 if( !xTarget.is() )
1651 return 0;
1653 //create shape
1654 uno::Reference< drawing::XShape > xShape(
1655 m_xShapeFactory->createInstance(
1656 "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY );
1657 xTarget->add(xShape);
1659 //set properties
1660 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1661 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1662 if( xProp.is())
1666 drawing::PointSequenceSequence aPoints( PolyToPointSequence(
1667 createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) ));
1669 //Polygon
1670 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1671 , uno::makeAny( aPoints ) );
1673 //LineColor
1674 xProp->setPropertyValue( UNO_NAME_LINECOLOR
1675 , uno::makeAny( nBorderColor ) );
1677 //FillColor
1678 xProp->setPropertyValue( UNO_NAME_FILLCOLOR
1679 , uno::makeAny( nFillColor ) );
1681 catch( const uno::Exception& e )
1683 ASSERT_EXCEPTION( e );
1686 return xShape;
1689 uno::Reference< drawing::XShape >
1690 ShapeFactory::createGraphic2D(
1691 const uno::Reference< drawing::XShapes >& xTarget
1692 , const drawing::Position3D& rPosition
1693 , const drawing::Direction3D& rSize
1694 , const uno::Reference< graphic::XGraphic >& xGraphic )
1696 if( !xTarget.is() || !xGraphic.is() )
1697 return 0;
1699 // @todo: change this to a rectangle shape with a fill bitmap for
1700 // performance reasons (ask AW, said CL)
1702 //create shape
1703 uno::Reference< drawing::XShape > xShape(
1704 m_xShapeFactory->createInstance(
1705 "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY );
1706 xTarget->add(xShape);
1710 // assume position is upper left corner. Transform to center.
1711 drawing::Position3D aCenterPosition(
1712 rPosition.PositionX - (rSize.DirectionX / 2.0),
1713 rPosition.PositionY - (rSize.DirectionY / 2.0),
1714 rPosition.PositionZ );
1715 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1716 xShape->setSize( Direction3DToAWTSize( rSize ));
1718 catch( const uno::Exception & e )
1720 ASSERT_EXCEPTION( e );
1722 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1723 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1724 if( xProp.is())
1728 xProp->setPropertyValue( "Graphic", uno::makeAny( xGraphic ));
1730 catch( const uno::Exception& e )
1732 ASSERT_EXCEPTION( e );
1735 return xShape;
1738 uno::Reference< drawing::XShapes >
1739 ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget
1740 , const OUString& aName )
1742 if( !xTarget.is() )
1743 return 0;
1746 //create and add to target
1747 uno::Reference< drawing::XShape > xShape(
1748 m_xShapeFactory->createInstance(
1749 "com.sun.star.drawing.GroupShape" ), uno::UNO_QUERY );
1750 xTarget->add(xShape);
1752 //set name
1753 if(!aName.isEmpty())
1754 setShapeName( xShape , aName );
1756 {//workaround
1757 //need this null size as otherwise empty group shapes where painted with a gray border
1758 xShape->setSize(awt::Size(0,0));
1761 //return
1762 uno::Reference< drawing::XShapes > xShapes =
1763 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1764 return xShapes;
1766 catch( const uno::Exception& e )
1768 ASSERT_EXCEPTION( e );
1770 return 0;
1773 uno::Reference< drawing::XShapes >
1774 ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget
1775 , const OUString& aName )
1777 if( !xTarget.is() )
1778 return 0;
1781 //create shape
1782 uno::Reference< drawing::XShape > xShape(
1783 m_xShapeFactory->createInstance(
1784 "com.sun.star.drawing.Shape3DSceneObject" ), uno::UNO_QUERY );
1786 xTarget->add(xShape);
1788 //it is necessary to set the transform matrix to initialize the scene properly
1789 //otherwise all objects which are placed into this Group will not be visible
1790 //the following should be unnecessary after a the bug is fixed
1792 //set properties
1793 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1794 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1795 if( xProp.is())
1799 ::basegfx::B3DHomMatrix aM;
1800 xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
1801 , uno::makeAny(B3DHomMatrixToHomogenMatrix(aM)) );
1803 catch( const uno::Exception& e )
1805 ASSERT_EXCEPTION( e );
1810 //set name
1811 if(!aName.isEmpty())
1812 setShapeName( xShape , aName );
1814 //return
1815 uno::Reference< drawing::XShapes > xShapes =
1816 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1817 return xShapes;
1819 catch( const uno::Exception& e )
1821 ASSERT_EXCEPTION( e );
1823 return 0;
1826 uno::Reference< drawing::XShape >
1827 ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget
1828 , const drawing::Position3D& rPosition
1829 , const drawing::Direction3D& rSize )
1831 if( !xTarget.is() )
1832 return 0;
1834 //create shape
1835 uno::Reference< drawing::XShape > xShape(
1836 m_xShapeFactory->createInstance(
1837 "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY );
1838 xTarget->add(xShape);
1842 drawing::Position3D aCenterPosition(
1843 rPosition.PositionX - (rSize.DirectionX / 2.0),
1844 rPosition.PositionY - (rSize.DirectionY / 2.0),
1845 rPosition.PositionZ );
1846 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1847 xShape->setSize( Direction3DToAWTSize( rSize ));
1849 catch( const uno::Exception & e )
1851 ASSERT_EXCEPTION( e );
1854 //set properties
1855 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1856 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1857 if( xProp.is())
1861 drawing::CircleKind eKind = drawing::CircleKind_FULL;
1862 xProp->setPropertyValue( UNO_NAME_CIRCKIND
1863 , uno::makeAny( eKind ) );
1865 catch( const uno::Exception& e )
1867 ASSERT_EXCEPTION( e );
1870 return xShape;
1873 uno::Reference< drawing::XShape >
1874 ShapeFactory::createCircle( const uno::Reference< drawing::XShapes >& xTarget
1875 , const awt::Size& rSize
1876 , const awt::Point& rPosition )
1878 uno::Reference< drawing::XShape > xShape(
1879 m_xShapeFactory->createInstance(
1880 "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY );
1881 xTarget->add(xShape);
1882 xShape->setSize( rSize );
1883 xShape->setPosition( rPosition );
1885 return xShape;
1888 uno::Reference< drawing::XShape >
1889 ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget
1890 , const drawing::PolyPolygonShape3D& rPoints
1891 , const VLineProperties& rLineProperties )
1893 if( !xTarget.is() )
1894 return 0;
1896 if(!rPoints.SequenceX.getLength())
1897 return NULL;
1899 //create shape
1900 uno::Reference< drawing::XShape > xShape(
1901 m_xShapeFactory->createInstance(
1902 "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY );
1903 xTarget->add(xShape);
1905 //set properties
1906 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1907 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1908 if( xProp.is())
1912 //Polygon
1913 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
1914 , uno::makeAny( rPoints ) );
1916 //LineOnly
1917 xProp->setPropertyValue( UNO_NAME_3D_LINEONLY
1918 , uno::makeAny( true ) );
1920 //Transparency
1921 if(rLineProperties.Transparence.hasValue())
1922 xProp->setPropertyValue( UNO_NAME_LINETRANSPARENCE
1923 , rLineProperties.Transparence );
1925 //LineStyle
1926 if(rLineProperties.LineStyle.hasValue())
1927 xProp->setPropertyValue( UNO_NAME_LINESTYLE
1928 , rLineProperties.LineStyle );
1930 //LineWidth
1931 if(rLineProperties.Width.hasValue())
1932 xProp->setPropertyValue( UNO_NAME_LINEWIDTH
1933 , rLineProperties.Width );
1935 //LineColor
1936 if(rLineProperties.Color.hasValue())
1937 xProp->setPropertyValue( UNO_NAME_LINECOLOR
1938 , rLineProperties.Color );
1939 //, uno::makeAny( sal_Int32( Color(COL_RED).GetColor()) ) );
1941 catch( const uno::Exception& e )
1943 ASSERT_EXCEPTION( e );
1946 return xShape;
1949 uno::Reference< drawing::XShape >
1950 ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget
1951 , const drawing::PointSequenceSequence& rPoints
1952 , const VLineProperties* pLineProperties )
1954 if( !xTarget.is() )
1955 return 0;
1957 if(!rPoints.getLength())
1958 return NULL;
1960 //create shape
1961 uno::Reference< drawing::XShape > xShape(
1962 m_xShapeFactory->createInstance(
1963 "com.sun.star.drawing.PolyLineShape" ), uno::UNO_QUERY );
1964 xTarget->add(xShape);
1966 //set properties
1967 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1968 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1969 if( xProp.is())
1973 //Polygon
1974 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1975 , uno::makeAny( rPoints ) );
1977 if(pLineProperties)
1979 //Transparency
1980 if(pLineProperties->Transparence.hasValue())
1981 xProp->setPropertyValue( UNO_NAME_LINETRANSPARENCE
1982 , pLineProperties->Transparence );
1984 //LineStyle
1985 if(pLineProperties->LineStyle.hasValue())
1986 xProp->setPropertyValue( UNO_NAME_LINESTYLE
1987 , pLineProperties->LineStyle );
1989 //LineWidth
1990 if(pLineProperties->Width.hasValue())
1991 xProp->setPropertyValue( UNO_NAME_LINEWIDTH
1992 , pLineProperties->Width );
1994 //LineColor
1995 if(pLineProperties->Color.hasValue())
1996 xProp->setPropertyValue( UNO_NAME_LINECOLOR
1997 , pLineProperties->Color );
1999 //LineDashName
2000 if(pLineProperties->DashName.hasValue())
2001 xProp->setPropertyValue( "LineDashName"
2002 , pLineProperties->DashName );
2005 catch( const uno::Exception& e )
2007 ASSERT_EXCEPTION( e );
2010 return xShape;
2013 uno::Reference< drawing::XShape >
2014 ShapeFactory::createLine ( const uno::Reference< drawing::XShapes >& xTarget,
2015 const awt::Size& rSize, const awt::Point& rPosition )
2017 //create shape
2018 uno::Reference< drawing::XShape > xShape(
2019 m_xShapeFactory->createInstance(
2020 "com.sun.star.drawing.LineShape" ), uno::UNO_QUERY );
2021 xTarget->add(xShape);
2022 xShape->setSize( rSize );
2023 xShape->setPosition( rPosition );
2025 return xShape;
2028 uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle(
2029 const uno::Reference< drawing::XShapes >& xTarget
2030 , const awt::Size& rSize )
2034 if(!xTarget.is())
2035 return 0;
2037 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2038 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2039 if( xShape.is())
2041 xTarget->add( xShape );
2042 ShapeFactory::makeShapeInvisible( xShape );
2043 xShape->setSize( rSize );
2045 return xShape;
2047 catch( const uno::Exception & ex )
2049 ASSERT_EXCEPTION( ex );
2051 return 0;
2054 uno::Reference< drawing::XShape > ShapeFactory::createRectangle(
2055 const uno::Reference< drawing::XShapes >& xTarget,
2056 const awt::Size& rSize,
2057 const awt::Point& rPosition,
2058 const tNameSequence& rPropNames,
2059 const tAnySequence& rPropValues,
2060 StackPosition ePos )
2062 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2063 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2064 if( xShape.is())
2066 if (ePos == Bottom)
2068 uno::Reference<drawing::XShapes2> xTarget2(xTarget, uno::UNO_QUERY);
2069 if (xTarget2.is())
2070 xTarget2->addBottom(xShape);
2072 else
2073 xTarget->add(xShape);
2075 xShape->setPosition( rPosition );
2076 xShape->setSize( rSize );
2077 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY_THROW );
2078 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xPropSet );
2081 return xShape;
2084 uno::Reference< drawing::XShape >
2085 ShapeFactory::createRectangle(
2086 const uno::Reference<
2087 drawing::XShapes >& xTarget )
2089 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2090 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2091 xTarget->add( xShape );
2093 return xShape;
2096 uno::Reference< drawing::XShape >
2097 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2098 , const OUString& rText
2099 , const tNameSequence& rPropNames
2100 , const tAnySequence& rPropValues
2101 , const uno::Any& rATransformation )
2103 if( !xTarget.is() )
2104 return 0;
2106 if(rText.isEmpty())
2107 return 0;
2109 //create shape and add to page
2110 uno::Reference< drawing::XShape > xShape(
2111 m_xShapeFactory->createInstance(
2112 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2113 xTarget->add(xShape);
2115 //set text
2116 uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY );
2117 if( xTextRange.is() )
2118 xTextRange->setString( rText );
2120 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2121 if( xProp.is() )
2123 //set properties
2124 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2126 //set position matrix
2127 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2130 xProp->setPropertyValue( "Transformation", rATransformation );
2132 catch( const uno::Exception& e )
2134 ASSERT_EXCEPTION( e );
2137 return xShape;
2140 uno::Reference< drawing::XShape >
2141 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget,
2142 const awt::Size& rSize,
2143 const awt::Point& rPos,
2144 uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString,
2145 const uno::Reference<
2146 beans::XPropertySet > & xTextProperties,
2147 double nRotation, const OUString& aName )
2149 //create shape and add to page
2150 uno::Reference< drawing::XShape > xShape(
2151 m_xShapeFactory->createInstance(
2152 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2155 xTarget->add(xShape);
2157 //set text and text properties
2158 uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2159 uno::Reference< text::XTextCursor > xTextCursor( xText->createTextCursor() );
2160 uno::Reference< text::XTextRange > xTextRange( xTextCursor, uno::UNO_QUERY );
2161 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
2162 if( !xText.is() || !xTextRange.is() || !xTextCursor.is() || !xShapeProp.is() || !xTextProperties.is() )
2163 return xShape;
2165 tPropertyNameValueMap aValueMap;
2166 //fill line-, fill- and paragraph-properties into the ValueMap
2168 tMakePropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForParagraphProperties();
2169 aNameMap( PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
2171 PropertyMapper::getValueMap( aValueMap, aNameMap, xTextProperties );
2174 //fill some more shape properties into the ValueMap
2176 drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER;
2177 drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
2179 aValueMap.insert( tPropertyNameValueMap::value_type( "TextHorizontalAdjust", uno::makeAny(eHorizontalAdjust) ) ); // drawing::TextHorizontalAdjust
2180 aValueMap.insert( tPropertyNameValueMap::value_type( "TextVerticalAdjust", uno::makeAny(eVerticalAdjust) ) ); //drawing::TextVerticalAdjust
2181 aValueMap.insert( tPropertyNameValueMap::value_type( "TextAutoGrowHeight", uno::makeAny(sal_True) ) ); // sal_Bool
2182 aValueMap.insert( tPropertyNameValueMap::value_type( "TextAutoGrowWidth", uno::makeAny(sal_True) ) ); // sal_Bool
2184 //set name/classified ObjectID (CID)
2185 if( !aName.isEmpty() )
2186 aValueMap.insert( tPropertyNameValueMap::value_type( "Name", uno::makeAny( aName ) ) ); //CID OUString
2189 //set global title properties
2191 tNameSequence aPropNames;
2192 tAnySequence aPropValues;
2193 PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
2194 PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
2197 bool bStackCharacters(false);
2200 xTextProperties->getPropertyValue( "StackCharacters" ) >>= bStackCharacters;
2202 catch( const uno::Exception& e )
2204 ASSERT_EXCEPTION( e );
2207 if(bStackCharacters)
2209 //if the characters should be stacked we use only the first character properties for code simplicity
2210 if( xFormattedString.getLength()>0 )
2212 OUString aLabel;
2213 for( sal_Int32 nN=0; nN<xFormattedString.getLength();nN++ )
2214 aLabel += xFormattedString[nN]->getString();
2215 aLabel = ShapeFactory::getStackedString( aLabel, bStackCharacters );
2217 xTextCursor->gotoEnd(false);
2218 xText->insertString( xTextRange, aLabel, false );
2219 xTextCursor->gotoEnd(true);
2220 uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
2221 uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
2223 PropertyMapper::setMappedProperties( xTargetProps, xSourceProps
2224 , PropertyMapper::getPropertyNameMapForCharacterProperties() );
2226 // adapt font size according to page size
2227 awt::Size aOldRefSize;
2228 if( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize )
2230 RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize );
2234 else
2236 uno::Sequence< uno::Reference< text::XTextCursor > > aCursorList( xFormattedString.getLength() );
2237 sal_Int32 nN = 0;
2238 for( nN=0; nN<xFormattedString.getLength();nN++ )
2240 xTextCursor->gotoEnd(false);
2241 xText->insertString( xTextRange, xFormattedString[nN]->getString(), false );
2242 xTextCursor->gotoEnd(true);
2243 aCursorList[nN] = xText->createTextCursorByRange( uno::Reference< text::XTextRange >(xTextCursor,uno::UNO_QUERY) );
2245 awt::Size aOldRefSize;
2246 bool bHasRefPageSize =
2247 ( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize );
2249 if( xFormattedString.getLength()>0 )
2251 uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
2252 uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
2253 PropertyMapper::setMappedProperties( xTargetProps, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() );
2255 // adapt font size according to page size
2256 if( bHasRefPageSize )
2258 RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize );
2263 // #i109336# Improve auto positioning in chart
2264 float fFontHeight = 0.0;
2265 if ( xShapeProp.is() && ( xShapeProp->getPropertyValue( "CharHeight" ) >>= fFontHeight ) )
2267 fFontHeight *= ( 2540.0f / 72.0f ); // pt -> 1/100 mm
2268 float fXFraction = 0.18f;
2269 sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * fXFraction ) );
2270 float fYFraction = 0.30f;
2271 sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * fYFraction ) );
2272 xShapeProp->setPropertyValue( "TextLeftDistance", uno::makeAny( nXDistance ) );
2273 xShapeProp->setPropertyValue( "TextRightDistance", uno::makeAny( nXDistance ) );
2274 xShapeProp->setPropertyValue( "TextUpperDistance", uno::makeAny( nYDistance ) );
2275 xShapeProp->setPropertyValue( "TextLowerDistance", uno::makeAny( nYDistance ) );
2277 sal_Int32 nXPos = rPos.X;
2278 sal_Int32 nYPos = rPos.Y;
2280 //set position matrix
2281 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2282 ::basegfx::B2DHomMatrix aM;
2283 aM.rotate( -nRotation*F_PI/180.0 );//#i78696#->#i80521#
2284 aM.translate( nXPos, nYPos );
2285 xShapeProp->setPropertyValue( "Transformation", uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) ) );
2287 catch( const uno::Exception& e )
2289 ASSERT_EXCEPTION( e );
2291 return xShape;
2294 } //namespace chart
2296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */