Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / chart2 / source / view / main / ShapeFactory.cxx
blobf6219c6501512d58544f2b675d91c32c043a67ad
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 <BaseGFXHelper.hxx>
22 #include <ViewDefines.hxx>
23 #include <Stripe.hxx>
24 #include <CommonConverters.hxx>
25 #include <RelativeSizeHelper.hxx>
26 #include <PropertyMapper.hxx>
27 #include <VLineProperties.hxx>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/beans/XMultiPropertySet.hpp>
30 #include <com/sun/star/chart2/XFormattedString.hpp>
31 #include <com/sun/star/drawing/CircleKind.hpp>
32 #include <com/sun/star/drawing/DoubleSequence.hpp>
33 #include <com/sun/star/drawing/FlagSequence.hpp>
34 #include <com/sun/star/drawing/FillStyle.hpp>
35 #include <com/sun/star/drawing/LineStyle.hpp>
36 #include <com/sun/star/drawing/NormalsKind.hpp>
37 #include <com/sun/star/drawing/PointSequence.hpp>
38 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
39 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
40 #include <com/sun/star/drawing/TextureProjectionMode.hpp>
41 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
42 #include <com/sun/star/drawing/XShapes2.hpp>
43 #include <com/sun/star/graphic/XGraphic.hpp>
44 #include <com/sun/star/drawing/XShapes.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/text/XText.hpp>
47 #include <com/sun/star/uno/Sequence.hxx>
48 #include <com/sun/star/uno/Any.hxx>
50 #include <editeng/unoprnms.hxx>
51 #include <rtl/math.hxx>
53 #include <basegfx/point/b2dpoint.hxx>
54 #include <basegfx/matrix/b3dhommatrix.hxx>
55 #include <tools/diagnose_ex.h>
56 #include <tools/helpers.hxx>
57 #include <sal/log.hxx>
59 #include <algorithm>
61 using namespace ::com::sun::star;
62 using ::com::sun::star::uno::Reference;
64 namespace chart
67 namespace
70 void lcl_addProperty(uno::Sequence<OUString> & rPropertyNames, uno::Sequence<uno::Any> & rPropertyValues,
71 OUString const & rName, uno::Any const & rAny)
73 rPropertyNames.realloc(rPropertyNames.getLength() + 1);
74 rPropertyNames[rPropertyNames.getLength() - 1] = rName;
76 rPropertyValues.realloc(rPropertyValues.getLength() + 1);
77 rPropertyValues[rPropertyValues.getLength() - 1] = rAny;
80 } // end anonymous namespace
82 uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape(
83 const uno::Reference< drawing::XDrawPage>& xDrawPage )
85 uno::Reference<drawing::XShapes> xRet = ShapeFactory::getChartRootShape(xDrawPage);
86 if (xRet.is())
87 return xRet;
89 // Create a new root shape and set it to the bottom of the page. The root
90 // shape is identified by having the name com.sun.star.chart2.shapes.
91 uno::Reference<drawing::XShape> xShape(
92 m_xShapeFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY);
93 uno::Reference<drawing::XShapes2> xShapes2(xDrawPage, uno::UNO_QUERY_THROW);
94 xShapes2->addBottom(xShape);
96 setShapeName(xShape, "com.sun.star.chart2.shapes");
97 xShape->setSize(awt::Size(0,0));
99 xRet.set(xShape, uno::UNO_QUERY);
100 return xRet;
103 void ShapeFactory::setPageSize(const uno::Reference<drawing::XShapes>&, const awt::Size&) {}
105 // diverse tools::PolyPolygon create methods
107 static 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 static 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 static 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& )
382 TOOLS_WARN_EXCEPTION("chart2", "" );
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& )
448 TOOLS_WARN_EXCEPTION("chart2", "" );
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& )
696 TOOLS_WARN_EXCEPTION("chart2", "" );
699 return xShape;
702 static void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, bool bAppendInverse )
704 if(!rAdd.Coordinates.hasElements())
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 static 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;
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 static 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;
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 // tdf#123504: both 0 and 360 are valid and different values here!
874 while (fUnitCircleWidthAngleDegree > 360)
875 fUnitCircleWidthAngleDegree -= 360.0;
876 while (fUnitCircleWidthAngleDegree < 0)
877 fUnitCircleWidthAngleDegree += 360.0;
879 //create shape
880 uno::Reference< drawing::XShape > xShape(
881 m_xShapeFactory->createInstance(
882 "com.sun.star.drawing.ClosedBezierShape" ), uno::UNO_QUERY );
883 xTarget->add(xShape); //need to add the shape before setting of properties
885 //set properties
886 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
887 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
888 if( xProp.is())
892 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
893 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
895 const double fAngleSubdivisionRadian = F_PI/10.0;
897 drawing::PolyPolygonBezierCoords aCoords
898 = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius,
899 basegfx::deg2rad(fUnitCircleStartAngleDegree),
900 basegfx::deg2rad(fUnitCircleWidthAngleDegree),
901 aTransformationFromUnitCircle, fAngleSubdivisionRadian);
903 xProp->setPropertyValue( "PolyPolygonBezier", uno::Any( aCoords ) );
905 catch( const uno::Exception& )
907 TOOLS_WARN_EXCEPTION("chart2", "" );
911 return xShape;
914 uno::Reference< drawing::XShape >
915 ShapeFactory::createPieSegment(
916 const uno::Reference< drawing::XShapes >& xTarget
917 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
918 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
919 , const drawing::Direction3D& rOffset
920 , const drawing::HomogenMatrix& rUnitCircleToScene
921 , double fDepth )
923 if( !xTarget.is() )
924 return nullptr;
926 // tdf#123504: both 0 and 360 are valid and different values here!
927 while (fUnitCircleWidthAngleDegree > 360)
928 fUnitCircleWidthAngleDegree -= 360.0;
929 while (fUnitCircleWidthAngleDegree < 0)
930 fUnitCircleWidthAngleDegree += 360.0;
932 //create shape
933 uno::Reference< drawing::XShape > xShape(
934 m_xShapeFactory->createInstance(
935 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
936 xTarget->add(xShape); //need to add the shape before setting of properties
938 //set properties
939 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
940 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
941 if( xProp.is())
945 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
946 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
948 const double fAngleSubdivisionRadian = F_PI/32.0;
950 drawing::PolyPolygonBezierCoords aCoords
951 = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius,
952 basegfx::deg2rad(fUnitCircleStartAngleDegree),
953 basegfx::deg2rad(fUnitCircleWidthAngleDegree),
954 aTransformationFromUnitCircle, fAngleSubdivisionRadian);
956 //depth
957 xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
958 , uno::Any(static_cast<sal_Int32>(fDepth)) );
960 //PercentDiagonal
961 xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
962 , uno::Any( sal_Int16(0) ) );
964 //Polygon
965 drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
966 ShapeFactory::closePolygon( aPoly );
967 xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
968 , uno::Any( aPoly ) );
970 //DoubleSided
971 xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
972 , uno::Any( true ) );
974 //Reduced lines
975 xProp->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
976 , uno::Any( true ) );
978 //TextureProjectionMode
979 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
980 , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
982 //TextureProjectionMode
983 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X
984 , uno::Any( drawing::TextureProjectionMode_PARALLEL ) );
985 xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
986 , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
988 catch( const uno::Exception& )
990 TOOLS_WARN_EXCEPTION("chart2", "" );
993 return xShape;
996 uno::Reference< drawing::XShape >
997 ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& xTarget
998 , const Stripe& rStripe
999 , const uno::Reference< beans::XPropertySet >& xSourceProp
1000 , const tPropertyNameMap& rPropertyNameMap
1001 , bool bDoubleSided
1002 , short nRotatedTexture
1003 , bool bFlatNormals )
1005 if( !xTarget.is() )
1006 return nullptr;
1008 //create shape
1009 uno::Reference< drawing::XShape > xShape(
1010 m_xShapeFactory->createInstance(
1011 "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY );
1012 xTarget->add(xShape);
1014 //set properties
1015 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
1016 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
1017 if (xMultiPropertySet.is())
1021 uno::Sequence<OUString> aPropertyNames{
1022 UNO_NAME_3D_POLYPOLYGON3D,
1023 UNO_NAME_3D_TEXTUREPOLYGON3D,
1024 UNO_NAME_3D_NORMALSPOLYGON3D,
1025 UNO_NAME_3D_LINEONLY,
1026 UNO_NAME_3D_DOUBLE_SIDED
1029 uno::Sequence<uno::Any> aPropertyValues {
1030 rStripe.getPolyPolygonShape3D(), // Polygon
1031 Stripe::getTexturePolygon(nRotatedTexture), // TexturePolygon
1032 rStripe.getNormalsPolygon(), // Normals Polygon
1033 uno::Any(false), // LineOnly
1034 uno::Any(bDoubleSided) // DoubleSided
1037 //NormalsKind
1038 if (bFlatNormals)
1039 lcl_addProperty(aPropertyNames, aPropertyValues,
1040 UNO_NAME_3D_NORMALS_KIND, uno::Any(drawing::NormalsKind_FLAT));
1042 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
1044 uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
1045 if (xSourceProp.is() && xPropertySet.is())
1047 PropertyMapper::setMappedProperties(xPropertySet, xSourceProp, rPropertyNameMap);
1050 catch( const uno::Exception& )
1052 TOOLS_WARN_EXCEPTION("chart2", "" );
1055 return xShape;
1058 uno::Reference< drawing::XShape >
1059 ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget
1060 , const drawing::PolyPolygonShape3D& rPolyPolygon
1061 , double fDepth )
1063 if( !xTarget.is() )
1064 return nullptr;
1066 if( !rPolyPolygon.SequenceX.hasElements())
1067 return nullptr;
1069 //create shape
1070 uno::Reference< drawing::XShape > xShape(
1071 m_xShapeFactory->createInstance(
1072 "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY );
1073 xTarget->add(xShape);
1075 //set properties
1076 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
1077 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
1078 if (xMultiPropertySet.is())
1082 uno::Sequence<OUString> aPropertyNames{
1083 UNO_NAME_3D_EXTRUDE_DEPTH,
1084 UNO_NAME_3D_PERCENT_DIAGONAL,
1085 UNO_NAME_3D_POLYPOLYGON3D,
1086 UNO_NAME_3D_DOUBLE_SIDED,
1089 uno::Sequence<uno::Any> aPropertyValues {
1090 uno::Any(sal_Int32(fDepth)), // depth
1091 uno::Any(sal_Int16(0)), // PercentDiagonal
1092 uno::Any(rPolyPolygon), // Polygon
1093 uno::Any(true) // DoubleSided
1096 //the z component of the polygon is now ignored by the drawing layer,
1097 //so we need to translate the object via transformation matrix
1099 //Matrix for position
1100 if (rPolyPolygon.SequenceZ.hasElements()&& rPolyPolygon.SequenceZ[0].hasElements())
1102 basegfx::B3DHomMatrix aM;
1103 aM.translate(0, 0, rPolyPolygon.SequenceZ[0][0]);
1104 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
1105 lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM));
1107 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
1109 catch( const uno::Exception& )
1111 TOOLS_WARN_EXCEPTION("chart2", "" );
1114 return xShape;
1117 uno::Reference< drawing::XShape >
1118 ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget
1119 , const drawing::PolyPolygonShape3D& rPolyPolygon )
1121 if( !xTarget.is() )
1122 return nullptr;
1124 //create shape
1125 uno::Reference< drawing::XShape > xShape(
1126 m_xShapeFactory->createInstance(
1127 "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY );
1128 xTarget->add(xShape);
1130 //set properties
1131 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1132 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1133 if( xProp.is())
1137 //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
1138 drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) );
1140 //Polygon
1141 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1142 , uno::Any( aPoints ) );
1144 //ZOrder
1145 //an area should always be behind other shapes
1146 xProp->setPropertyValue( UNO_NAME_MISC_OBJ_ZORDER
1147 , uno::Any( sal_Int32(0) ) );
1149 catch( const uno::Exception& )
1151 TOOLS_WARN_EXCEPTION("chart2", "" );
1154 return xShape;
1157 static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Position3D& rPos
1158 , const drawing::Direction3D& rSize
1159 , sal_Int32 nStandardSymbol )
1161 if(nStandardSymbol<0)
1162 nStandardSymbol*=-1;
1163 nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
1164 SymbolEnum eSymbolType=static_cast<SymbolEnum>(nStandardSymbol);
1166 const double& fX = rPos.PositionX;
1167 const double& fY = rPos.PositionY;
1169 const double fWidthH = rSize.DirectionX/2.0; //fWidthH stands for Half Width
1170 const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
1172 const sal_Int32 nQuarterCount = 35; // points inside a quadrant, used in case circle
1174 sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
1175 switch( eSymbolType )
1177 case Symbol_Square:
1178 case Symbol_Diamond:
1179 case Symbol_Bowtie:
1180 case Symbol_Sandglass:
1181 case Symbol_HorizontalBar:
1182 case Symbol_VerticalBar:
1183 nPointCount = 5;
1184 break;
1185 case Symbol_X:
1186 nPointCount = 13;
1187 break;
1188 case Symbol_Plus:
1189 nPointCount = 13;
1190 break;
1191 case Symbol_Star:
1192 nPointCount = 9;
1193 break;
1194 case Symbol_Asterisk:
1195 nPointCount = 19;
1196 break;
1197 case Symbol_Circle:
1198 nPointCount = 5 + 4 * nQuarterCount;
1199 break;
1200 default:
1201 break;
1204 drawing::PolyPolygonShape3D aPP;
1206 aPP.SequenceX.realloc(1);
1207 aPP.SequenceY.realloc(1);
1208 aPP.SequenceZ.realloc(1);
1210 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
1211 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
1212 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
1214 pOuterSequenceX->realloc(nPointCount);
1215 pOuterSequenceY->realloc(nPointCount);
1216 pOuterSequenceZ->realloc(nPointCount);
1218 double* pInnerSequenceX = pOuterSequenceX->getArray();
1219 double* pInnerSequenceY = pOuterSequenceY->getArray();
1220 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
1222 for(sal_Int32 nN = nPointCount; nN--;)
1223 *pInnerSequenceZ++ = 0.0;
1225 switch(eSymbolType)
1227 case Symbol_Square:
1229 *pInnerSequenceX++ = fX-fWidthH;
1230 *pInnerSequenceY++ = fY-fHeightH;
1232 *pInnerSequenceX++ = fX-fWidthH;
1233 *pInnerSequenceY++ = fY+fHeightH;
1235 *pInnerSequenceX++ = fX+fWidthH;
1236 *pInnerSequenceY++ = fY+fHeightH;
1238 *pInnerSequenceX++ = fX+fWidthH;
1239 *pInnerSequenceY++ = fY-fHeightH;
1241 *pInnerSequenceX++ = fX-fWidthH;
1242 *pInnerSequenceY++ = fY-fHeightH;
1243 break;
1245 case Symbol_UpArrow:
1247 *pInnerSequenceX++ = fX-fWidthH;
1248 *pInnerSequenceY++ = fY+fHeightH;
1250 *pInnerSequenceX++ = fX+fWidthH;
1251 *pInnerSequenceY++ = fY+fHeightH;
1253 *pInnerSequenceX++ = fX;
1254 *pInnerSequenceY++ = fY-fHeightH;
1256 *pInnerSequenceX++ = fX-fWidthH;
1257 *pInnerSequenceY++ = fY+fHeightH;
1258 break;
1260 case Symbol_DownArrow:
1262 *pInnerSequenceX++ = fX-fWidthH;
1263 *pInnerSequenceY++ = fY-fHeightH;
1265 *pInnerSequenceX++ = fX;
1266 *pInnerSequenceY++ = fY+fHeightH;
1268 *pInnerSequenceX++ = fX+fWidthH;
1269 *pInnerSequenceY++ = fY-fHeightH;
1271 *pInnerSequenceX++ = fX-fWidthH;
1272 *pInnerSequenceY++ = fY-fHeightH;
1273 break;
1275 case Symbol_RightArrow:
1277 *pInnerSequenceX++ = fX-fWidthH;
1278 *pInnerSequenceY++ = fY-fHeightH;
1280 *pInnerSequenceX++ = fX-fWidthH;
1281 *pInnerSequenceY++ = fY+fHeightH;
1283 *pInnerSequenceX++ = fX+fWidthH;
1284 *pInnerSequenceY++ = fY;
1286 *pInnerSequenceX++ = fX-fWidthH;
1287 *pInnerSequenceY++ = fY-fHeightH;
1288 break;
1290 case Symbol_LeftArrow:
1292 *pInnerSequenceX++ = fX-fWidthH;
1293 *pInnerSequenceY++ = fY;
1295 *pInnerSequenceX++ = fX+fWidthH;
1296 *pInnerSequenceY++ = fY+fHeightH;
1298 *pInnerSequenceX++ = fX+fWidthH;
1299 *pInnerSequenceY++ = fY-fHeightH;
1301 *pInnerSequenceX++ = fX-fWidthH;
1302 *pInnerSequenceY++ = fY;
1303 break;
1305 case Symbol_Bowtie:
1307 *pInnerSequenceX++ = fX-fWidthH;
1308 *pInnerSequenceY++ = fY-fHeightH;
1310 *pInnerSequenceX++ = fX-fWidthH;
1311 *pInnerSequenceY++ = fY+fHeightH;
1313 *pInnerSequenceX++ = fX+fWidthH;
1314 *pInnerSequenceY++ = fY-fHeightH;
1316 *pInnerSequenceX++ = fX+fWidthH;
1317 *pInnerSequenceY++ = fY+fHeightH;
1319 *pInnerSequenceX++ = fX-fWidthH;
1320 *pInnerSequenceY++ = fY-fHeightH;
1321 break;
1323 case Symbol_Sandglass:
1325 *pInnerSequenceX++ = fX-fWidthH;
1326 *pInnerSequenceY++ = fY+fHeightH;
1328 *pInnerSequenceX++ = fX+fWidthH;
1329 *pInnerSequenceY++ = fY+fHeightH;
1331 *pInnerSequenceX++ = fX-fWidthH;
1332 *pInnerSequenceY++ = fY-fHeightH;
1334 *pInnerSequenceX++ = fX+fWidthH;
1335 *pInnerSequenceY++ = fY-fHeightH;
1337 *pInnerSequenceX++ = fX-fWidthH;
1338 *pInnerSequenceY++ = fY+fHeightH;
1339 break;
1341 case Symbol_Diamond:
1343 *pInnerSequenceX++ = fX-fWidthH;
1344 *pInnerSequenceY++ = fY;
1346 *pInnerSequenceX++ = fX;
1347 *pInnerSequenceY++ = fY+fHeightH;
1349 *pInnerSequenceX++ = fX+fWidthH;
1350 *pInnerSequenceY++ = fY;
1352 *pInnerSequenceX++ = fX;
1353 *pInnerSequenceY++ = fY-fHeightH;
1355 *pInnerSequenceX++ = fX-fWidthH;
1356 *pInnerSequenceY++ = fY;
1357 break;
1359 case Symbol_HorizontalBar:
1361 *pInnerSequenceX++ = fX-fWidthH;
1362 *pInnerSequenceY++ = fY-0.2*fHeightH;
1364 *pInnerSequenceX++ = fX+fWidthH;
1365 *pInnerSequenceY++ = fY-0.2*fHeightH;
1367 *pInnerSequenceX++ = fX+fWidthH;
1368 *pInnerSequenceY++ = fY+0.2*fHeightH;
1370 *pInnerSequenceX++ = fX-fWidthH;
1371 *pInnerSequenceY++ = fY+0.2*fHeightH;
1373 *pInnerSequenceX++ = fX-fWidthH;
1374 *pInnerSequenceY++ = fY-0.2*fHeightH;
1375 break;
1377 case Symbol_VerticalBar:
1379 *pInnerSequenceX++ = fX-0.2*fWidthH;
1380 *pInnerSequenceY++ = fY-fHeightH;
1382 *pInnerSequenceX++ = fX+0.2*fWidthH;
1383 *pInnerSequenceY++ = fY-fHeightH;
1385 *pInnerSequenceX++ = fX+0.2*fWidthH;
1386 *pInnerSequenceY++ = fY+fHeightH;
1388 *pInnerSequenceX++ = fX-0.2*fWidthH;
1389 *pInnerSequenceY++ = fY+fHeightH;
1391 *pInnerSequenceX++ = fX-0.2*fWidthH;
1392 *pInnerSequenceY++ = fY-fHeightH;
1394 break;
1396 case Symbol_Circle:
1398 double fOmega = 1.5707963267948966192 / (nQuarterCount + 1.0);
1399 // one point in the middle of each edge to get full size bounding rectangle
1400 *pInnerSequenceX++ = fX + fWidthH;
1401 *pInnerSequenceY++ = fY;
1402 // 0 to PI/2
1403 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1405 *pInnerSequenceX++ = fX + fWidthH * cos( i * fOmega );
1406 *pInnerSequenceY++ = fY - fHeightH * sin( i * fOmega );
1408 // PI/2 to PI
1409 *pInnerSequenceX++ = fX;
1410 *pInnerSequenceY++ = fY - fHeightH;
1411 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1413 *pInnerSequenceX++ = fX - fWidthH * sin( i * fOmega);
1414 *pInnerSequenceY++ = fY - fHeightH * cos( i * fOmega);
1416 // PI to 3/2*PI
1417 *pInnerSequenceX++ = fX - fWidthH;
1418 *pInnerSequenceY++ = fY;
1419 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1421 *pInnerSequenceX++ = fX - fWidthH * cos( i * fOmega);
1422 *pInnerSequenceY++ = fY + fHeightH * sin( i * fOmega);
1424 // 3/2*PI to 2*PI
1425 *pInnerSequenceX++ = fX;
1426 *pInnerSequenceY++ = fY + fHeightH;
1427 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1429 *pInnerSequenceX++ = fX + fWidthH * sin(i * fOmega);
1430 *pInnerSequenceY++ = fY + fHeightH * cos(i * fOmega);
1432 // close polygon
1433 *pInnerSequenceX++ = fX + fWidthH;
1434 *pInnerSequenceY++ = fY;
1435 break;
1437 case Symbol_Star:
1439 *pInnerSequenceX++ = fX;
1440 *pInnerSequenceY++ = fY-fHeightH;
1442 *pInnerSequenceX++ = fX+0.2*fWidthH;
1443 *pInnerSequenceY++ = fY-0.2*fHeightH;
1445 *pInnerSequenceX++ = fX+fWidthH;
1446 *pInnerSequenceY++ = fY;
1448 *pInnerSequenceX++ = fX+0.2*fWidthH;
1449 *pInnerSequenceY++ = fY+0.2*fHeightH;
1451 *pInnerSequenceX++ = fX;
1452 *pInnerSequenceY++ = fY+fHeightH;
1454 *pInnerSequenceX++ = fX-0.2*fWidthH;
1455 *pInnerSequenceY++ = fY+0.2*fHeightH;
1457 *pInnerSequenceX++ = fX-fWidthH;
1458 *pInnerSequenceY++ = fY;
1460 *pInnerSequenceX++ = fX-0.2*fWidthH;
1461 *pInnerSequenceY++ = fY-0.2*fHeightH;
1463 *pInnerSequenceX++ = fX;
1464 *pInnerSequenceY++ = fY-fHeightH;
1465 break;
1467 case Symbol_X:
1469 const double fScaleX = fWidthH / 128.0;
1470 const double fScaleY = fHeightH / 128.0;
1471 const double fSmall = sqrt(200.0);
1472 const double fLarge = 128.0 - fSmall;
1474 *pInnerSequenceX++ = fX;
1475 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1477 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1478 *pInnerSequenceY++ = fY - fHeightH;
1480 *pInnerSequenceX++ = fX - fWidthH;
1481 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1483 *pInnerSequenceX++ = fX - fScaleX * fSmall;
1484 *pInnerSequenceY++ = fY;
1486 *pInnerSequenceX++ = fX - fWidthH;
1487 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1489 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1490 *pInnerSequenceY++ = fY + fHeightH;
1492 *pInnerSequenceX++ = fX;
1493 *pInnerSequenceY++ = fY + fScaleY * fSmall;
1495 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1496 *pInnerSequenceY++ = fY + fHeightH;
1498 *pInnerSequenceX++ = fX + fWidthH;
1499 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1501 *pInnerSequenceX++ = fX + fScaleX * fSmall;
1502 *pInnerSequenceY++ = fY;
1504 *pInnerSequenceX++ = fX + fWidthH;
1505 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1507 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1508 *pInnerSequenceY++ = fY - fHeightH;
1510 *pInnerSequenceX++ = fX;
1511 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1512 break;
1515 case Symbol_Plus:
1517 const double fScaleX = fWidthH / 128.0;
1518 const double fScaleY = fHeightH / 128.0;
1519 const double fHalf = 10.0; //half line width on 256 size square
1520 const double fdX = fScaleX * fHalf;
1521 const double fdY = fScaleY * fHalf;
1523 *pInnerSequenceX++ = fX-fdX;
1524 *pInnerSequenceY++ = fY-fHeightH;
1526 *pInnerSequenceX++ = fX-fdX;
1527 *pInnerSequenceY++ = fY-fdY;
1529 *pInnerSequenceX++ = fX-fWidthH;
1530 *pInnerSequenceY++ = fY-fdY;
1532 *pInnerSequenceX++ = fX-fWidthH;
1533 *pInnerSequenceY++ = fY+fdY;
1535 *pInnerSequenceX++ = fX-fdX;
1536 *pInnerSequenceY++ = fY+fdY;
1538 *pInnerSequenceX++ = fX-fdX;
1539 *pInnerSequenceY++ = fY+fHeightH;
1541 *pInnerSequenceX++ = fX+fdX;
1542 *pInnerSequenceY++ = fY+fHeightH;
1544 *pInnerSequenceX++ = fX+fdX;
1545 *pInnerSequenceY++ = fY+fdY;
1547 *pInnerSequenceX++ = fX+fWidthH;
1548 *pInnerSequenceY++ = fY+fdY;
1550 *pInnerSequenceX++ = fX+fWidthH;
1551 *pInnerSequenceY++ = fY-fdY;
1553 *pInnerSequenceX++ = fX+fdX;
1554 *pInnerSequenceY++ = fY-fdY;
1556 *pInnerSequenceX++ = fX+fdY;
1557 *pInnerSequenceY++ = fY-fHeightH;
1559 *pInnerSequenceX++ = fX-fdX;
1560 *pInnerSequenceY++ = fY-fHeightH;
1561 break;
1564 case Symbol_Asterisk:
1566 const double fHalf = 10.0; // half line width on 256 size square
1567 const double fTwoY = fHalf * sqrt(3.0);
1568 const double fFourY = (128.0 - 2.0 * fHalf ) / sqrt(3.0);
1569 const double fThreeX = 128.0 - fHalf;
1570 const double fThreeY = fHalf * sqrt(3.0) + fFourY;
1571 const double fFiveX = 2.0 * fHalf;
1573 const double fScaleX = fWidthH / 128.0;
1574 const double fScaleY = fHeightH / 128.0;
1577 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1578 *pInnerSequenceY++ = fY-fHeightH;
1580 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1581 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1583 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1584 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1586 *pInnerSequenceX++ = fX-fWidthH;
1587 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1589 *pInnerSequenceX++ = fX-fScaleX * fFiveX;
1590 *pInnerSequenceY++ = fY;
1591 //6 as 4
1592 *pInnerSequenceX++ = fX-fWidthH;
1593 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1594 //7 as 3
1595 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1596 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1597 //8 as 2
1598 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1599 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1600 //9 as 1
1601 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1602 *pInnerSequenceY++ = fY+fHeightH;
1603 //10 as 1
1604 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1605 *pInnerSequenceY++ = fY+fHeightH;
1606 //11 as 2
1607 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1608 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1609 //12 as 3
1610 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1611 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1612 //13 as 4
1613 *pInnerSequenceX++ = fX+fWidthH;
1614 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1615 //14 as 5
1616 *pInnerSequenceX++ = fX+fScaleX * fFiveX;
1617 *pInnerSequenceY++ = fY;
1618 //15 as 4
1619 *pInnerSequenceX++ = fX+fWidthH;
1620 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1621 //16 as 3
1622 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1623 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1624 //17 as 2
1625 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1626 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1627 // 18 as 1
1628 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1629 *pInnerSequenceY++ = fY-fHeightH;
1630 // 19 = 1, closing
1631 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1632 *pInnerSequenceY++ = fY-fHeightH;
1633 break;
1635 default: //case Symbol_Square:
1637 *pInnerSequenceX++ = fX-fWidthH;
1638 *pInnerSequenceY++ = fY-fHeightH;
1640 *pInnerSequenceX++ = fX-fWidthH;
1641 *pInnerSequenceY++ = fY+fHeightH;
1643 *pInnerSequenceX++ = fX+fWidthH;
1644 *pInnerSequenceY++ = fY+fHeightH;
1646 *pInnerSequenceX++ = fX+fWidthH;
1647 *pInnerSequenceY++ = fY-fHeightH;
1649 *pInnerSequenceX++ = fX-fWidthH;
1650 *pInnerSequenceY++ = fY-fHeightH;
1651 break;
1655 return aPP;
1658 uno::Reference< drawing::XShape >
1659 ShapeFactory::createSymbol2D(
1660 const uno::Reference< drawing::XShapes >& xTarget
1661 , const drawing::Position3D& rPosition
1662 , const drawing::Direction3D& rSize
1663 , sal_Int32 nStandardSymbol
1664 , sal_Int32 nBorderColor
1665 , sal_Int32 nFillColor )
1667 if( !xTarget.is() )
1668 return nullptr;
1670 //create shape
1671 uno::Reference< drawing::XShape > xShape(
1672 m_xShapeFactory->createInstance(
1673 "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY );
1674 xTarget->add(xShape);
1676 //set properties
1677 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1678 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1679 if( xProp.is())
1683 drawing::PointSequenceSequence aPoints( PolyToPointSequence(
1684 createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) ));
1686 //Polygon
1687 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
1688 , uno::Any( aPoints ) );
1690 //LineColor
1691 xProp->setPropertyValue( UNO_NAME_LINECOLOR
1692 , uno::Any( nBorderColor ) );
1694 //FillColor
1695 xProp->setPropertyValue( UNO_NAME_FILLCOLOR
1696 , uno::Any( nFillColor ) );
1698 catch( const uno::Exception& )
1700 TOOLS_WARN_EXCEPTION("chart2", "" );
1703 return xShape;
1706 uno::Reference< drawing::XShape >
1707 ShapeFactory::createGraphic2D(
1708 const uno::Reference< drawing::XShapes >& xTarget
1709 , const drawing::Position3D& rPosition
1710 , const drawing::Direction3D& rSize
1711 , const uno::Reference< graphic::XGraphic >& xGraphic )
1713 if( !xTarget.is() || !xGraphic.is() )
1714 return nullptr;
1716 // @todo: change this to a rectangle shape with a fill bitmap for
1717 // performance reasons (ask AW, said CL)
1719 //create shape
1720 uno::Reference< drawing::XShape > xShape(
1721 m_xShapeFactory->createInstance(
1722 "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY );
1723 xTarget->add(xShape);
1727 // assume position is upper left corner. Transform to center.
1728 drawing::Position3D aCenterPosition(
1729 rPosition.PositionX - (rSize.DirectionX / 2.0),
1730 rPosition.PositionY - (rSize.DirectionY / 2.0),
1731 rPosition.PositionZ );
1732 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1733 xShape->setSize( Direction3DToAWTSize( rSize ));
1735 catch( const uno::Exception & )
1737 TOOLS_WARN_EXCEPTION("chart2", "" );
1739 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1740 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1741 if( xProp.is())
1745 xProp->setPropertyValue( "Graphic", uno::Any( xGraphic ));
1747 catch( const uno::Exception& )
1749 TOOLS_WARN_EXCEPTION("chart2", "" );
1752 return xShape;
1755 uno::Reference< drawing::XShapes >
1756 ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget
1757 , const OUString& aName )
1759 if( !xTarget.is() )
1760 return nullptr;
1763 //create and add to target
1764 uno::Reference< drawing::XShape > xShape(
1765 m_xShapeFactory->createInstance(
1766 "com.sun.star.drawing.GroupShape" ), uno::UNO_QUERY );
1767 xTarget->add(xShape);
1769 //set name
1770 if(!aName.isEmpty())
1771 setShapeName( xShape , aName );
1773 {//workaround
1774 //need this null size as otherwise empty group shapes where painted with a gray border
1775 xShape->setSize(awt::Size(0,0));
1778 //return
1779 uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY );
1780 return xShapes;
1782 catch( const uno::Exception& )
1784 TOOLS_WARN_EXCEPTION("chart2", "" );
1786 return nullptr;
1789 uno::Reference< drawing::XShapes >
1790 ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget
1791 , const OUString& aName )
1793 if( !xTarget.is() )
1794 return nullptr;
1797 //create shape
1798 uno::Reference< drawing::XShape > xShape(
1799 m_xShapeFactory->createInstance(
1800 "com.sun.star.drawing.Shape3DSceneObject" ), uno::UNO_QUERY );
1802 xTarget->add(xShape);
1804 //it is necessary to set the transform matrix to initialize the scene properly
1805 //otherwise all objects which are placed into this Group will not be visible
1806 //the following should be unnecessary after the bug is fixed
1808 //set properties
1809 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1810 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1811 if( xProp.is())
1815 ::basegfx::B3DHomMatrix aM;
1816 xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
1817 , uno::Any(B3DHomMatrixToHomogenMatrix(aM)) );
1819 catch( const uno::Exception& )
1821 TOOLS_WARN_EXCEPTION("chart2", "" );
1826 //set name
1827 if(!aName.isEmpty())
1828 setShapeName( xShape , aName );
1830 //return
1831 uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY );
1832 return xShapes;
1834 catch( const uno::Exception& )
1836 TOOLS_WARN_EXCEPTION("chart2", "" );
1838 return nullptr;
1841 uno::Reference< drawing::XShape >
1842 ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget
1843 , const drawing::Position3D& rPosition
1844 , const drawing::Direction3D& rSize )
1846 if( !xTarget.is() )
1847 return nullptr;
1849 //create shape
1850 uno::Reference< drawing::XShape > xShape(
1851 m_xShapeFactory->createInstance(
1852 "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY );
1853 xTarget->add(xShape);
1857 drawing::Position3D aCenterPosition(
1858 rPosition.PositionX - (rSize.DirectionX / 2.0),
1859 rPosition.PositionY - (rSize.DirectionY / 2.0),
1860 rPosition.PositionZ );
1861 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1862 xShape->setSize( Direction3DToAWTSize( rSize ));
1864 catch( const uno::Exception & )
1866 TOOLS_WARN_EXCEPTION("chart2", "" );
1869 //set properties
1870 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1871 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1872 if( xProp.is())
1876 xProp->setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) );
1878 catch( const uno::Exception& )
1880 TOOLS_WARN_EXCEPTION("chart2", "" );
1883 return xShape;
1886 uno::Reference< drawing::XShape >
1887 ShapeFactory::createCircle( const uno::Reference< drawing::XShapes >& xTarget
1888 , const awt::Size& rSize
1889 , const awt::Point& rPosition )
1891 uno::Reference< drawing::XShape > xShape(
1892 m_xShapeFactory->createInstance(
1893 "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY );
1894 xTarget->add(xShape);
1895 xShape->setSize( rSize );
1896 xShape->setPosition( rPosition );
1898 return xShape;
1901 uno::Reference< drawing::XShape >
1902 ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget
1903 , const drawing::PolyPolygonShape3D& rPoints
1904 , const VLineProperties& rLineProperties )
1906 if( !xTarget.is() )
1907 return nullptr;
1909 if(!rPoints.SequenceX.hasElements())
1910 return nullptr;
1912 //create shape
1913 uno::Reference< drawing::XShape > xShape(
1914 m_xShapeFactory->createInstance(
1915 "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY );
1916 xTarget->add(xShape);
1918 //set properties
1919 uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY);
1920 OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet");
1921 if (xMultiPropertySet.is())
1925 uno::Sequence<OUString> aPropertyNames {
1926 UNO_NAME_3D_POLYPOLYGON3D,
1927 UNO_NAME_3D_LINEONLY
1930 uno::Sequence<uno::Any> aPropertyValues {
1931 uno::Any(rPoints), // Polygon
1932 uno::Any(true) // LineOnly
1935 //Transparency
1936 if(rLineProperties.Transparence.hasValue())
1938 lcl_addProperty(aPropertyNames, aPropertyValues,
1939 UNO_NAME_LINETRANSPARENCE,
1940 rLineProperties.Transparence);
1943 //LineStyle
1944 if(rLineProperties.LineStyle.hasValue())
1946 lcl_addProperty(aPropertyNames, aPropertyValues,
1947 UNO_NAME_LINESTYLE,
1948 rLineProperties.LineStyle);
1951 //LineWidth
1952 if(rLineProperties.Width.hasValue())
1954 lcl_addProperty(aPropertyNames, aPropertyValues,
1955 UNO_NAME_LINEWIDTH,
1956 rLineProperties.Width);
1959 //LineColor
1960 if(rLineProperties.Color.hasValue())
1962 lcl_addProperty(aPropertyNames, aPropertyValues,
1963 UNO_NAME_LINECOLOR,
1964 rLineProperties.Color);
1966 xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues);
1968 catch( const uno::Exception& )
1970 TOOLS_WARN_EXCEPTION("chart2", "" );
1973 return xShape;
1976 uno::Reference< drawing::XShape >
1977 ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget
1978 , const drawing::PointSequenceSequence& rPoints
1979 , const VLineProperties* pLineProperties )
1981 if( !xTarget.is() )
1982 return nullptr;
1984 if(!rPoints.hasElements())
1985 return nullptr;
1987 //create shape
1988 uno::Reference< drawing::XShape > xShape(
1989 m_xShapeFactory->createInstance(
1990 "com.sun.star.drawing.PolyLineShape" ), uno::UNO_QUERY );
1991 xTarget->add(xShape);
1993 //set properties
1994 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1995 OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet");
1996 if( xProp.is())
2000 //Polygon
2001 xProp->setPropertyValue( UNO_NAME_POLYPOLYGON
2002 , uno::Any( rPoints ) );
2004 if(pLineProperties)
2006 //Transparency
2007 if(pLineProperties->Transparence.hasValue())
2008 xProp->setPropertyValue( UNO_NAME_LINETRANSPARENCE
2009 , pLineProperties->Transparence );
2011 //LineStyle
2012 if(pLineProperties->LineStyle.hasValue())
2013 xProp->setPropertyValue( UNO_NAME_LINESTYLE
2014 , pLineProperties->LineStyle );
2016 //LineWidth
2017 if(pLineProperties->Width.hasValue())
2018 xProp->setPropertyValue( UNO_NAME_LINEWIDTH
2019 , pLineProperties->Width );
2021 //LineColor
2022 if(pLineProperties->Color.hasValue())
2023 xProp->setPropertyValue( UNO_NAME_LINECOLOR
2024 , pLineProperties->Color );
2026 //LineDashName
2027 if(pLineProperties->DashName.hasValue())
2028 xProp->setPropertyValue( "LineDashName"
2029 , pLineProperties->DashName );
2032 catch( const uno::Exception& )
2034 TOOLS_WARN_EXCEPTION("chart2", "" );
2037 return xShape;
2040 uno::Reference< drawing::XShape >
2041 ShapeFactory::createLine ( const uno::Reference< drawing::XShapes >& xTarget,
2042 const awt::Size& rSize, const awt::Point& rPosition )
2044 //create shape
2045 uno::Reference< drawing::XShape > xShape(
2046 m_xShapeFactory->createInstance(
2047 "com.sun.star.drawing.LineShape" ), uno::UNO_QUERY );
2048 xTarget->add(xShape);
2049 xShape->setSize( rSize );
2050 xShape->setPosition( rPosition );
2052 return xShape;
2055 uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle(
2056 const uno::Reference< drawing::XShapes >& xTarget
2057 , const awt::Size& rSize )
2061 if(!xTarget.is())
2062 return nullptr;
2064 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2065 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2066 if( xShape.is())
2068 xTarget->add( xShape );
2069 ShapeFactory::makeShapeInvisible( xShape );
2070 xShape->setSize( rSize );
2072 return xShape;
2074 catch( const uno::Exception & )
2076 DBG_UNHANDLED_EXCEPTION("chart2");
2078 return nullptr;
2081 uno::Reference< drawing::XShape > ShapeFactory::createRectangle(
2082 const uno::Reference< drawing::XShapes >& xTarget,
2083 const awt::Size& rSize,
2084 const awt::Point& rPosition,
2085 const tNameSequence& rPropNames,
2086 const tAnySequence& rPropValues,
2087 StackPosition ePos )
2089 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2090 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2091 if( xShape.is())
2093 if (ePos == StackPosition::Bottom)
2095 uno::Reference<drawing::XShapes2> xTarget2(xTarget, uno::UNO_QUERY);
2096 if (xTarget2.is())
2097 xTarget2->addBottom(xShape);
2099 else
2100 xTarget->add(xShape);
2102 xShape->setPosition( rPosition );
2103 xShape->setSize( rSize );
2104 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY_THROW );
2105 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xPropSet );
2108 return xShape;
2111 uno::Reference< drawing::XShape >
2112 ShapeFactory::createRectangle(
2113 const uno::Reference<
2114 drawing::XShapes >& xTarget )
2116 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2117 "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY );
2118 xTarget->add( xShape );
2120 return xShape;
2123 uno::Reference< drawing::XShape >
2124 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2125 , const OUString& rText
2126 , const tNameSequence& rPropNames
2127 , const tAnySequence& rPropValues
2128 , const uno::Any& rATransformation )
2130 if( !xTarget.is() )
2131 return nullptr;
2133 if(rText.isEmpty())
2134 return nullptr;
2136 //create shape and add to page
2137 uno::Reference< drawing::XShape > xShape(
2138 m_xShapeFactory->createInstance(
2139 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2140 xTarget->add(xShape);
2142 //set text
2143 uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY );
2144 if( xTextRange.is() )
2145 xTextRange->setString( rText );
2147 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2148 if( xProp.is() )
2150 //set properties
2151 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2153 //set position matrix
2154 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2157 if (rATransformation.hasValue())
2158 xProp->setPropertyValue( "Transformation", rATransformation );
2159 else
2160 SAL_INFO("chart2", "No rATransformation value is given to ShapeFactory::createText()");
2163 catch( const uno::Exception& )
2165 TOOLS_WARN_EXCEPTION("chart2", "" );
2168 return xShape;
2171 uno::Reference< drawing::XShape >
2172 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2173 , const uno::Sequence< OUString >& rTextParagraphs
2174 , const uno::Sequence< tNameSequence >& rParaPropNames
2175 , const uno::Sequence< tAnySequence >& rParaPropValues
2176 , const tNameSequence& rPropNames
2177 , const tAnySequence& rPropValues
2178 , const uno::Any& rATransformation )
2180 if( !xTarget.is() )
2181 return nullptr;
2183 if( !rTextParagraphs.hasElements() )
2184 return nullptr;
2186 sal_Int32 nNumberOfParagraphs = rTextParagraphs.getLength();
2188 if( rParaPropNames.getLength() != nNumberOfParagraphs )
2189 return nullptr;
2191 if( rParaPropValues.getLength() != nNumberOfParagraphs )
2192 return nullptr;
2194 bool bNotEmpty = false;
2195 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2197 if( !rTextParagraphs[nN].isEmpty() )
2199 bNotEmpty = true;
2200 break;
2203 if( !bNotEmpty )
2204 return nullptr;
2206 //create shape and add to page
2207 uno::Reference< drawing::XShape > xShape(
2208 m_xShapeFactory->createInstance(
2209 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2210 xTarget->add(xShape);
2212 //set paragraph properties
2213 bNotEmpty = false;
2214 Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2215 if( xText.is() )
2217 // the first cursor is used for appending the next paragraph,
2218 // after a new string has been inserted the cursor is moved at the end
2219 // of the inserted string
2220 // the second cursor is used for selecting the paragraph and apply the
2221 // passed text properties
2222 Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor();
2223 Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor();
2224 if( xInsertCursor.is() && xSelectionCursor.is() )
2226 uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
2227 if( xSelectionProp.is() )
2229 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2231 if( !rTextParagraphs[nN].isEmpty() )
2233 xInsertCursor->gotoEnd(false);
2234 if( bNotEmpty )
2236 xText->insertString( xInsertCursor, "\n", false );
2238 xSelectionCursor->gotoEnd(false);
2239 xText->insertString( xInsertCursor, rTextParagraphs[nN], false );
2240 bNotEmpty = true;
2241 xSelectionCursor->gotoEnd(true); // select current paragraph
2242 PropertyMapper::setMultiProperties( rParaPropNames[nN], rParaPropValues[nN], xSelectionProp );
2249 if( !bNotEmpty )
2250 return nullptr;
2252 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2253 if( xProp.is() )
2255 //set whole text shape properties
2256 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2258 if (rATransformation.hasValue())
2260 //set position matrix
2261 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2264 xProp->setPropertyValue( "Transformation", rATransformation );
2266 catch( const uno::Exception& )
2268 TOOLS_WARN_EXCEPTION("chart2", "" );
2272 return xShape;
2275 uno::Reference< drawing::XShape >
2276 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2277 , uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString
2278 , const tNameSequence& rPropNames
2279 , const tAnySequence& rPropValues
2280 , const uno::Any& rATransformation )
2282 if( !xTarget.is() )
2283 return nullptr;
2285 if( !xFormattedString.hasElements() )
2286 return nullptr;
2288 sal_Int32 nNumberOfParagraphs = xFormattedString.getLength();
2290 bool bNotEmpty = false;
2291 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2293 if( !xFormattedString[nN]->getString().isEmpty() )
2295 bNotEmpty = true;
2296 break;
2299 if( !bNotEmpty )
2300 return nullptr;
2302 //create shape and add to page
2303 uno::Reference< drawing::XShape > xShape(
2304 m_xShapeFactory->createInstance(
2305 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2306 xTarget->add(xShape);
2308 //set paragraph properties
2309 bNotEmpty = false;
2310 Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2311 if( xText.is() )
2313 // the first cursor is used for appending the next paragraph,
2314 // after a new string has been inserted the cursor is moved at the end
2315 // of the inserted string
2316 // the second cursor is used for selecting the paragraph and apply the
2317 // passed text properties
2318 Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor();
2319 Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor();
2320 if( xInsertCursor.is() && xSelectionCursor.is() )
2322 uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
2323 if( xSelectionProp.is() )
2325 for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2327 if( !xFormattedString[nN]->getString().isEmpty() )
2329 xInsertCursor->gotoEnd( false );
2330 xSelectionCursor->gotoEnd( false );
2331 xText->insertString( xInsertCursor, xFormattedString[nN]->getString(), false );
2332 bNotEmpty = true;
2333 xSelectionCursor->gotoEnd( true ); // select current paragraph
2334 uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY );
2335 PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties,
2336 PropertyMapper::getPropertyNameMapForTextShapeProperties() );
2343 if( !bNotEmpty )
2344 return nullptr;
2346 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2347 if( xProp.is() )
2349 //set whole text shape properties
2350 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2352 if( rATransformation.hasValue() )
2354 //set position matrix
2355 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2358 xProp->setPropertyValue( "Transformation", rATransformation );
2360 catch( const uno::Exception& )
2362 TOOLS_WARN_EXCEPTION("chart2", "" );
2366 return xShape;
2369 uno::Reference< drawing::XShape >
2370 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget,
2371 const awt::Size& rSize,
2372 const awt::Point& rPos,
2373 uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString,
2374 const uno::Reference<
2375 beans::XPropertySet > & xTextProperties,
2376 double nRotation, const OUString& aName )
2378 //create shape and add to page
2379 uno::Reference< drawing::XShape > xShape(
2380 m_xShapeFactory->createInstance(
2381 "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
2384 xTarget->add(xShape);
2386 //set text and text properties
2387 uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2388 uno::Reference< text::XTextCursor > xTextCursor( xText->createTextCursor() );
2389 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
2390 if( !xText.is() || !xTextCursor.is() || !xShapeProp.is() || !xTextProperties.is() )
2391 return xShape;
2393 tPropertyNameValueMap aValueMap;
2394 //fill line-, fill- and paragraph-properties into the ValueMap
2396 tPropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForParagraphProperties();
2397 auto const & add = PropertyMapper::getPropertyNameMapForFillAndLineProperties();
2398 aNameMap.insert(add.begin(), add.end());
2400 PropertyMapper::getValueMap( aValueMap, aNameMap, xTextProperties );
2403 //fill some more shape properties into the ValueMap
2405 aValueMap.insert( { "TextHorizontalAdjust", uno::Any(drawing::TextHorizontalAdjust_CENTER) } ); // drawing::TextHorizontalAdjust
2406 aValueMap.insert( { "TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_CENTER) } ); //drawing::TextVerticalAdjust
2407 aValueMap.insert( { "TextAutoGrowHeight", uno::Any(true) } ); // sal_Bool
2408 aValueMap.insert( { "TextAutoGrowWidth", uno::Any(true) } ); // sal_Bool
2409 aValueMap.insert( { "TextMaximumFrameWidth", uno::Any(rSize.Width) } ); // sal_Int32
2411 //set name/classified ObjectID (CID)
2412 if( !aName.isEmpty() )
2413 aValueMap.emplace( "Name", uno::Any( aName ) ); //CID OUString
2416 //set global title properties
2418 tNameSequence aPropNames;
2419 tAnySequence aPropValues;
2420 PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
2421 PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
2424 bool bStackCharacters(false);
2427 xTextProperties->getPropertyValue( "StackCharacters" ) >>= bStackCharacters;
2429 catch( const uno::Exception& )
2431 TOOLS_WARN_EXCEPTION("chart2", "" );
2434 if(bStackCharacters)
2436 //if the characters should be stacked we use only the first character properties for code simplicity
2437 if( xFormattedString.hasElements() )
2439 OUString aLabel;
2440 for( sal_Int32 nN=0; nN<xFormattedString.getLength();nN++ )
2441 aLabel += xFormattedString[nN]->getString();
2442 aLabel = ShapeFactory::getStackedString( aLabel, bStackCharacters );
2444 xTextCursor->gotoEnd(false);
2445 xText->insertString( xTextCursor, aLabel, false );
2446 xTextCursor->gotoEnd(true);
2447 uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
2448 uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
2450 PropertyMapper::setMappedProperties( xTargetProps, xSourceProps
2451 , PropertyMapper::getPropertyNameMapForCharacterProperties() );
2453 // adapt font size according to page size
2454 awt::Size aOldRefSize;
2455 if( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize )
2457 RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize );
2461 else
2463 sal_Int32 nN = 0;
2464 for( nN=0; nN<xFormattedString.getLength();nN++ )
2466 xTextCursor->gotoEnd(false);
2467 xText->insertString( xTextCursor, xFormattedString[nN]->getString(), false );
2468 xTextCursor->gotoEnd(true);
2470 awt::Size aOldRefSize;
2471 bool bHasRefPageSize =
2472 ( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize );
2474 if( xFormattedString.hasElements() )
2476 uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
2477 uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
2478 PropertyMapper::setMappedProperties( xTargetProps, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() );
2480 // adapt font size according to page size
2481 if( bHasRefPageSize )
2483 RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize );
2488 // #i109336# Improve auto positioning in chart
2489 float fFontHeight = 0.0;
2490 if ( xShapeProp.is() && ( xShapeProp->getPropertyValue( "CharHeight" ) >>= fFontHeight ) )
2492 fFontHeight *= ( 2540.0f / 72.0f ); // pt -> 1/100 mm
2493 sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.18f ) );
2494 sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.30f ) );
2495 xShapeProp->setPropertyValue( "TextLeftDistance", uno::Any( nXDistance ) );
2496 xShapeProp->setPropertyValue( "TextRightDistance", uno::Any( nXDistance ) );
2497 xShapeProp->setPropertyValue( "TextUpperDistance", uno::Any( nYDistance ) );
2498 xShapeProp->setPropertyValue( "TextLowerDistance", uno::Any( nYDistance ) );
2500 sal_Int32 nXPos = rPos.X;
2501 sal_Int32 nYPos = rPos.Y;
2503 //set position matrix
2504 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2505 ::basegfx::B2DHomMatrix aM;
2506 aM.rotate( -basegfx::deg2rad(nRotation) );//#i78696#->#i80521#
2507 aM.translate( nXPos, nYPos );
2508 xShapeProp->setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) );
2510 catch( const uno::Exception& )
2512 TOOLS_WARN_EXCEPTION("chart2", "" );
2514 return xShape;
2517 ShapeFactory* ShapeFactory::getOrCreateShapeFactory(const uno::Reference< lang::XMultiServiceFactory>& xFactory)
2519 static ShapeFactory* pShapeFactory = new ShapeFactory(xFactory);
2520 return pShapeFactory;
2523 uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape(
2524 const uno::Reference< drawing::XDrawPage>& xDrawPage )
2526 uno::Reference< drawing::XShapes > xRet;
2527 uno::Reference< drawing::XShapes > xShapes( xDrawPage, uno::UNO_QUERY );
2528 if( xShapes.is() )
2530 sal_Int32 nCount = xShapes->getCount();
2531 uno::Reference< drawing::XShape > xShape;
2532 for( sal_Int32 nN = nCount; nN--; )
2534 if( xShapes->getByIndex( nN ) >>= xShape )
2536 if( ShapeFactory::getShapeName( xShape ) == "com.sun.star.chart2.shapes" )
2538 xRet.set( xShape, uno::UNO_QUERY );
2539 break;
2544 return xRet;
2547 void ShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape )
2549 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
2550 OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
2551 if( xShapeProp.is())
2555 xShapeProp->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ));
2556 xShapeProp->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE ));
2558 catch( const uno::Exception& )
2560 TOOLS_WARN_EXCEPTION("chart2", "" );
2565 // set a name/CID at a shape (is used for selection handling)
2567 void ShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
2568 , const OUString& rName )
2570 if(!xShape.is())
2571 return;
2572 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2573 OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
2574 if( xProp.is())
2578 xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME
2579 , uno::Any( rName ) );
2581 catch( const uno::Exception& )
2583 TOOLS_WARN_EXCEPTION("chart2", "" );
2588 OUString ShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
2590 OUString aRet;
2592 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2593 OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
2594 if( xProp.is())
2598 xProp->getPropertyValue( UNO_NAME_MISC_OBJ_NAME ) >>= aRet;
2600 catch( const uno::Exception& )
2602 TOOLS_WARN_EXCEPTION("chart2", "" );
2606 return aRet;
2609 uno::Any ShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
2611 ::basegfx::B2DHomMatrix aM;
2612 //As autogrow is active the rectangle is automatically expanded to that side
2613 //to which the text is not adjusted.
2614 // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
2615 aM.rotate( fRotationAnglePi );
2616 aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
2617 uno::Any aATransformation( B2DHomMatrixToHomogenMatrix3(aM) );
2618 return aATransformation;
2621 OUString ShapeFactory::getStackedString( const OUString& rString, bool bStacked )
2623 sal_Int32 nLen = rString.getLength();
2624 if(!bStacked || !nLen)
2625 return rString;
2627 OUStringBuffer aStackStr;
2629 //add a newline after each letter
2630 //as we do not no letters here add a newline after each char
2631 for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
2633 if( nPosSrc )
2634 aStackStr.append( '\r' );
2635 aStackStr.append(rString[nPosSrc]);
2637 return aStackStr.makeStringAndClear();
2640 bool ShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly)
2642 // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
2643 for( sal_Int32 nIdx = 0, nCount = rPoly.SequenceX.getLength(); nIdx < nCount; ++nIdx )
2644 if( rPoly.SequenceX[ nIdx ].getLength() > 1 )
2645 return true;
2646 return false;
2649 bool ShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly)
2651 // true, if empty polypolygon or one polygon with one point
2652 return !rPoly.SequenceX.hasElements() ||
2653 ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
2656 void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
2658 OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
2659 //add a last point == first point
2660 if(isPolygonEmptyOrSinglePoint(rPoly))
2661 return;
2662 drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
2663 AddPointToPoly( rPoly, aFirst );
2666 awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
2667 const awt::Size& rTargetSize
2668 , const awt::Size& rSourceSizeWithCorrectAspectRatio )
2670 awt::Size aNewSize;
2672 double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
2673 double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
2674 double fFactor = std::min(fFactorWidth,fFactorHeight);
2675 aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
2676 aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);
2678 return aNewSize;
2681 awt::Point ShapeFactory::calculateTopLeftPositionToCenterObject(
2682 const awt::Point& rTargetAreaPosition
2683 , const awt::Size& rTargetAreaSize
2684 , const awt::Size& rObjectSize )
2686 awt::Point aNewPosition(rTargetAreaPosition);
2687 aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
2688 aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
2689 return aNewPosition;
2692 ::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape(
2693 const uno::Reference< drawing::XShape >& xShape )
2695 ::basegfx::B2IRectangle aRet;
2697 if( xShape.is() )
2699 awt::Point aPos = xShape->getPosition();
2700 awt::Size aSize = xShape->getSize();
2701 aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
2703 return aRet;
2707 awt::Size ShapeFactory::getSizeAfterRotation(
2708 const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
2710 awt::Size aRet(0,0);
2711 if(xShape.is())
2713 const awt::Size aSize( xShape->getSize() );
2715 if( fRotationAngleDegree == 0.0 )
2716 aRet = aSize;
2717 else
2719 fRotationAngleDegree = NormAngle360(fRotationAngleDegree);
2720 if(fRotationAngleDegree>270.0)
2721 fRotationAngleDegree=360.0-fRotationAngleDegree;
2722 else if(fRotationAngleDegree>180.0)
2723 fRotationAngleDegree=fRotationAngleDegree-180.0;
2724 else if(fRotationAngleDegree>90.0)
2725 fRotationAngleDegree=180.0-fRotationAngleDegree;
2727 const double fAnglePi = basegfx::deg2rad(fRotationAngleDegree);
2729 aRet.Height = static_cast<sal_Int32>(
2730 aSize.Width*rtl::math::sin( fAnglePi )
2731 + aSize.Height*rtl::math::cos( fAnglePi ));
2732 aRet.Width = static_cast<sal_Int32>(
2733 aSize.Width*rtl::math::cos( fAnglePi )
2734 + aSize.Height*rtl::math::sin( fAnglePi ));
2737 return aRet;
2740 void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
2742 if( xShapes.is() )
2744 sal_Int32 nSubCount = xShapes->getCount();
2745 uno::Reference< drawing::XShape > xShape;
2746 for( sal_Int32 nS = nSubCount; nS--; )
2748 if( xShapes->getByIndex( nS ) >>= xShape )
2749 xShapes->remove( xShape );
2754 } //namespace chart
2756 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */