Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / chart2 / source / view / main / ShapeFactory.cxx
blob159c2b893e0a7e53e0ff653c21d5c22691b15bf6
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 <RelativeSizeHelper.hxx>
25 #include <PropertyMapper.hxx>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/beans/XMultiPropertySet.hpp>
28 #include <com/sun/star/drawing/CircleKind.hpp>
29 #include <com/sun/star/drawing/DoubleSequence.hpp>
30 #include <com/sun/star/drawing/FlagSequence.hpp>
31 #include <com/sun/star/drawing/FillStyle.hpp>
32 #include <com/sun/star/drawing/LineStyle.hpp>
33 #include <com/sun/star/drawing/NormalsKind.hpp>
34 #include <com/sun/star/drawing/PointSequence.hpp>
35 #include <com/sun/star/drawing/PolygonKind.hpp>
36 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
37 #include <com/sun/star/drawing/ProjectionMode.hpp>
38 #include <com/sun/star/drawing/ShadeMode.hpp>
39 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
40 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
41 #include <com/sun/star/drawing/TextureProjectionMode.hpp>
42 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
43 #include <com/sun/star/style/ParagraphAdjust.hpp>
44 #include <com/sun/star/text/XText.hpp>
45 #include <com/sun/star/uno/Sequence.hxx>
46 #include <com/sun/star/uno/Any.hxx>
48 #include <editeng/unoprnms.hxx>
49 #include <rtl/math.hxx>
50 #include <svx/svdocirc.hxx>
51 #include <svx/svdopath.hxx>
53 #include <basegfx/point/b2dpoint.hxx>
54 #include <basegfx/matrix/b3dhommatrix.hxx>
55 #include <tools/diagnose_ex.h>
57 #include <algorithm>
59 using namespace ::com::sun::star;
60 using ::com::sun::star::uno::Reference;
62 namespace chart
65 namespace
68 void lcl_addProperty(uno::Sequence<OUString> & rPropertyNames, uno::Sequence<uno::Any> & rPropertyValues,
69 OUString const & rName, uno::Any const & rAny)
71 rPropertyNames.realloc(rPropertyNames.getLength() + 1);
72 rPropertyNames[rPropertyNames.getLength() - 1] = rName;
74 rPropertyValues.realloc(rPropertyValues.getLength() + 1);
75 rPropertyValues[rPropertyValues.getLength() - 1] = rAny;
78 } // end anonymous namespace
80 uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape(
81 const uno::Reference< drawing::XDrawPage>& xDrawPage )
83 uno::Reference<drawing::XShapes> xRet = ShapeFactory::getChartRootShape(xDrawPage);
84 if (xRet.is())
85 return xRet;
87 // Create a new root shape and set it to the bottom of the page. The root
88 // shape is identified by having the name com.sun.star.chart2.shapes.
89 uno::Reference<drawing::XShape> xShape(
90 m_xShapeFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY);
91 uno::Reference<drawing::XShapes2> xShapes2(xDrawPage, uno::UNO_QUERY_THROW);
92 xShapes2->addBottom(xShape);
94 setShapeName(xShape, "com.sun.star.chart2.shapes");
95 xShape->setSize(awt::Size(0,0));
97 xRet.set(xShape, uno::UNO_QUERY);
98 return xRet;
101 void ShapeFactory::setPageSize(uno::Reference< drawing::XShapes >, const awt::Size& )
105 // diverse tools::PolyPolygon create methods
107 uno::Any createPolyPolygon_Cube(
108 const drawing::Direction3D& rSize, double fRoundedEdge, bool bRounded )
110 OSL_PRECOND(fRoundedEdge>=0, "fRoundedEdge needs to be >= 0");
112 // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
113 if( fRoundedEdge == 0.0 && bRounded)
114 fRoundedEdge = 0.4 / 200.0;
115 else if(!bRounded)
116 fRoundedEdge = 0.0;
118 //fWidthH stands for Half Width
119 const double fWidthH = rSize.DirectionX >=0.0? rSize.DirectionX/2.0 : -rSize.DirectionX/2.0;
120 const double fHeight = rSize.DirectionY;
122 const double fHeightSign = fHeight >= 0.0 ? 1.0 : -1.0;
124 const double fOffset = (fWidthH * fRoundedEdge) * 1.05; // increase by 5% for safety
125 const bool bRoundEdges = fRoundedEdge && fOffset < fWidthH && 2.0 * fOffset < fHeightSign*fHeight;
126 const sal_Int32 nPointCount = bRoundEdges ? 13 : 5;
128 drawing::PolyPolygonShape3D aPP;
130 aPP.SequenceX.realloc(1);
131 aPP.SequenceY.realloc(1);
132 aPP.SequenceZ.realloc(1);
134 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
135 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
136 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
138 pOuterSequenceX->realloc(nPointCount);
139 pOuterSequenceY->realloc(nPointCount);
140 pOuterSequenceZ->realloc(nPointCount);
142 double* pInnerSequenceX = pOuterSequenceX->getArray();
143 double* pInnerSequenceY = pOuterSequenceY->getArray();
144 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
146 for(sal_Int32 nN = nPointCount; nN--;)
147 *pInnerSequenceZ++ = 0.0;
149 if(nPointCount == 5)
151 *pInnerSequenceY++ = 0.0;
152 *pInnerSequenceY++ = 0.0;
153 *pInnerSequenceY++ = fHeight;
154 *pInnerSequenceY++ = fHeight;
155 *pInnerSequenceY++ = 0.0;
157 *pInnerSequenceX++ = -fWidthH;
158 *pInnerSequenceX++ = fWidthH;
159 *pInnerSequenceX++ = fWidthH;
160 *pInnerSequenceX++ = -fWidthH;
161 *pInnerSequenceX++ = -fWidthH;
163 else
165 *pInnerSequenceY++ = 0.0;
166 *pInnerSequenceY++ = 0.0;
167 *pInnerSequenceY++ = 0.0;
168 *pInnerSequenceY++ = fHeightSign*fOffset;
169 *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
170 *pInnerSequenceY++ = fHeight;
171 *pInnerSequenceY++ = fHeight;
172 *pInnerSequenceY++ = fHeight;
173 *pInnerSequenceY++ = fHeight;
174 *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
175 *pInnerSequenceY++ = fHeightSign*fOffset;
176 *pInnerSequenceY++ = 0.0;
177 *pInnerSequenceY++ = 0.0;
179 *pInnerSequenceX++ = -fWidthH + fOffset;
180 *pInnerSequenceX++ = fWidthH - fOffset;
181 *pInnerSequenceX++ = fWidthH;
182 *pInnerSequenceX++ = fWidthH;
183 *pInnerSequenceX++ = fWidthH;
184 *pInnerSequenceX++ = fWidthH;
185 *pInnerSequenceX++ = fWidthH - fOffset;
186 *pInnerSequenceX++ = -fWidthH + fOffset;
187 *pInnerSequenceX++ = -fWidthH;
188 *pInnerSequenceX++ = -fWidthH;
189 *pInnerSequenceX++ = -fWidthH;
190 *pInnerSequenceX++ = -fWidthH;
191 *pInnerSequenceX++ = -fWidthH + fOffset;
193 return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
196 uno::Any createPolyPolygon_Cylinder(
197 double fHeight
198 , double fRadius
199 , sal_Int32& nVerticalSegmentCount )
201 //fHeight may be negative
202 OSL_PRECOND(fRadius>0, "The radius of a cylinder needs to be > 0");
204 drawing::PolyPolygonShape3D aPP;
206 nVerticalSegmentCount=1;
208 aPP.SequenceX.realloc(3);
209 aPP.SequenceY.realloc(3);
210 aPP.SequenceZ.realloc(3);
212 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
213 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
214 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
216 pOuterSequenceX->realloc(2);
217 pOuterSequenceY->realloc(2);
218 pOuterSequenceZ->realloc(2);
220 double* pInnerSequenceX = pOuterSequenceX->getArray();
221 double* pInnerSequenceY = pOuterSequenceY->getArray();
222 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
224 double fY1 = 0.0;
225 double fY2 = fHeight;
227 if( fHeight<0.0 )
228 std::swap(fY1,fY2);
230 for(sal_Int32 nN = 2; nN--;)
231 *pInnerSequenceZ++ = 0.0;
233 *pInnerSequenceX++ = 0.0;
234 *pInnerSequenceY++ = fY1;
236 *pInnerSequenceX++ = fRadius;
237 *pInnerSequenceY++ = fY1;
239 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
240 pOuterSequenceX->realloc(2);
241 pOuterSequenceY->realloc(2);
242 pOuterSequenceZ->realloc(2);
244 pInnerSequenceX = pOuterSequenceX->getArray();
245 pInnerSequenceY = pOuterSequenceY->getArray();
246 pInnerSequenceZ = pOuterSequenceZ->getArray();
248 for(sal_Int32 nN = 2; nN--;)
249 *pInnerSequenceZ++ = 0.0;
251 *pInnerSequenceX++ = fRadius;
252 *pInnerSequenceY++ = fY1;
254 *pInnerSequenceX++ = fRadius;
255 *pInnerSequenceY++ = fY2;
257 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
258 pOuterSequenceX->realloc(2);
259 pOuterSequenceY->realloc(2);
260 pOuterSequenceZ->realloc(2);
262 pInnerSequenceX = pOuterSequenceX->getArray();
263 pInnerSequenceY = pOuterSequenceY->getArray();
264 pInnerSequenceZ = pOuterSequenceZ->getArray();
266 for(sal_Int32 nN = 2; nN--;)
267 *pInnerSequenceZ++ = 0.0;
269 *pInnerSequenceX++ = fRadius;
270 *pInnerSequenceY++ = fY2;
272 *pInnerSequenceX++ = 0.0;
273 *pInnerSequenceY++ = fY2;
275 return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
278 uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double fTopHeight
279 , sal_Int32& nVerticalSegmentCount )
281 OSL_PRECOND(fRadius>0, "The radius of a cone needs to be > 0");
283 //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
284 //fTopHeight indicates the high of the cutted top only (not the full height)
285 bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight );
287 double r1= 0.0, r2 = fRadius;
288 if(bTopless)
289 // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
290 r1 = fRadius * fTopHeight/(fabs(fHeight)+fTopHeight);
292 nVerticalSegmentCount=1;
293 drawing::PolyPolygonShape3D aPP;
295 aPP.SequenceX.realloc(2);
296 aPP.SequenceY.realloc(2);
297 aPP.SequenceZ.realloc(2);
299 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
300 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
301 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
303 pOuterSequenceX->realloc(2);
304 pOuterSequenceY->realloc(2);
305 pOuterSequenceZ->realloc(2);
307 double* pInnerSequenceX = pOuterSequenceX->getArray();
308 double* pInnerSequenceY = pOuterSequenceY->getArray();
309 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
311 double fX1 = 0.0;
312 double fX2 = r2;
313 double fX3 = r1;
315 double fY1 = 0.0;
316 double fY2 = 0.0;
317 double fY3 = fHeight;
319 if( fHeight<0.0 )
321 std::swap(fX1,fX3);
322 std::swap(fY1,fY3);
325 for(sal_Int32 nN = 2; nN--;)
326 *pInnerSequenceZ++ = 0.0;
328 *pInnerSequenceY++ = fY1;
329 *pInnerSequenceX++ = fX1;
331 *pInnerSequenceY++ = fY2;
332 *pInnerSequenceX++ = fX2;
334 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
335 pOuterSequenceX->realloc(2);
336 pOuterSequenceY->realloc(2);
337 pOuterSequenceZ->realloc(2);
339 pInnerSequenceX = pOuterSequenceX->getArray();
340 pInnerSequenceY = pOuterSequenceY->getArray();
341 pInnerSequenceZ = pOuterSequenceZ->getArray();
343 for(sal_Int32 nN = 2; nN--;)
344 *pInnerSequenceZ++ = 0.0;
346 *pInnerSequenceY++ = fY2;
347 *pInnerSequenceX++ = fX2;
349 *pInnerSequenceY++ = fY3;
350 *pInnerSequenceX++ = fX3;
352 return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
355 // methods for 3D shape creation
357 uno::Reference<drawing::XShape>
358 ShapeFactory::createCube(
359 const uno::Reference<drawing::XShapes>& xTarget
360 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
361 , sal_Int32 nRotateZAngleHundredthDegree
362 , const uno::Reference< beans::XPropertySet >& xSourceProp
363 , const tPropertyNameMap& rPropertyNameMap
364 , bool bRounded )
366 if( !xTarget.is() )
367 return nullptr;
368 if( bRounded )
372 if( xSourceProp.is() )
374 drawing::LineStyle aLineStyle;
375 xSourceProp->getPropertyValue( "BorderStyle" ) >>= aLineStyle;
376 if( aLineStyle == drawing::LineStyle_SOLID )
377 bRounded = false;
380 catch( const uno::Exception& e )
382 SAL_WARN("chart2", "Exception caught. " << e );
385 uno::Reference<drawing::XShape> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded );
386 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
387 if( xSourceProp.is())
388 PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
389 return xShape;
392 uno::Reference<drawing::XShape>
393 ShapeFactory::impl_createCube(
394 const uno::Reference<drawing::XShapes>& xTarget
395 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
396 , sal_Int32 nRotateZAngleHundredthDegree
397 , bool bRounded )
399 if( !xTarget.is() )
400 return nullptr;
402 //create shape
403 uno::Reference< drawing::XShape > xShape(
404 m_xShapeFactory->createInstance(
405 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
406 xTarget->add(xShape);
408 //set properties
409 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
410 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
411 if (xMultiPropertySet.is())
415 //depth
416 double fDepth = rSize.DirectionZ;
417 if (fDepth<0)
418 fDepth*=-1.0;
420 //PercentDiagonal
421 sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
423 //Matrix for position
424 basegfx::B3DHomMatrix aHomMatrix;
425 if (nRotateZAngleHundredthDegree != 0)
426 aHomMatrix.rotate(0.0, 0.0, -nRotateZAngleHundredthDegree / 18000.00 * F_PI);
427 aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY,
428 rPosition.PositionZ - (fDepth / 2.0));
430 uno::Sequence<OUString> aPropertyNames {
431 UNO_NAME_3D_EXTRUDE_DEPTH,
432 UNO_NAME_3D_PERCENT_DIAGONAL,
433 UNO_NAME_3D_POLYPOLYGON3D,
434 UNO_NAME_3D_TRANSFORM_MATRIX,
437 uno::Sequence<uno::Any> aPropertyValues {
438 uno::Any(sal_Int32(fDepth)), // Depth
439 uno::Any(nPercentDiagonal), // PercentDiagonal
440 createPolyPolygon_Cube(rSize, double(nPercentDiagonal) / 200.0, bRounded),
441 uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix))
444 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
446 catch( const uno::Exception& e )
448 SAL_WARN("chart2", "Exception caught. " << e );
451 return xShape;
454 uno::Reference<drawing::XShape>
455 ShapeFactory::createCylinder(
456 const uno::Reference<drawing::XShapes>& xTarget
457 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
458 , sal_Int32 nRotateZAngleHundredthDegree )
460 return impl_createConeOrCylinder(
461 xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true );
464 uno::Reference<drawing::XShape>
465 ShapeFactory::createPyramid(
466 const uno::Reference<drawing::XShapes>& xTarget
467 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
468 , double fTopHeight, bool bRotateZ
469 , const uno::Reference< beans::XPropertySet >& xSourceProp
470 , const tPropertyNameMap& rPropertyNameMap )
472 if( !xTarget.is() )
473 return nullptr;
475 Reference< drawing::XShapes > xGroup( ShapeFactory::createGroup3D( xTarget ) );
477 bool bDoubleSided = false;
478 short nRotatedTexture = 0;
480 const double fWidth = rSize.DirectionX;
481 const double fDepth = rSize.DirectionZ;
482 const double fHeight = rSize.DirectionY;
484 drawing::Position3D aBottomP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth/2.0 );
485 if(bRotateZ)
486 aBottomP1.PositionY -= fWidth/2.0;
487 else
488 aBottomP1.PositionX -= fWidth/2.0;
489 drawing::Position3D aBottomP2( aBottomP1 );
490 if(bRotateZ)
491 aBottomP2.PositionY += fWidth;
492 else
493 aBottomP2.PositionX += fWidth;
494 drawing::Position3D aBottomP3( aBottomP2 );
495 drawing::Position3D aBottomP4( aBottomP1 );
496 aBottomP3.PositionZ += fDepth;
497 aBottomP4.PositionZ += fDepth;
499 const double fTopFactor = fTopHeight/(fabs(fHeight)+fTopHeight);
500 drawing::Position3D aTopP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth*fTopFactor/2.0 );
501 if(bRotateZ)
503 aTopP1.PositionY -= fWidth*fTopFactor/2.0;
504 aTopP1.PositionX += fHeight;
506 else
508 aTopP1.PositionX -= fWidth*fTopFactor/2.0;
509 aTopP1.PositionY += fHeight;
511 drawing::Position3D aTopP2( aTopP1 );
512 if(bRotateZ)
513 aTopP2.PositionY += fWidth*fTopFactor;
514 else
515 aTopP2.PositionX += fWidth*fTopFactor;
516 drawing::Position3D aTopP3( aTopP2 );
517 drawing::Position3D aTopP4( aTopP1 );
518 aTopP3.PositionZ += fDepth*fTopFactor;
519 aTopP4.PositionZ += fDepth*fTopFactor;
521 Stripe aStripeBottom( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
523 drawing::Position3D aNormalsBottomP1( aBottomP1 );
524 drawing::Position3D aNormalsBottomP2( aBottomP2 );
525 drawing::Position3D aNormalsBottomP3( aBottomP3 );
526 drawing::Position3D aNormalsBottomP4( aBottomP4 );
527 drawing::Position3D aNormalsTopP1( aBottomP1 );
528 drawing::Position3D aNormalsTopP2( aBottomP2 );
529 drawing::Position3D aNormalsTopP3( aBottomP3 );
530 drawing::Position3D aNormalsTopP4( aBottomP4 );
531 if( bRotateZ )
533 aNormalsTopP1.PositionX += fHeight;
534 aNormalsTopP2.PositionX += fHeight;
535 aNormalsTopP3.PositionX += fHeight;
536 aNormalsTopP4.PositionX += fHeight;
538 else
540 aNormalsTopP1.PositionY += fHeight;
541 aNormalsTopP2.PositionY += fHeight;
542 aNormalsTopP3.PositionY += fHeight;
543 aNormalsTopP4.PositionY += fHeight;
546 bool bInvertPolygon = false;
547 bool bInvertNormals = false;
549 if(bRotateZ)
551 //bars
552 if(fHeight>=0.0)
554 nRotatedTexture = 2;
555 bInvertNormals = true;
556 aStripeBottom = Stripe( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
558 else
560 bInvertPolygon = true;
561 nRotatedTexture = 1;
562 aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
565 else
567 //columns
568 if(fHeight>=0.0)
570 bInvertPolygon = true;
571 nRotatedTexture = 2;
572 aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
574 else
576 nRotatedTexture = 3;
577 bInvertNormals = true;
578 aStripeBottom = Stripe( aBottomP4, aBottomP3, aBottomP2, aBottomP1 );
581 aStripeBottom.InvertNormal(true);
583 Stripe aStripe1( aTopP2, aTopP1, aBottomP1, aBottomP2 );
584 Stripe aStripe2( aTopP3, aTopP2, aBottomP2, aBottomP3 );
585 Stripe aStripe3( aTopP4, aTopP3, aBottomP3, aBottomP4 );
586 Stripe aStripe4( aTopP1, aTopP4, aBottomP4, aBottomP1 );
588 if( bInvertPolygon )
590 aStripe1 = Stripe( aBottomP1, aTopP1, aTopP2, aBottomP2 );
591 aStripe2 = Stripe( aBottomP2, aTopP2, aTopP3, aBottomP3 );
592 aStripe3 = Stripe( aBottomP3, aTopP3, aTopP4, aBottomP4 );
593 aStripe4 = Stripe( aBottomP4, aTopP4, aTopP1, aBottomP1 );
596 Stripe aNormalsStripe1( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP2, aNormalsTopP2 );
597 Stripe aNormalsStripe2( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP3, aNormalsTopP3 );
598 Stripe aNormalsStripe3( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP4, aNormalsTopP4 );
599 Stripe aNormalsStripe4( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP1, aNormalsTopP1 );
601 if( bInvertNormals )
603 aNormalsStripe1 = Stripe( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP1, aNormalsTopP1 );
604 aNormalsStripe2 = Stripe( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP2, aNormalsTopP2 );
605 aNormalsStripe3 = Stripe( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP3, aNormalsTopP3 );
606 aNormalsStripe4 = Stripe( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP4, aNormalsTopP4 );
609 aStripe1.SetManualNormal( aNormalsStripe1.getNormal() );
610 aStripe2.SetManualNormal( aNormalsStripe2.getNormal() );
611 aStripe3.SetManualNormal( aNormalsStripe3.getNormal() );
612 aStripe4.SetManualNormal( aNormalsStripe4.getNormal() );
614 const bool bFlatNormals = false;
615 ShapeFactory::createStripe( xGroup, aStripe1, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
616 ShapeFactory::createStripe( xGroup, aStripe2, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
617 ShapeFactory::createStripe( xGroup, aStripe3, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
618 ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
619 ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
621 return Reference< drawing::XShape >( xGroup, uno::UNO_QUERY );
624 uno::Reference<drawing::XShape>
625 ShapeFactory::createCone(
626 const uno::Reference<drawing::XShapes>& xTarget
627 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
628 , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree )
630 return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree, false );
633 uno::Reference<drawing::XShape>
634 ShapeFactory::impl_createConeOrCylinder(
635 const uno::Reference<drawing::XShapes>& xTarget
636 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
637 , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
638 , bool bCylinder )
640 if( !xTarget.is() )
641 return nullptr;
643 //create shape
644 uno::Reference< drawing::XShape > xShape(
645 m_xShapeFactory->createInstance(
646 "com.sun.star.drawing.Shape3DLatheObject" ), uno::UNO_QUERY );
647 xTarget->add(xShape);
649 double fWidth = rSize.DirectionX/2.0; //The depth will be corrected within Matrix
650 double fRadius = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
651 double fHeight = rSize.DirectionY;
653 //set properties
654 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
655 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
656 if (xMultiPropertySet.is())
660 //Polygon
661 sal_Int32 nVerticalSegmentCount = 0;
662 uno::Any aPPolygon = bCylinder
663 ? createPolyPolygon_Cylinder(fHeight, fRadius, nVerticalSegmentCount)
664 : createPolyPolygon_Cone(fHeight, fRadius, fTopHeight, nVerticalSegmentCount);
666 //Matrix for position
667 basegfx::B3DHomMatrix aHomMatrix;
668 if (nRotateZAngleHundredthDegree != 0)
669 aHomMatrix.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
670 //stretch the symmetric objects to given depth
671 aHomMatrix.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX);
672 aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ);
674 uno::Sequence<OUString> aPropertyNames{
675 UNO_NAME_3D_PERCENT_DIAGONAL,
676 UNO_NAME_3D_POLYPOLYGON3D,
677 UNO_NAME_3D_TRANSFORM_MATRIX,
678 UNO_NAME_3D_HORZ_SEGS,
679 UNO_NAME_3D_VERT_SEGS,
680 UNO_NAME_3D_REDUCED_LINE_GEOMETRY
683 uno::Sequence<uno::Any> aPropertyValues {
684 uno::Any(sal_Int16(5)), // PercentDiagonal
685 aPPolygon, // Polygon
686 uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)), // Matrix
687 uno::Any(CHART_3DOBJECT_SEGMENTCOUNT), // Horizontal Segments
688 uno::Any(nVerticalSegmentCount), // Vertical Segments
689 uno::Any(true) // Reduced lines
692 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
694 catch( const uno::Exception& e )
696 SAL_WARN("chart2", "Exception caught. " << e );
699 return xShape;
702 void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, bool bAppendInverse )
704 if(!rAdd.Coordinates.getLength())
705 return;
706 sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
707 if(!nAddCount)
708 return;
710 sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
712 rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1);
713 rReturn.Flags[0].realloc(nOldCount+nAddCount+1);
715 for(sal_Int32 nN=0;nN<nAddCount; nN++ )
717 sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
718 rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd];
719 rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd];
722 //close
723 rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0];
724 rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0];
727 drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
728 double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
729 , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
730 , const double fAngleSubdivisionRadian )
732 //at least one polygon is created using two normal and two control points
733 //if the angle is larger it is separated into multiple sub angles
735 drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
736 sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
737 if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
738 nSegmentCount++;
740 double fFirstSegmentAngle = fAngleSubdivisionRadian;
741 double fLastSegmentAngle = fAngleSubdivisionRadian;
742 if(nSegmentCount==1)
744 fFirstSegmentAngle = fWidthAngleRadian;
745 fLastSegmentAngle = 0.0;
747 else
749 double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
750 if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) )
751 fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian;
753 if(nSegmentCount>1)
755 fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
756 if( fLastSegmentAngle<0 )
757 nSegmentCount--;
758 if( fLastSegmentAngle>fAngleSubdivisionRadian )
760 fLastSegmentAngle-=fAngleSubdivisionRadian;
761 nSegmentCount++;
766 sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
768 aReturn.Coordinates = drawing::PointSequenceSequence(1);
769 aReturn.Flags = drawing::FlagSequenceSequence(1);
771 drawing::PointSequence aPoints(nPointCount);
772 drawing::FlagSequence aFlags(nPointCount);
774 //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
775 ::basegfx::B2DPoint P0,P1,P2,P3;
777 sal_Int32 nPoint=0;
778 double fCurrentRotateAngle = fStartAngleRadian;
779 for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
781 double fCurrentSegmentAngle = fAngleSubdivisionRadian;
782 if(nSegment==0)//first segment gets only a smaller peace until the next subdevision
783 fCurrentSegmentAngle = fFirstSegmentAngle;
784 else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
785 fCurrentSegmentAngle = fLastSegmentAngle;
787 //first create untransformed points for a unit circle arc:
788 const double fCos = cos(fCurrentSegmentAngle/2.0);
789 const double fSin = sin(fCurrentSegmentAngle/2.0);
790 P0.setX(fCos);
791 P3.setX(fCos);
792 P0.setY(-fSin);
793 P3.setY(-P0.getY());
795 P1.setX((4.0-fCos)/3.0);
796 P2.setX(P1.getX());
797 P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
798 P2.setY(-P1.getY());
799 //transform thus startangle equals NULL
800 ::basegfx::B2DHomMatrix aStart;
801 aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
802 fCurrentRotateAngle+=fCurrentSegmentAngle;
804 aStart.scale( fUnitRadius, fUnitRadius );
806 //apply given transformation to get final points
807 P0 = rTransformationFromUnitCircle*(aStart*P0);
808 P1 = rTransformationFromUnitCircle*(aStart*P1);
809 P2 = rTransformationFromUnitCircle*(aStart*P2);
810 P3 = rTransformationFromUnitCircle*(aStart*P3);
812 aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
813 aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
814 aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
816 aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
817 aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
818 aFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
820 aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
821 aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
822 aFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
824 if(nSegment==(nSegmentCount-1))
826 aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
827 aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
828 aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
832 aReturn.Coordinates[0] = aPoints;
833 aReturn.Flags[0] = aFlags;
835 return aReturn;
838 drawing::PolyPolygonBezierCoords getRingBezierCoords(
839 double fUnitCircleInnerRadius
840 , double fUnitCircleOuterRadius
841 , double fStartAngleRadian, double fWidthAngleRadian
842 , const ::basegfx::B2DHomMatrix& aTransformationFromUnitCircle
843 , const double fAngleSubdivisionRadian )
845 drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
847 aReturn.Coordinates = drawing::PointSequenceSequence(1);
848 aReturn.Flags = drawing::FlagSequenceSequence(1);
850 drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
851 fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
852 aReturn.Coordinates[0] = aOuterArc.Coordinates[0];
853 aReturn.Flags[0] = aOuterArc.Flags[0];
855 drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
856 fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
857 appendAndCloseBezierCoords( aReturn, aInnerArc, true );
859 return aReturn;
862 uno::Reference< drawing::XShape >
863 ShapeFactory::createPieSegment2D(
864 const uno::Reference< drawing::XShapes >& xTarget
865 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
866 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
867 , const drawing::Direction3D& rOffset
868 , const drawing::HomogenMatrix& rUnitCircleToScene )
870 if( !xTarget.is() )
871 return nullptr;
873 while(fUnitCircleWidthAngleDegree>360)
874 fUnitCircleWidthAngleDegree -= 360.0;
875 while(fUnitCircleWidthAngleDegree<0)
876 fUnitCircleWidthAngleDegree += 360.0;
878 //create shape
879 uno::Reference< drawing::XShape > xShape(
880 m_xShapeFactory->createInstance(
881 "com.sun.star.drawing.ClosedBezierShape" ), uno::UNO_QUERY );
882 xTarget->add(xShape); //need to add the shape before setting of properties
884 //set properties
885 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
886 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
887 if( xProp.is())
891 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
892 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
894 const double fAngleSubdivisionRadian = F_PI/10.0;
896 drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
897 fUnitCircleInnerRadius, fUnitCircleOuterRadius
898 , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
899 , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
901 xProp->setPropertyValue( "PolyPolygonBezier", uno::Any( aCoords ) );
903 catch( const uno::Exception& e )
905 SAL_WARN("chart2", "Exception caught. " << e );
909 return xShape;
912 uno::Reference< drawing::XShape >
913 ShapeFactory::createPieSegment(
914 const uno::Reference< drawing::XShapes >& xTarget
915 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
916 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
917 , const drawing::Direction3D& rOffset
918 , const drawing::HomogenMatrix& rUnitCircleToScene
919 , double fDepth )
921 if( !xTarget.is() )
922 return nullptr;
924 while(fUnitCircleWidthAngleDegree>360)
925 fUnitCircleWidthAngleDegree -= 360.0;
926 while(fUnitCircleWidthAngleDegree<0)
927 fUnitCircleWidthAngleDegree += 360.0;
929 //create shape
930 uno::Reference< drawing::XShape > xShape(
931 m_xShapeFactory->createInstance(
932 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
933 xTarget->add(xShape); //need to add the shape before setting of properties
935 //set properties
936 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
937 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
938 if( xProp.is())
942 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
943 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
945 const double fAngleSubdivisionRadian = F_PI/32.0;
947 drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
948 fUnitCircleInnerRadius, fUnitCircleOuterRadius
949 , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
950 , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
952 //depth
953 xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
954 , uno::Any(static_cast<sal_Int32>(fDepth)) );
956 //PercentDiagonal
957 xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
958 , uno::Any( sal_Int16(0) ) );
960 //Polygon
961 drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
962 ShapeFactory::closePolygon( aPoly );
963 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
964 , uno::Any( aPoly ) );
966 //DoubleSided
967 xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
968 , uno::Any( true ) );
970 //Reduced lines
971 xProp->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
972 , uno::Any( true ) );
974 //TextureProjectionMode
975 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
976 , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
978 //TextureProjectionMode
979 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X
980 , uno::Any( drawing::TextureProjectionMode_PARALLEL ) );
981 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
982 , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
984 catch( const uno::Exception& e )
986 SAL_WARN("chart2", "Exception caught. " << e );
989 return xShape;
992 uno::Reference< drawing::XShape >
993 ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& xTarget
994 , const Stripe& rStripe
995 , const uno::Reference< beans::XPropertySet >& xSourceProp
996 , const tPropertyNameMap& rPropertyNameMap
997 , bool bDoubleSided
998 , short nRotatedTexture
999 , bool bFlatNormals )
1001 if( !xTarget.is() )
1002 return nullptr;
1004 //create shape
1005 uno::Reference< drawing::XShape > xShape(
1006 m_xShapeFactory->createInstance(
1007 "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY );
1008 xTarget->add(xShape);
1010 //set properties
1011 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
1012 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
1013 if (xMultiPropertySet.is())
1017 uno::Sequence<OUString> aPropertyNames{
1018 UNO_NAME_3D_POLYPOLYGON3D,
1019 UNO_NAME_3D_TEXTUREPOLYGON3D,
1020 UNO_NAME_3D_NORMALSPOLYGON3D,
1021 UNO_NAME_3D_LINEONLY,
1022 UNO_NAME_3D_DOUBLE_SIDED
1025 uno::Sequence<uno::Any> aPropertyValues {
1026 rStripe.getPolyPolygonShape3D(), // Polygon
1027 Stripe::getTexturePolygon(nRotatedTexture), // TexturePolygon
1028 rStripe.getNormalsPolygon(), // Normals Polygon
1029 uno::Any(false), // LineOnly
1030 uno::Any(bDoubleSided) // DoubleSided
1033 //NormalsKind
1034 if (bFlatNormals)
1035 lcl_addProperty(aPropertyNames, aPropertyValues,
1036 UNO_NAME_3D_NORMALS_KIND, uno::Any(drawing::NormalsKind_FLAT));
1038 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
1040 uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
1041 if (xSourceProp.is() && xPropertySet.is())
1043 PropertyMapper::setMappedProperties(xPropertySet, xSourceProp, rPropertyNameMap);
1046 catch( const uno::Exception& e )
1048 SAL_WARN("chart2", "Exception caught. " << e );
1051 return xShape;
1054 uno::Reference< drawing::XShape >
1055 ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget
1056 , const drawing::PolyPolygonShape3D& rPolyPolygon
1057 , double fDepth )
1059 if( !xTarget.is() )
1060 return nullptr;
1062 if( !rPolyPolygon.SequenceX.getLength())
1063 return nullptr;
1065 //create shape
1066 uno::Reference< drawing::XShape > xShape(
1067 m_xShapeFactory->createInstance(
1068 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
1069 xTarget->add(xShape);
1071 //set properties
1072 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
1073 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
1074 if (xMultiPropertySet.is())
1078 uno::Sequence<OUString> aPropertyNames{
1079 UNO_NAME_3D_EXTRUDE_DEPTH,
1080 UNO_NAME_3D_PERCENT_DIAGONAL,
1081 UNO_NAME_3D_POLYPOLYGON3D,
1082 UNO_NAME_3D_DOUBLE_SIDED,
1085 uno::Sequence<uno::Any> aPropertyValues {
1086 uno::Any(sal_Int32(fDepth)), // depth
1087 uno::Any(sal_Int16(0)), // PercentDiagonal
1088 uno::Any(rPolyPolygon), // Polygon
1089 uno::Any(true) // DoubleSided
1092 //the z component of the polygon is now ignored by the drawing layer,
1093 //so we need to translate the object via transformation matrix
1095 //Matrix for position
1096 if (rPolyPolygon.SequenceZ.getLength()&& rPolyPolygon.SequenceZ[0].getLength())
1098 basegfx::B3DHomMatrix aM;
1099 aM.translate(0, 0, rPolyPolygon.SequenceZ[0][0]);
1100 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
1101 lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM));
1103 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
1105 catch( const uno::Exception& e )
1107 SAL_WARN("chart2", "Exception caught. " << e );
1110 return xShape;
1113 uno::Reference< drawing::XShape >
1114 ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget
1115 , const drawing::PolyPolygonShape3D& rPolyPolygon )
1117 if( !xTarget.is() )
1118 return nullptr;
1120 //create shape
1121 uno::Reference< drawing::XShape > xShape(
1122 m_xShapeFactory->createInstance(
1123 "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY );
1124 xTarget->add(xShape);
1126 //set properties
1127 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1128 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1129 if( xProp.is())
1133 //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
1134 drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) );
1136 //Polygon
1137 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1138 , uno::Any( aPoints ) );
1140 //ZOrder
1141 //an area should always be behind other shapes
1142 xProp->setPropertyValue( UNO_NAME_MISC_OBJ_ZORDER
1143 , uno::Any( sal_Int32(0) ) );
1145 catch( const uno::Exception& e )
1147 SAL_WARN("chart2", "Exception caught. " << e );
1150 return xShape;
1153 drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Position3D& rPos
1154 , const drawing::Direction3D& rSize
1155 , sal_Int32 nStandardSymbol )
1157 if(nStandardSymbol<0)
1158 nStandardSymbol*=-1;
1159 nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
1160 SymbolEnum eSymbolType=static_cast<SymbolEnum>(nStandardSymbol);
1162 const double& fX = rPos.PositionX;
1163 const double& fY = rPos.PositionY;
1165 const double fWidthH = rSize.DirectionX/2.0; //fWidthH stands for Half Width
1166 const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
1168 const sal_Int32 nQuarterCount = 35; // points inside a quadrant, used in case circle
1170 sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
1171 switch( eSymbolType )
1173 case Symbol_Square:
1174 case Symbol_Diamond:
1175 case Symbol_Bowtie:
1176 case Symbol_Sandglass:
1177 case Symbol_HorizontalBar:
1178 case Symbol_VerticalBar:
1179 nPointCount = 5;
1180 break;
1181 case Symbol_X:
1182 nPointCount = 13;
1183 break;
1184 case Symbol_Plus:
1185 nPointCount = 13;
1186 break;
1187 case Symbol_Star:
1188 nPointCount = 9;
1189 break;
1190 case Symbol_Asterisk:
1191 nPointCount = 19;
1192 break;
1193 case Symbol_Circle:
1194 nPointCount = 5 + 4 * nQuarterCount;
1195 break;
1196 default:
1197 break;
1200 drawing::PolyPolygonShape3D aPP;
1202 aPP.SequenceX.realloc(1);
1203 aPP.SequenceY.realloc(1);
1204 aPP.SequenceZ.realloc(1);
1206 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
1207 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
1208 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
1210 pOuterSequenceX->realloc(nPointCount);
1211 pOuterSequenceY->realloc(nPointCount);
1212 pOuterSequenceZ->realloc(nPointCount);
1214 double* pInnerSequenceX = pOuterSequenceX->getArray();
1215 double* pInnerSequenceY = pOuterSequenceY->getArray();
1216 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
1218 for(sal_Int32 nN = nPointCount; nN--;)
1219 *pInnerSequenceZ++ = 0.0;
1221 switch(eSymbolType)
1223 case Symbol_Square:
1225 *pInnerSequenceX++ = fX-fWidthH;
1226 *pInnerSequenceY++ = fY-fHeightH;
1228 *pInnerSequenceX++ = fX-fWidthH;
1229 *pInnerSequenceY++ = fY+fHeightH;
1231 *pInnerSequenceX++ = fX+fWidthH;
1232 *pInnerSequenceY++ = fY+fHeightH;
1234 *pInnerSequenceX++ = fX+fWidthH;
1235 *pInnerSequenceY++ = fY-fHeightH;
1237 *pInnerSequenceX++ = fX-fWidthH;
1238 *pInnerSequenceY++ = fY-fHeightH;
1239 break;
1241 case Symbol_UpArrow:
1243 *pInnerSequenceX++ = fX-fWidthH;
1244 *pInnerSequenceY++ = fY+fHeightH;
1246 *pInnerSequenceX++ = fX+fWidthH;
1247 *pInnerSequenceY++ = fY+fHeightH;
1249 *pInnerSequenceX++ = fX;
1250 *pInnerSequenceY++ = fY-fHeightH;
1252 *pInnerSequenceX++ = fX-fWidthH;
1253 *pInnerSequenceY++ = fY+fHeightH;
1254 break;
1256 case Symbol_DownArrow:
1258 *pInnerSequenceX++ = fX-fWidthH;
1259 *pInnerSequenceY++ = fY-fHeightH;
1261 *pInnerSequenceX++ = fX;
1262 *pInnerSequenceY++ = fY+fHeightH;
1264 *pInnerSequenceX++ = fX+fWidthH;
1265 *pInnerSequenceY++ = fY-fHeightH;
1267 *pInnerSequenceX++ = fX-fWidthH;
1268 *pInnerSequenceY++ = fY-fHeightH;
1269 break;
1271 case Symbol_RightArrow:
1273 *pInnerSequenceX++ = fX-fWidthH;
1274 *pInnerSequenceY++ = fY-fHeightH;
1276 *pInnerSequenceX++ = fX-fWidthH;
1277 *pInnerSequenceY++ = fY+fHeightH;
1279 *pInnerSequenceX++ = fX+fWidthH;
1280 *pInnerSequenceY++ = fY;
1282 *pInnerSequenceX++ = fX-fWidthH;
1283 *pInnerSequenceY++ = fY-fHeightH;
1284 break;
1286 case Symbol_LeftArrow:
1288 *pInnerSequenceX++ = fX-fWidthH;
1289 *pInnerSequenceY++ = fY;
1291 *pInnerSequenceX++ = fX+fWidthH;
1292 *pInnerSequenceY++ = fY+fHeightH;
1294 *pInnerSequenceX++ = fX+fWidthH;
1295 *pInnerSequenceY++ = fY-fHeightH;
1297 *pInnerSequenceX++ = fX-fWidthH;
1298 *pInnerSequenceY++ = fY;
1299 break;
1301 case Symbol_Bowtie:
1303 *pInnerSequenceX++ = fX-fWidthH;
1304 *pInnerSequenceY++ = fY-fHeightH;
1306 *pInnerSequenceX++ = fX-fWidthH;
1307 *pInnerSequenceY++ = fY+fHeightH;
1309 *pInnerSequenceX++ = fX+fWidthH;
1310 *pInnerSequenceY++ = fY-fHeightH;
1312 *pInnerSequenceX++ = fX+fWidthH;
1313 *pInnerSequenceY++ = fY+fHeightH;
1315 *pInnerSequenceX++ = fX-fWidthH;
1316 *pInnerSequenceY++ = fY-fHeightH;
1317 break;
1319 case Symbol_Sandglass:
1321 *pInnerSequenceX++ = fX-fWidthH;
1322 *pInnerSequenceY++ = fY+fHeightH;
1324 *pInnerSequenceX++ = fX+fWidthH;
1325 *pInnerSequenceY++ = fY+fHeightH;
1327 *pInnerSequenceX++ = fX-fWidthH;
1328 *pInnerSequenceY++ = fY-fHeightH;
1330 *pInnerSequenceX++ = fX+fWidthH;
1331 *pInnerSequenceY++ = fY-fHeightH;
1333 *pInnerSequenceX++ = fX-fWidthH;
1334 *pInnerSequenceY++ = fY+fHeightH;
1335 break;
1337 case Symbol_Diamond:
1339 *pInnerSequenceX++ = fX-fWidthH;
1340 *pInnerSequenceY++ = fY;
1342 *pInnerSequenceX++ = fX;
1343 *pInnerSequenceY++ = fY+fHeightH;
1345 *pInnerSequenceX++ = fX+fWidthH;
1346 *pInnerSequenceY++ = fY;
1348 *pInnerSequenceX++ = fX;
1349 *pInnerSequenceY++ = fY-fHeightH;
1351 *pInnerSequenceX++ = fX-fWidthH;
1352 *pInnerSequenceY++ = fY;
1353 break;
1355 case Symbol_HorizontalBar:
1357 *pInnerSequenceX++ = fX-fWidthH;
1358 *pInnerSequenceY++ = fY-0.2*fHeightH;
1360 *pInnerSequenceX++ = fX+fWidthH;
1361 *pInnerSequenceY++ = fY-0.2*fHeightH;
1363 *pInnerSequenceX++ = fX+fWidthH;
1364 *pInnerSequenceY++ = fY+0.2*fHeightH;
1366 *pInnerSequenceX++ = fX-fWidthH;
1367 *pInnerSequenceY++ = fY+0.2*fHeightH;
1369 *pInnerSequenceX++ = fX-fWidthH;
1370 *pInnerSequenceY++ = fY-0.2*fHeightH;
1371 break;
1373 case Symbol_VerticalBar:
1375 *pInnerSequenceX++ = fX-0.2*fWidthH;
1376 *pInnerSequenceY++ = fY-fHeightH;
1378 *pInnerSequenceX++ = fX+0.2*fWidthH;
1379 *pInnerSequenceY++ = fY-fHeightH;
1381 *pInnerSequenceX++ = fX+0.2*fWidthH;
1382 *pInnerSequenceY++ = fY+fHeightH;
1384 *pInnerSequenceX++ = fX-0.2*fWidthH;
1385 *pInnerSequenceY++ = fY+fHeightH;
1387 *pInnerSequenceX++ = fX-0.2*fWidthH;
1388 *pInnerSequenceY++ = fY-fHeightH;
1390 break;
1392 case Symbol_Circle:
1394 double fOmega = 1.5707963267948966192 / (nQuarterCount + 1.0);
1395 // one point in the middle of each edge to get full size bounding rectangle
1396 *pInnerSequenceX++ = fX + fWidthH;
1397 *pInnerSequenceY++ = fY;
1398 // 0 to PI/2
1399 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1401 *pInnerSequenceX++ = fX + fWidthH * cos( i * fOmega );
1402 *pInnerSequenceY++ = fY - fHeightH * sin( i * fOmega );
1404 // PI/2 to PI
1405 *pInnerSequenceX++ = fX;
1406 *pInnerSequenceY++ = fY - fHeightH;
1407 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1409 *pInnerSequenceX++ = fX - fWidthH * sin( i * fOmega);
1410 *pInnerSequenceY++ = fY - fHeightH * cos( i * fOmega);
1412 // PI to 3/2*PI
1413 *pInnerSequenceX++ = fX - fWidthH;
1414 *pInnerSequenceY++ = fY;
1415 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1417 *pInnerSequenceX++ = fX - fWidthH * cos( i * fOmega);
1418 *pInnerSequenceY++ = fY + fHeightH * sin( i * fOmega);
1420 // 3/2*PI to 2*PI
1421 *pInnerSequenceX++ = fX;
1422 *pInnerSequenceY++ = fY + fHeightH;
1423 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1425 *pInnerSequenceX++ = fX + fWidthH * sin(i * fOmega);
1426 *pInnerSequenceY++ = fY + fHeightH * cos(i * fOmega);
1428 // close polygon
1429 *pInnerSequenceX++ = fX + fWidthH;
1430 *pInnerSequenceY++ = fY;
1431 break;
1433 case Symbol_Star:
1435 *pInnerSequenceX++ = fX;
1436 *pInnerSequenceY++ = fY-fHeightH;
1438 *pInnerSequenceX++ = fX+0.2*fWidthH;
1439 *pInnerSequenceY++ = fY-0.2*fHeightH;
1441 *pInnerSequenceX++ = fX+fWidthH;
1442 *pInnerSequenceY++ = fY;
1444 *pInnerSequenceX++ = fX+0.2*fWidthH;
1445 *pInnerSequenceY++ = fY+0.2*fHeightH;
1447 *pInnerSequenceX++ = fX;
1448 *pInnerSequenceY++ = fY+fHeightH;
1450 *pInnerSequenceX++ = fX-0.2*fWidthH;
1451 *pInnerSequenceY++ = fY+0.2*fHeightH;
1453 *pInnerSequenceX++ = fX-fWidthH;
1454 *pInnerSequenceY++ = fY;
1456 *pInnerSequenceX++ = fX-0.2*fWidthH;
1457 *pInnerSequenceY++ = fY-0.2*fHeightH;
1459 *pInnerSequenceX++ = fX;
1460 *pInnerSequenceY++ = fY-fHeightH;
1461 break;
1463 case Symbol_X:
1465 const double fScaleX = fWidthH / 128.0;
1466 const double fScaleY = fHeightH / 128.0;
1467 const double fSmall = sqrt(200.0);
1468 const double fLarge = 128.0 - fSmall;
1470 *pInnerSequenceX++ = fX;
1471 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1473 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1474 *pInnerSequenceY++ = fY - fHeightH;
1476 *pInnerSequenceX++ = fX - fWidthH;
1477 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1479 *pInnerSequenceX++ = fX - fScaleX * fSmall;
1480 *pInnerSequenceY++ = fY;
1482 *pInnerSequenceX++ = fX - fWidthH;
1483 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1485 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1486 *pInnerSequenceY++ = fY + fHeightH;
1488 *pInnerSequenceX++ = fX;
1489 *pInnerSequenceY++ = fY + fScaleY * fSmall;
1491 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1492 *pInnerSequenceY++ = fY + fHeightH;
1494 *pInnerSequenceX++ = fX + fWidthH;
1495 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1497 *pInnerSequenceX++ = fX + fScaleX * fSmall;
1498 *pInnerSequenceY++ = fY;
1500 *pInnerSequenceX++ = fX + fWidthH;
1501 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1503 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1504 *pInnerSequenceY++ = fY - fHeightH;
1506 *pInnerSequenceX++ = fX;
1507 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1508 break;
1511 case Symbol_Plus:
1513 const double fScaleX = fWidthH / 128.0;
1514 const double fScaleY = fHeightH / 128.0;
1515 const double fHalf = 10.0; //half line width on 256 size square
1516 const double fdX = fScaleX * fHalf;
1517 const double fdY = fScaleY * fHalf;
1519 *pInnerSequenceX++ = fX-fdX;
1520 *pInnerSequenceY++ = fY-fHeightH;
1522 *pInnerSequenceX++ = fX-fdX;
1523 *pInnerSequenceY++ = fY-fdY;
1525 *pInnerSequenceX++ = fX-fWidthH;
1526 *pInnerSequenceY++ = fY-fdY;
1528 *pInnerSequenceX++ = fX-fWidthH;
1529 *pInnerSequenceY++ = fY+fdY;
1531 *pInnerSequenceX++ = fX-fdX;
1532 *pInnerSequenceY++ = fY+fdY;
1534 *pInnerSequenceX++ = fX-fdX;
1535 *pInnerSequenceY++ = fY+fHeightH;
1537 *pInnerSequenceX++ = fX+fdX;
1538 *pInnerSequenceY++ = fY+fHeightH;
1540 *pInnerSequenceX++ = fX+fdX;
1541 *pInnerSequenceY++ = fY+fdY;
1543 *pInnerSequenceX++ = fX+fWidthH;
1544 *pInnerSequenceY++ = fY+fdY;
1546 *pInnerSequenceX++ = fX+fWidthH;
1547 *pInnerSequenceY++ = fY-fdY;
1549 *pInnerSequenceX++ = fX+fdX;
1550 *pInnerSequenceY++ = fY-fdY;
1552 *pInnerSequenceX++ = fX+fdY;
1553 *pInnerSequenceY++ = fY-fHeightH;
1555 *pInnerSequenceX++ = fX-fdX;
1556 *pInnerSequenceY++ = fY-fHeightH;
1557 break;
1560 case Symbol_Asterisk:
1562 const double fHalf = 10.0; // half line width on 256 size square
1563 const double fTwoY = fHalf * sqrt(3.0);
1564 const double fFourY = (128.0 - 2.0 * fHalf ) / sqrt(3.0);
1565 const double fThreeX = 128.0 - fHalf;
1566 const double fThreeY = fHalf * sqrt(3.0) + fFourY;
1567 const double fFiveX = 2.0 * fHalf;
1569 const double fScaleX = fWidthH / 128.0;
1570 const double fScaleY = fHeightH / 128.0;
1573 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1574 *pInnerSequenceY++ = fY-fHeightH;
1576 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1577 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1579 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1580 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1582 *pInnerSequenceX++ = fX-fWidthH;
1583 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1585 *pInnerSequenceX++ = fX-fScaleX * fFiveX;
1586 *pInnerSequenceY++ = fY;
1587 //6 as 4
1588 *pInnerSequenceX++ = fX-fWidthH;
1589 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1590 //7 as 3
1591 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1592 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1593 //8 as 2
1594 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1595 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1596 //9 as 1
1597 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1598 *pInnerSequenceY++ = fY+fHeightH;
1599 //10 as 1
1600 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1601 *pInnerSequenceY++ = fY+fHeightH;
1602 //11 as 2
1603 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1604 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1605 //12 as 3
1606 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1607 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1608 //13 as 4
1609 *pInnerSequenceX++ = fX+fWidthH;
1610 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1611 //14 as 5
1612 *pInnerSequenceX++ = fX+fScaleX * fFiveX;
1613 *pInnerSequenceY++ = fY;
1614 //15 as 4
1615 *pInnerSequenceX++ = fX+fWidthH;
1616 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1617 //16 as 3
1618 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1619 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1620 //17 as 2
1621 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1622 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1623 // 18 as 1
1624 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1625 *pInnerSequenceY++ = fY-fHeightH;
1626 // 19 = 1, closing
1627 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1628 *pInnerSequenceY++ = fY-fHeightH;
1629 break;
1631 default: //case Symbol_Square:
1633 *pInnerSequenceX++ = fX-fWidthH;
1634 *pInnerSequenceY++ = fY-fHeightH;
1636 *pInnerSequenceX++ = fX-fWidthH;
1637 *pInnerSequenceY++ = fY+fHeightH;
1639 *pInnerSequenceX++ = fX+fWidthH;
1640 *pInnerSequenceY++ = fY+fHeightH;
1642 *pInnerSequenceX++ = fX+fWidthH;
1643 *pInnerSequenceY++ = fY-fHeightH;
1645 *pInnerSequenceX++ = fX-fWidthH;
1646 *pInnerSequenceY++ = fY-fHeightH;
1647 break;
1651 return aPP;
1654 uno::Reference< drawing::XShape >
1655 ShapeFactory::createSymbol2D(
1656 const uno::Reference< drawing::XShapes >& xTarget
1657 , const drawing::Position3D& rPosition
1658 , const drawing::Direction3D& rSize
1659 , sal_Int32 nStandardSymbol
1660 , sal_Int32 nBorderColor
1661 , sal_Int32 nFillColor )
1663 if( !xTarget.is() )
1664 return nullptr;
1666 //create shape
1667 uno::Reference< drawing::XShape > xShape(
1668 m_xShapeFactory->createInstance(
1669 "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY );
1670 xTarget->add(xShape);
1672 //set properties
1673 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1674 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1675 if( xProp.is())
1679 drawing::PointSequenceSequence aPoints( PolyToPointSequence(
1680 createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) ));
1682 //Polygon
1683 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1684 , uno::Any( aPoints ) );
1686 //LineColor
1687 xProp->setPropertyValue( UNO_NAME_LINECOLOR
1688 , uno::Any( nBorderColor ) );
1690 //FillColor
1691 xProp->setPropertyValue( UNO_NAME_FILLCOLOR
1692 , uno::Any( nFillColor ) );
1694 catch( const uno::Exception& e )
1696 SAL_WARN("chart2", "Exception caught. " << e );
1699 return xShape;
1702 uno::Reference< drawing::XShape >
1703 ShapeFactory::createGraphic2D(
1704 const uno::Reference< drawing::XShapes >& xTarget
1705 , const drawing::Position3D& rPosition
1706 , const drawing::Direction3D& rSize
1707 , const uno::Reference< graphic::XGraphic >& xGraphic )
1709 if( !xTarget.is() || !xGraphic.is() )
1710 return nullptr;
1712 // @todo: change this to a rectangle shape with a fill bitmap for
1713 // performance reasons (ask AW, said CL)
1715 //create shape
1716 uno::Reference< drawing::XShape > xShape(
1717 m_xShapeFactory->createInstance(
1718 "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY );
1719 xTarget->add(xShape);
1723 // assume position is upper left corner. Transform to center.
1724 drawing::Position3D aCenterPosition(
1725 rPosition.PositionX - (rSize.DirectionX / 2.0),
1726 rPosition.PositionY - (rSize.DirectionY / 2.0),
1727 rPosition.PositionZ );
1728 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1729 xShape->setSize( Direction3DToAWTSize( rSize ));
1731 catch( const uno::Exception & e )
1733 SAL_WARN("chart2", "Exception caught. " << e );
1735 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1736 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1737 if( xProp.is())
1741 xProp->setPropertyValue( "Graphic", uno::Any( xGraphic ));
1743 catch( const uno::Exception& e )
1745 SAL_WARN("chart2", "Exception caught. " << e );
1748 return xShape;
1751 uno::Reference< drawing::XShapes >
1752 ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget
1753 , const OUString& aName )
1755 if( !xTarget.is() )
1756 return nullptr;
1759 //create and add to target
1760 uno::Reference< drawing::XShape > xShape(
1761 m_xShapeFactory->createInstance(
1762 "com.sun.star.drawing.GroupShape" ), uno::UNO_QUERY );
1763 xTarget->add(xShape);
1765 //set name
1766 if(!aName.isEmpty())
1767 setShapeName( xShape , aName );
1769 {//workaround
1770 //need this null size as otherwise empty group shapes where painted with a gray border
1771 xShape->setSize(awt::Size(0,0));
1774 //return
1775 uno::Reference< drawing::XShapes > xShapes =
1776 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1777 return xShapes;
1779 catch( const uno::Exception& e )
1781 SAL_WARN("chart2", "Exception caught. " << e );
1783 return nullptr;
1786 uno::Reference< drawing::XShapes >
1787 ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget
1788 , const OUString& aName )
1790 if( !xTarget.is() )
1791 return nullptr;
1794 //create shape
1795 uno::Reference< drawing::XShape > xShape(
1796 m_xShapeFactory->createInstance(
1797 "com.sun.star.drawing.Shape3DSceneObject" ), uno::UNO_QUERY );
1799 xTarget->add(xShape);
1801 //it is necessary to set the transform matrix to initialize the scene properly
1802 //otherwise all objects which are placed into this Group will not be visible
1803 //the following should be unnecessary after a the bug is fixed
1805 //set properties
1806 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1807 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1808 if( xProp.is())
1812 ::basegfx::B3DHomMatrix aM;
1813 xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
1814 , uno::Any(B3DHomMatrixToHomogenMatrix(aM)) );
1816 catch( const uno::Exception& e )
1818 SAL_WARN("chart2", "Exception caught. " << e );
1823 //set name
1824 if(!aName.isEmpty())
1825 setShapeName( xShape , aName );
1827 //return
1828 uno::Reference< drawing::XShapes > xShapes =
1829 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1830 return xShapes;
1832 catch( const uno::Exception& e )
1834 SAL_WARN("chart2", "Exception caught. " << e );
1836 return nullptr;
1839 uno::Reference< drawing::XShape >
1840 ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget
1841 , const drawing::Position3D& rPosition
1842 , const drawing::Direction3D& rSize )
1844 if( !xTarget.is() )
1845 return nullptr;
1847 //create shape
1848 uno::Reference< drawing::XShape > xShape(
1849 m_xShapeFactory->createInstance(
1850 "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY );
1851 xTarget->add(xShape);
1855 drawing::Position3D aCenterPosition(
1856 rPosition.PositionX - (rSize.DirectionX / 2.0),
1857 rPosition.PositionY - (rSize.DirectionY / 2.0),
1858 rPosition.PositionZ );
1859 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1860 xShape->setSize( Direction3DToAWTSize( rSize ));
1862 catch( const uno::Exception & e )
1864 SAL_WARN("chart2", "Exception caught. " << e );
1867 //set properties
1868 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1869 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1870 if( xProp.is())
1874 xProp->setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) );
1876 catch( const uno::Exception& e )
1878 SAL_WARN("chart2", "Exception caught. " << e );
1881 return xShape;
1884 uno::Reference< drawing::XShape >
1885 ShapeFactory::createCircle( const uno::Reference< drawing::XShapes >& xTarget
1886 , const awt::Size& rSize
1887 , const awt::Point& rPosition )
1889 uno::Reference< drawing::XShape > xShape(
1890 m_xShapeFactory->createInstance(
1891 "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY );
1892 xTarget->add(xShape);
1893 xShape->setSize( rSize );
1894 xShape->setPosition( rPosition );
1896 return xShape;
1899 uno::Reference< drawing::XShape >
1900 ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget
1901 , const drawing::PolyPolygonShape3D& rPoints
1902 , const VLineProperties& rLineProperties )
1904 if( !xTarget.is() )
1905 return nullptr;
1907 if(!rPoints.SequenceX.getLength())
1908 return nullptr;
1910 //create shape
1911 uno::Reference< drawing::XShape > xShape(
1912 m_xShapeFactory->createInstance(
1913 "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY );
1914 xTarget->add(xShape);
1916 //set properties
1917 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
1918 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
1919 if (xMultiPropertySet.is())
1923 uno::Sequence<OUString> aPropertyNames {
1924 UNO_NAME_3D_POLYPOLYGON3D,
1925 UNO_NAME_3D_LINEONLY
1928 uno::Sequence<uno::Any> aPropertyValues {
1929 uno::Any(rPoints), // Polygon
1930 uno::Any(true) // LineOnly
1933 //Transparency
1934 if(rLineProperties.Transparence.hasValue())
1936 lcl_addProperty(aPropertyNames, aPropertyValues,
1937 UNO_NAME_LINETRANSPARENCE,
1938 rLineProperties.Transparence);
1941 //LineStyle
1942 if(rLineProperties.LineStyle.hasValue())
1944 lcl_addProperty(aPropertyNames, aPropertyValues,
1945 UNO_NAME_LINESTYLE,
1946 rLineProperties.LineStyle);
1949 //LineWidth
1950 if(rLineProperties.Width.hasValue())
1952 lcl_addProperty(aPropertyNames, aPropertyValues,
1953 UNO_NAME_LINEWIDTH,
1954 rLineProperties.Width);
1957 //LineColor
1958 if(rLineProperties.Color.hasValue())
1960 lcl_addProperty(aPropertyNames, aPropertyValues,
1961 UNO_NAME_LINECOLOR,
1962 rLineProperties.Color);
1964 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
1966 catch( const uno::Exception& e )
1968 SAL_WARN("chart2", "Exception caught. " << e );
1971 return xShape;
1974 uno::Reference< drawing::XShape >
1975 ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget
1976 , const drawing::PointSequenceSequence& rPoints
1977 , const VLineProperties* pLineProperties )
1979 if( !xTarget.is() )
1980 return nullptr;
1982 if(!rPoints.getLength())
1983 return nullptr;
1985 //create shape
1986 uno::Reference< drawing::XShape > xShape(
1987 m_xShapeFactory->createInstance(
1988 "com.sun.star.drawing.PolyLineShape" ), uno::UNO_QUERY );
1989 xTarget->add(xShape);
1991 //set properties
1992 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1993 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1994 if( xProp.is())
1998 //Polygon
1999 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
2000 , uno::Any( rPoints ) );
2002 if(pLineProperties)
2004 //Transparency
2005 if(pLineProperties->Transparence.hasValue())
2006 xProp->setPropertyValue( UNO_NAME_LINETRANSPARENCE
2007 , pLineProperties->Transparence );
2009 //LineStyle
2010 if(pLineProperties->LineStyle.hasValue())
2011 xProp->setPropertyValue( UNO_NAME_LINESTYLE
2012 , pLineProperties->LineStyle );
2014 //LineWidth
2015 if(pLineProperties->Width.hasValue())
2016 xProp->setPropertyValue( UNO_NAME_LINEWIDTH
2017 , pLineProperties->Width );
2019 //LineColor
2020 if(pLineProperties->Color.hasValue())
2021 xProp->setPropertyValue( UNO_NAME_LINECOLOR
2022 , pLineProperties->Color );
2024 //LineDashName
2025 if(pLineProperties->DashName.hasValue())
2026 xProp->setPropertyValue( "LineDashName"
2027 , pLineProperties->DashName );
2030 catch( const uno::Exception& e )
2032 SAL_WARN("chart2", "Exception caught. " << e );
2035 return xShape;
2038 uno::Reference< drawing::XShape >
2039 ShapeFactory::createLine ( const uno::Reference< drawing::XShapes >& xTarget,
2040 const awt::Size& rSize, const awt::Point& rPosition )
2042 //create shape
2043 uno::Reference< drawing::XShape > xShape(
2044 m_xShapeFactory->createInstance(
2045 "com.sun.star.drawing.LineShape" ), uno::UNO_QUERY );
2046 xTarget->add(xShape);
2047 xShape->setSize( rSize );
2048 xShape->setPosition( rPosition );
2050 return xShape;
2053 uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle(
2054 const uno::Reference< drawing::XShapes >& xTarget
2055 , const awt::Size& rSize )
2059 if(!xTarget.is())
2060 return nullptr;
2062 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2063 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2064 if( xShape.is())
2066 xTarget->add( xShape );
2067 ShapeFactory::makeShapeInvisible( xShape );
2068 xShape->setSize( rSize );
2070 return xShape;
2072 catch( const uno::Exception & )
2074 DBG_UNHANDLED_EXCEPTION("chart2");
2076 return nullptr;
2079 uno::Reference< drawing::XShape > ShapeFactory::createRectangle(
2080 const uno::Reference< drawing::XShapes >& xTarget,
2081 const awt::Size& rSize,
2082 const awt::Point& rPosition,
2083 const tNameSequence& rPropNames,
2084 const tAnySequence& rPropValues,
2085 StackPosition ePos )
2087 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2088 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2089 if( xShape.is())
2091 if (ePos == Bottom)
2093 uno::Reference<drawing::XShapes2> xTarget2(xTarget, uno::UNO_QUERY);
2094 if (xTarget2.is())
2095 xTarget2->addBottom(xShape);
2097 else
2098 xTarget->add(xShape);
2100 xShape->setPosition( rPosition );
2101 xShape->setSize( rSize );
2102 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY_THROW );
2103 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xPropSet );
2106 return xShape;
2109 uno::Reference< drawing::XShape >
2110 ShapeFactory::createRectangle(
2111 const uno::Reference<
2112 drawing::XShapes >& xTarget )
2114 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2115 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2116 xTarget->add( xShape );
2118 return xShape;
2121 uno::Reference< drawing::XShape >
2122 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2123 , const OUString& rText
2124 , const tNameSequence& rPropNames
2125 , const tAnySequence& rPropValues
2126 , const uno::Any& rATransformation )
2128 if( !xTarget.is() )
2129 return nullptr;
2131 if(rText.isEmpty())
2132 return nullptr;
2134 //create shape and add to page
2135 uno::Reference< drawing::XShape > xShape(
2136 m_xShapeFactory->createInstance(
2137 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2138 xTarget->add(xShape);
2140 //set text
2141 uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY );
2142 if( xTextRange.is() )
2143 xTextRange->setString( rText );
2145 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2146 if( xProp.is() )
2148 //set properties
2149 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2151 //set position matrix
2152 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2155 xProp->setPropertyValue( "Transformation", rATransformation );
2157 catch( const uno::Exception& e )
2159 SAL_WARN("chart2", "Exception caught. " << e );
2162 return xShape;
2165 uno::Reference< drawing::XShape >
2166 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2167 , const uno::Sequence< OUString >& rTextParagraphs
2168 , const uno::Sequence< tNameSequence >& rParaPropNames
2169 , const uno::Sequence< tAnySequence >& rParaPropValues
2170 , const tNameSequence& rPropNames
2171 , const tAnySequence& rPropValues
2172 , const uno::Any& rATransformation )
2174 if( !xTarget.is() )
2175 return nullptr;
2177 if( !rTextParagraphs.hasElements() )
2178 return nullptr;
2180 sal_Int32 nNumberOfParagraphs = rTextParagraphs.getLength();
2182 if( rParaPropNames.getLength() != nNumberOfParagraphs )
2183 return nullptr;
2185 if( rParaPropValues.getLength() != nNumberOfParagraphs )
2186 return nullptr;
2188 bool bNotEmpty = false;
2189 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2191 if( !rTextParagraphs[nN].isEmpty() )
2193 bNotEmpty = true;
2194 break;
2197 if( !bNotEmpty )
2198 return nullptr;
2200 //create shape and add to page
2201 uno::Reference< drawing::XShape > xShape(
2202 m_xShapeFactory->createInstance(
2203 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2204 xTarget->add(xShape);
2206 //set paragraph properties
2207 bNotEmpty = false;
2208 Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2209 if( xText.is() )
2211 // the first cursor is used for appending the next paragraph,
2212 // after a new string has been inserted the cursor is moved at the end
2213 // of the inserted string
2214 // the second cursor is used for selecting the paragraph and apply the
2215 // passed text properties
2216 Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor();
2217 Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor();
2218 if( xInsertCursor.is() && xSelectionCursor.is() )
2220 uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
2221 if( xSelectionProp.is() )
2223 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2225 if( !rTextParagraphs[nN].isEmpty() )
2227 xInsertCursor->gotoEnd(false);
2228 if( bNotEmpty )
2230 xText->insertString( xInsertCursor, "\n", false );
2232 xSelectionCursor->gotoEnd(false);
2233 xText->insertString( xInsertCursor, rTextParagraphs[nN], false );
2234 bNotEmpty = true;
2235 xSelectionCursor->gotoEnd(true); // select current paragraph
2236 PropertyMapper::setMultiProperties( rParaPropNames[nN], rParaPropValues[nN], xSelectionProp );
2243 if( !bNotEmpty )
2244 return nullptr;
2246 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2247 if( xProp.is() )
2249 //set whole text shape properties
2250 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2252 if (rATransformation.hasValue())
2254 //set position matrix
2255 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2258 xProp->setPropertyValue( "Transformation", rATransformation );
2260 catch( const uno::Exception& e )
2262 SAL_WARN("chart2", "Exception caught. " << e );
2266 return xShape;
2269 uno::Reference< drawing::XShape >
2270 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2271 , uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString
2272 , const tNameSequence& rPropNames
2273 , const tAnySequence& rPropValues
2274 , const uno::Any& rATransformation )
2276 if( !xTarget.is() )
2277 return nullptr;
2279 if( !xFormattedString.hasElements() )
2280 return nullptr;
2282 sal_Int32 nNumberOfParagraphs = xFormattedString.getLength();
2284 bool bNotEmpty = false;
2285 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2287 if( !xFormattedString[nN]->getString().isEmpty() )
2289 bNotEmpty = true;
2290 break;
2293 if( !bNotEmpty )
2294 return nullptr;
2296 //create shape and add to page
2297 uno::Reference< drawing::XShape > xShape(
2298 m_xShapeFactory->createInstance(
2299 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2300 xTarget->add(xShape);
2302 //set paragraph properties
2303 bNotEmpty = false;
2304 Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2305 if( xText.is() )
2307 // the first cursor is used for appending the next paragraph,
2308 // after a new string has been inserted the cursor is moved at the end
2309 // of the inserted string
2310 // the second cursor is used for selecting the paragraph and apply the
2311 // passed text properties
2312 Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor();
2313 Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor();
2314 if( xInsertCursor.is() && xSelectionCursor.is() )
2316 uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
2317 if( xSelectionProp.is() )
2319 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2321 if( !xFormattedString[nN]->getString().isEmpty() )
2323 xInsertCursor->gotoEnd( false );
2324 xSelectionCursor->gotoEnd( false );
2325 xText->insertString( xInsertCursor, xFormattedString[nN]->getString(), false );
2326 bNotEmpty = true;
2327 xSelectionCursor->gotoEnd( true ); // select current paragraph
2328 uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY );
2329 PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties,
2330 PropertyMapper::getPropertyNameMapForTextShapeProperties() );
2337 if( !bNotEmpty )
2338 return nullptr;
2340 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2341 if( xProp.is() )
2343 //set whole text shape properties
2344 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2346 if( rATransformation.hasValue() )
2348 //set position matrix
2349 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2352 xProp->setPropertyValue( "Transformation", rATransformation );
2354 catch( const uno::Exception& e )
2356 SAL_WARN("chart2", "Exception caught. " << e );
2360 return xShape;
2363 uno::Reference< drawing::XShape >
2364 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget,
2365 const awt::Size& rSize,
2366 const awt::Point& rPos,
2367 uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString,
2368 const uno::Reference<
2369 beans::XPropertySet > & xTextProperties,
2370 double nRotation, const OUString& aName )
2372 //create shape and add to page
2373 uno::Reference< drawing::XShape > xShape(
2374 m_xShapeFactory->createInstance(
2375 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2378 xTarget->add(xShape);
2380 //set text and text properties
2381 uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2382 uno::Reference< text::XTextCursor > xTextCursor( xText->createTextCursor() );
2383 uno::Reference< text::XTextRange > xTextRange( xTextCursor, uno::UNO_QUERY );
2384 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
2385 if( !xText.is() || !xTextRange.is() || !xTextCursor.is() || !xShapeProp.is() || !xTextProperties.is() )
2386 return xShape;
2388 tPropertyNameValueMap aValueMap;
2389 //fill line-, fill- and paragraph-properties into the ValueMap
2391 tPropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForParagraphProperties();
2392 auto const & add = PropertyMapper::getPropertyNameMapForFillAndLineProperties();
2393 aNameMap.insert(add.begin(), add.end());
2395 PropertyMapper::getValueMap( aValueMap, aNameMap, xTextProperties );
2398 //fill some more shape properties into the ValueMap
2400 aValueMap.insert( { "TextHorizontalAdjust", uno::Any(drawing::TextHorizontalAdjust_CENTER) } ); // drawing::TextHorizontalAdjust
2401 aValueMap.insert( { "TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_CENTER) } ); //drawing::TextVerticalAdjust
2402 aValueMap.insert( { "TextAutoGrowHeight", uno::Any(true) } ); // sal_Bool
2403 aValueMap.insert( { "TextAutoGrowWidth", uno::Any(true) } ); // sal_Bool
2404 aValueMap.insert( { "TextMaximumFrameWidth", uno::Any(rSize.Width) } ); // sal_Int32
2406 //set name/classified ObjectID (CID)
2407 if( !aName.isEmpty() )
2408 aValueMap.emplace( "Name", uno::Any( aName ) ); //CID OUString
2411 //set global title properties
2413 tNameSequence aPropNames;
2414 tAnySequence aPropValues;
2415 PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
2416 PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
2419 bool bStackCharacters(false);
2422 xTextProperties->getPropertyValue( "StackCharacters" ) >>= bStackCharacters;
2424 catch( const uno::Exception& e )
2426 SAL_WARN("chart2", "Exception caught. " << e );
2429 if(bStackCharacters)
2431 //if the characters should be stacked we use only the first character properties for code simplicity
2432 if( xFormattedString.getLength()>0 )
2434 OUString aLabel;
2435 for( sal_Int32 nN=0; nN<xFormattedString.getLength();nN++ )
2436 aLabel += xFormattedString[nN]->getString();
2437 aLabel = ShapeFactory::getStackedString( aLabel, bStackCharacters );
2439 xTextCursor->gotoEnd(false);
2440 xText->insertString( xTextRange, aLabel, false );
2441 xTextCursor->gotoEnd(true);
2442 uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
2443 uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
2445 PropertyMapper::setMappedProperties( xTargetProps, xSourceProps
2446 , PropertyMapper::getPropertyNameMapForCharacterProperties() );
2448 // adapt font size according to page size
2449 awt::Size aOldRefSize;
2450 if( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize )
2452 RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize );
2456 else
2458 sal_Int32 nN = 0;
2459 for( nN=0; nN<xFormattedString.getLength();nN++ )
2461 xTextCursor->gotoEnd(false);
2462 xText->insertString( xTextRange, xFormattedString[nN]->getString(), false );
2463 xTextCursor->gotoEnd(true);
2465 awt::Size aOldRefSize;
2466 bool bHasRefPageSize =
2467 ( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize );
2469 if( xFormattedString.getLength()>0 )
2471 uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
2472 uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
2473 PropertyMapper::setMappedProperties( xTargetProps, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() );
2475 // adapt font size according to page size
2476 if( bHasRefPageSize )
2478 RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize );
2483 // #i109336# Improve auto positioning in chart
2484 float fFontHeight = 0.0;
2485 if ( xShapeProp.is() && ( xShapeProp->getPropertyValue( "CharHeight" ) >>= fFontHeight ) )
2487 fFontHeight *= ( 2540.0f / 72.0f ); // pt -> 1/100 mm
2488 sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.18f ) );
2489 sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.30f ) );
2490 xShapeProp->setPropertyValue( "TextLeftDistance", uno::Any( nXDistance ) );
2491 xShapeProp->setPropertyValue( "TextRightDistance", uno::Any( nXDistance ) );
2492 xShapeProp->setPropertyValue( "TextUpperDistance", uno::Any( nYDistance ) );
2493 xShapeProp->setPropertyValue( "TextLowerDistance", uno::Any( nYDistance ) );
2495 sal_Int32 nXPos = rPos.X;
2496 sal_Int32 nYPos = rPos.Y;
2498 //set position matrix
2499 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2500 ::basegfx::B2DHomMatrix aM;
2501 aM.rotate( -nRotation*F_PI/180.0 );//#i78696#->#i80521#
2502 aM.translate( nXPos, nYPos );
2503 xShapeProp->setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) );
2505 catch( const uno::Exception& e )
2507 SAL_WARN("chart2", "Exception caught. " << e );
2509 return xShape;
2512 } //namespace chart
2514 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */