1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "ShapeFactory.hxx"
27 #include "ViewDefines.hxx"
28 #include "Stripe.hxx"
29 #include "CommonConverters.hxx"
30 #include "macros.hxx"
31 #include "PropertyMapper.hxx"
32 #include <comphelper/InlineContainer.hxx>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/drawing/CircleKind.hpp>
35 #include <com/sun/star/drawing/DoubleSequence.hpp>
36 #include <com/sun/star/drawing/FlagSequence.hpp>
37 #include <com/sun/star/drawing/FillStyle.hpp>
38 #include <com/sun/star/drawing/LineStyle.hpp>
39 #include <com/sun/star/drawing/NormalsKind.hpp>
40 #include <com/sun/star/drawing/PointSequence.hpp>
41 #include <com/sun/star/drawing/PolygonKind.hpp>
42 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
43 #include <com/sun/star/drawing/ProjectionMode.hpp>
44 #include <com/sun/star/drawing/ShadeMode.hpp>
45 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
46 #include <com/sun/star/drawing/TextureProjectionMode.hpp>
47 #include <com/sun/star/text/XText.hpp>
48 #include <com/sun/star/uno/Any.hxx>
49
50
51 #include <editeng/unoprnms.hxx>
52 #include <tools/color.hxx>
53 #include <tools/debug.hxx>
54 #include <rtl/math.hxx>
55 #include <svx/svdocirc.hxx>
56 #include <svx/svdopath.hxx>
57
58 #ifndef _BGFX_VECTOR_B2DPOINT_HXX
59 #include <basegfx/point/b2dpoint.hxx>
60 #endif
61 #include <basegfx/matrix/b3dhommatrix.hxx>
62
63 #include <algorithm>
64
65 using namespace ::com::sun::star;
66 using ::com::sun::star::uno::Reference;
67
68 //.............................................................................
69 namespace chart
70 {
71 //.............................................................................
72
73 //-----------------------------------------------------------------------------
74 //-----------------------------------------------------------------------------
75 // set a name/CID at a shape (is used for selection handling)
76 //-----------------------------------------------------------------------------
77 //-----------------------------------------------------------------------------
78
setShapeName(const uno::Reference<drawing::XShape> & xShape,const rtl::OUString & rName)79 void ShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
80 , const rtl::OUString& rName )
81 {
82 if(!xShape.is())
83 return;
84 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
85 DBG_ASSERT(xProp.is(), "shape offers no XPropertySet");
86 if( xProp.is())
87 {
88 try
89 {
90 xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME )
91 , uno::makeAny( rName ) );
92 }
93 catch( uno::Exception& e )
94 {
95 ASSERT_EXCEPTION( e );
96 }
97 }
98 }
99
100 //-----------------------------------------------------------------------------
101
getShapeName(const uno::Reference<drawing::XShape> & xShape)102 rtl::OUString ShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
103 {
104 rtl::OUString aRet;
105
106 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
107 DBG_ASSERT(xProp.is(), "shape offers no XPropertySet");
108 if( xProp.is())
109 {
110 try
111 {
112 xProp->getPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ) ) >>= aRet;
113 }
114 catch( uno::Exception& e )
115 {
116 ASSERT_EXCEPTION( e );
117 }
118 }
119
120 return aRet;
121 }
122
123 //-----------------------------------------------------------------------------
124
getChartRootShape(const uno::Reference<drawing::XDrawPage> & xDrawPage)125 uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape(
126 const uno::Reference< drawing::XDrawPage>& xDrawPage )
127 {
128 uno::Reference< drawing::XShapes > xRet;
129 uno::Reference< drawing::XShapes > xShapes( xDrawPage, uno::UNO_QUERY );
130 if( xShapes.is() )
131 {
132 sal_Int32 nCount = xShapes->getCount();
133 uno::Reference< drawing::XShape > xShape;
134 for( sal_Int32 nN = nCount; nN--; )
135 {
136 if( xShapes->getByIndex( nN ) >>= xShape )
137 {
138 if( ShapeFactory::getShapeName( xShape ).equals(C2U("com.sun.star.chart2.shapes")) )
139 {
140 xRet = uno::Reference< drawing::XShapes >( xShape, uno::UNO_QUERY );
141 break;
142 }
143 }
144 }
145 }
146 return xRet;
147 }
148
149 //-----------------------------------------------------------------------------
150
getOrCreateChartRootShape(const uno::Reference<drawing::XDrawPage> & xDrawPage)151 uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape(
152 const uno::Reference< drawing::XDrawPage>& xDrawPage )
153 {
154 uno::Reference< drawing::XShapes > xRet( ShapeFactory::getChartRootShape( xDrawPage ) );
155 if( !xRet.is() )
156 {
157 //create the root shape
158 xRet = this->createGroup2D(
159 uno::Reference<drawing::XShapes>( xDrawPage, uno::UNO_QUERY )
160 , C2U("com.sun.star.chart2.shapes") );
161 }
162 return xRet;
163 }
164
165 //-----------------------------------------------------------------------------
166 //-----------------------------------------------------------------------------
167 // diverse PolyPolygon create methods
168 //-----------------------------------------------------------------------------
169 //-----------------------------------------------------------------------------
170
createPolyPolygon_Cube(const drawing::Direction3D & rSize,double fRoundedEdge,bool bRounded=true)171 uno::Any createPolyPolygon_Cube(
172 const drawing::Direction3D& rSize, double fRoundedEdge, bool bRounded = true )
173 {
174 DBG_ASSERT(fRoundedEdge>=0, "fRoundedEdge needs to be >= 0");
175
176 // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
177 if( fRoundedEdge == 0.0 && bRounded)
178 fRoundedEdge = 0.4 / 200.0;
179 else if(!bRounded)
180 fRoundedEdge = 0.0;
181
182 //fWidthH stands for Half Width
183 const double fWidthH = rSize.DirectionX >=0.0? rSize.DirectionX/2.0 : -rSize.DirectionX/2.0;
184 const double fHeight = rSize.DirectionY;
185 // const double fDepth = rSize.DirectionZ >=0.0? rSize.DirectionZ : -rSize.DirectionZ ;
186
187 const double fHeightSign = fHeight >= 0.0 ? 1.0 : -1.0;
188
189 const double fOffset = (fWidthH * fRoundedEdge) * 1.05; // increase by 5% for safety
190 const bool bRoundEdges = fRoundedEdge && fOffset < fWidthH && 2.0 * fOffset < fHeightSign*fHeight;
191 const sal_Int32 nPointCount = bRoundEdges ? 13 : 5;
192
193 //--------------------------------------
194 drawing::PolyPolygonShape3D aPP;
195
196 aPP.SequenceX.realloc(1);
197 aPP.SequenceY.realloc(1);
198 aPP.SequenceZ.realloc(1);
199
200 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
201 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
202 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
203
204 pOuterSequenceX->realloc(nPointCount);
205 pOuterSequenceY->realloc(nPointCount);
206 pOuterSequenceZ->realloc(nPointCount);
207
208 double* pInnerSequenceX = pOuterSequenceX->getArray();
209 double* pInnerSequenceY = pOuterSequenceY->getArray();
210 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
211
212 for(sal_Int32 nN = nPointCount; nN--;)
213 *pInnerSequenceZ++ = 0.0;
214 //*pInnerSequenceZ++ = -fDepth/2.0;
215
216 if(nPointCount == 5)
217 {
218 *pInnerSequenceY++ = 0.0;
219 *pInnerSequenceY++ = 0.0;
220 *pInnerSequenceY++ = fHeight;
221 *pInnerSequenceY++ = fHeight;
222 *pInnerSequenceY++ = 0.0;
223
224 *pInnerSequenceX++ = -fWidthH;
225 *pInnerSequenceX++ = fWidthH;
226 *pInnerSequenceX++ = fWidthH;
227 *pInnerSequenceX++ = -fWidthH;
228 *pInnerSequenceX++ = -fWidthH;
229 }
230 else
231 {
232 *pInnerSequenceY++ = 0.0;
233 *pInnerSequenceY++ = 0.0;
234 *pInnerSequenceY++ = 0.0;
235 *pInnerSequenceY++ = fHeightSign*fOffset;
236 *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
237 *pInnerSequenceY++ = fHeight;
238 *pInnerSequenceY++ = fHeight;
239 *pInnerSequenceY++ = fHeight;
240 *pInnerSequenceY++ = fHeight;
241 *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
242 *pInnerSequenceY++ = fHeightSign*fOffset;
243 *pInnerSequenceY++ = 0.0;
244 *pInnerSequenceY++ = 0.0;
245
246 *pInnerSequenceX++ = -fWidthH + fOffset;
247 *pInnerSequenceX++ = fWidthH - fOffset;
248 *pInnerSequenceX++ = fWidthH;
249 *pInnerSequenceX++ = fWidthH;
250 *pInnerSequenceX++ = fWidthH;
251 *pInnerSequenceX++ = fWidthH;
252 *pInnerSequenceX++ = fWidthH - fOffset;
253 *pInnerSequenceX++ = -fWidthH + fOffset;
254 *pInnerSequenceX++ = -fWidthH;
255 *pInnerSequenceX++ = -fWidthH;
256 *pInnerSequenceX++ = -fWidthH;
257 *pInnerSequenceX++ = -fWidthH;
258 *pInnerSequenceX++ = -fWidthH + fOffset;
259 }
260 return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
261 }
262
createPolyPolygon_Cylinder(double fHeight,double fRadius,sal_Int32 & nVerticalSegmentCount)263 uno::Any createPolyPolygon_Cylinder(
264 double fHeight
265 , double fRadius
266 , sal_Int32& nVerticalSegmentCount )
267 {
268 //fHeight may be negative
269 DBG_ASSERT(fRadius>0, "The radius of a cylinder needs to be > 0");
270
271 //--------------------------------------
272 drawing::PolyPolygonShape3D aPP;
273
274 nVerticalSegmentCount=1;
275
276 aPP.SequenceX.realloc(3);
277 aPP.SequenceY.realloc(3);
278 aPP.SequenceZ.realloc(3);
279
280 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
281 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
282 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
283
284 pOuterSequenceX->realloc(2);
285 pOuterSequenceY->realloc(2);
286 pOuterSequenceZ->realloc(2);
287
288 double* pInnerSequenceX = pOuterSequenceX->getArray();
289 double* pInnerSequenceY = pOuterSequenceY->getArray();
290 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
291
292 double fY1 = 0.0;
293 double fY2 = fHeight;
294
295 if( fHeight<0.0 )
296 ::std::swap(fY1,fY2);
297
298 //----------------------------
299 for(sal_Int32 nN = 2; nN--;)
300 *pInnerSequenceZ++ = 0.0;
301
302 *pInnerSequenceX++ = 0.0;
303 *pInnerSequenceY++ = fY1;
304
305 *pInnerSequenceX++ = fRadius;
306 *pInnerSequenceY++ = fY1;
307 //----------------------------
308
309 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
310 pOuterSequenceX->realloc(2);
311 pOuterSequenceY->realloc(2);
312 pOuterSequenceZ->realloc(2);
313
314 pInnerSequenceX = pOuterSequenceX->getArray();
315 pInnerSequenceY = pOuterSequenceY->getArray();
316 pInnerSequenceZ = pOuterSequenceZ->getArray();
317
318 //----------------------------
319 for(sal_Int32 nN = 2; nN--;)
320 *pInnerSequenceZ++ = 0.0;
321
322 *pInnerSequenceX++ = fRadius;
323 *pInnerSequenceY++ = fY1;
324
325 *pInnerSequenceX++ = fRadius;
326 *pInnerSequenceY++ = fY2;
327 //----------------------------
328
329 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
330 pOuterSequenceX->realloc(2);
331 pOuterSequenceY->realloc(2);
332 pOuterSequenceZ->realloc(2);
333
334 pInnerSequenceX = pOuterSequenceX->getArray();
335 pInnerSequenceY = pOuterSequenceY->getArray();
336 pInnerSequenceZ = pOuterSequenceZ->getArray();
337
338 //----------------------------
339 for(sal_Int32 nN = 2; nN--;)
340 *pInnerSequenceZ++ = 0.0;
341
342 *pInnerSequenceX++ = fRadius;
343 *pInnerSequenceY++ = fY2;
344
345 *pInnerSequenceX++ = 0.0;
346 *pInnerSequenceY++ = fY2;
347 //----------------------------
348
349 return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
350 }
351
createPolyPolygon_Cone(double fHeight,double fRadius,double fTopHeight,sal_Int32 & nVerticalSegmentCount)352 uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double fTopHeight
353 , sal_Int32& nVerticalSegmentCount )
354 {
355 DBG_ASSERT(fRadius>0, "The radius of a cone needs to be > 0");
356
357 //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
358 //fTopHeight indicates the high of the cutted top only (not the full height)
359 bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight );
360
361 double r1= 0.0, r2 = fRadius;
362 if(bTopless)
363 // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
364 r1 = fRadius * (fTopHeight)/(fabs(fHeight)+fTopHeight);
365
366 nVerticalSegmentCount=1;
367 drawing::PolyPolygonShape3D aPP;
368
369 aPP.SequenceX.realloc(2);
370 aPP.SequenceY.realloc(2);
371 aPP.SequenceZ.realloc(2);
372
373 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
374 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
375 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
376
377 pOuterSequenceX->realloc(2);
378 pOuterSequenceY->realloc(2);
379 pOuterSequenceZ->realloc(2);
380
381 double* pInnerSequenceX = pOuterSequenceX->getArray();
382 double* pInnerSequenceY = pOuterSequenceY->getArray();
383 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
384
385 double fX1 = 0.0;
386 double fX2 = r2;
387 double fX3 = r1;
388
389 double fY1 = 0.0;
390 double fY2 = 0.0;
391 double fY3 = fHeight;
392
393 if( fHeight<0.0 )
394 {
395 ::std::swap(fX1,fX3);
396 ::std::swap(fY1,fY3);
397 }
398
399 //----------------------------
400 for(sal_Int32 nN = 2; nN--;)
401 *pInnerSequenceZ++ = 0.0;
402
403 *pInnerSequenceY++ = fY1;
404 *pInnerSequenceX++ = fX1;
405
406 *pInnerSequenceY++ = fY2;
407 *pInnerSequenceX++ = fX2;
408 //----------------------------
409
410 pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
411 pOuterSequenceX->realloc(2);
412 pOuterSequenceY->realloc(2);
413 pOuterSequenceZ->realloc(2);
414
415 pInnerSequenceX = pOuterSequenceX->getArray();
416 pInnerSequenceY = pOuterSequenceY->getArray();
417 pInnerSequenceZ = pOuterSequenceZ->getArray();
418
419 //----------------------------
420 for(sal_Int32 nN = 2; nN--;)
421 *pInnerSequenceZ++ = 0.0;
422
423 *pInnerSequenceY++ = fY2;
424 *pInnerSequenceX++ = fX2;
425
426 *pInnerSequenceY++ = fY3;
427 *pInnerSequenceX++ = fX3;
428 //----------------------------
429
430 return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
431 }
432
433 //-----------------------------------------------------------------------------
434 //-----------------------------------------------------------------------------
435 // methods for 3D shape creation
436 //-----------------------------------------------------------------------------
437 //-----------------------------------------------------------------------------
438
439 uno::Reference<drawing::XShape>
createCube(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,sal_Int32 nRotateZAngleHundredthDegree,const uno::Reference<beans::XPropertySet> & xSourceProp,const tPropertyNameMap & rPropertyNameMap,bool bRounded)440 ShapeFactory::createCube(
441 const uno::Reference<drawing::XShapes>& xTarget
442 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
443 , sal_Int32 nRotateZAngleHundredthDegree
444 , const uno::Reference< beans::XPropertySet >& xSourceProp
445 , const tPropertyNameMap& rPropertyNameMap
446 , bool bRounded )
447 {
448 if( !xTarget.is() )
449 return 0;
450 if( bRounded )
451 {
452 try
453 {
454 if( xSourceProp.is() )
455 {
456 drawing::LineStyle aLineStyle;
457 xSourceProp->getPropertyValue( C2U( "BorderStyle" ) ) >>= aLineStyle;
458 if( aLineStyle == drawing::LineStyle_SOLID )
459 bRounded = false;
460 }
461 }
462 catch( uno::Exception& e )
463 {
464 ASSERT_EXCEPTION( e );
465 }
466 }
467 uno::Reference<drawing::XShape> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded );
468 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
469 if( xSourceProp.is())
470 PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
471 return xShape;
472 }
473
474 uno::Reference<drawing::XShape>
impl_createCube(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,sal_Int32 nRotateZAngleHundredthDegree,bool bRounded)475 ShapeFactory::impl_createCube(
476 const uno::Reference<drawing::XShapes>& xTarget
477 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
478 , sal_Int32 nRotateZAngleHundredthDegree
479 , bool bRounded )
480 {
481 if( !xTarget.is() )
482 return 0;
483
484 //create shape
485 uno::Reference< drawing::XShape > xShape(
486 m_xShapeFactory->createInstance( C2U(
487 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
488 xTarget->add(xShape);
489
490 //set properties
491 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
492 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
493 if( xProp.is())
494 {
495 try
496 {
497 //depth
498 double fDepth = rSize.DirectionZ;
499 if(fDepth<0)
500 fDepth*=-1.0;
501 xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
502 , uno::makeAny((sal_Int32)fDepth) );
503
504 //PercentDiagonal
505 sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
506 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
507 , uno::makeAny( nPercentDiagonal ) );
508
509 //Polygon
510 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
511 , createPolyPolygon_Cube( rSize, double(nPercentDiagonal)/200.0,bRounded) );
512
513 //Matrix for position
514 {
515 ::basegfx::B3DHomMatrix aM;
516 if(nRotateZAngleHundredthDegree!=0)
517 aM.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
518 aM.translate(rPosition.PositionX
519 , rPosition.PositionY
520 , rPosition.PositionZ - (fDepth/2.0));
521 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
522 xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
523 , uno::makeAny(aHM) );
524 }
525 }
526 catch( uno::Exception& e )
527 {
528 ASSERT_EXCEPTION( e );
529 }
530 }
531 return xShape;
532 }
533
534 uno::Reference<drawing::XShape>
createCylinder(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,sal_Int32 nRotateZAngleHundredthDegree)535 ShapeFactory::createCylinder(
536 const uno::Reference<drawing::XShapes>& xTarget
537 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
538 , sal_Int32 nRotateZAngleHundredthDegree )
539 {
540 return impl_createConeOrCylinder(
541 xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true );
542 }
543
544 uno::Reference<drawing::XShape>
createPyramid(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,double fTopHeight,bool bRotateZ,const uno::Reference<beans::XPropertySet> & xSourceProp,const tPropertyNameMap & rPropertyNameMap)545 ShapeFactory::createPyramid(
546 const uno::Reference<drawing::XShapes>& xTarget
547 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
548 , double fTopHeight, bool bRotateZ
549 , const uno::Reference< beans::XPropertySet >& xSourceProp
550 , const tPropertyNameMap& rPropertyNameMap )
551 {
552 if( !xTarget.is() )
553 return 0;
554
555 Reference< drawing::XShapes > xGroup( ShapeFactory::createGroup3D( xTarget, rtl::OUString() ) );
556
557 sal_Bool bDoubleSided = false;
558 short nRotatedTexture = 0;
559
560 const double fWidth = rSize.DirectionX;
561 const double fDepth = rSize.DirectionZ;
562 const double fHeight = rSize.DirectionY;
563
564 drawing::Position3D aBottomP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth/2.0 );
565 if(bRotateZ)
566 aBottomP1.PositionY -= fWidth/2.0;
567 else
568 aBottomP1.PositionX -= fWidth/2.0;
569 drawing::Position3D aBottomP2( aBottomP1 );
570 if(bRotateZ)
571 aBottomP2.PositionY += fWidth;
572 else
573 aBottomP2.PositionX += fWidth;
574 drawing::Position3D aBottomP3( aBottomP2 );
575 drawing::Position3D aBottomP4( aBottomP1 );
576 aBottomP3.PositionZ += fDepth;
577 aBottomP4.PositionZ += fDepth;
578
579 const double fTopFactor = (fTopHeight)/(fabs(fHeight)+fTopHeight);
580 drawing::Position3D aTopP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth*fTopFactor/2.0 );
581 if(bRotateZ)
582 {
583 aTopP1.PositionY -= fWidth*fTopFactor/2.0;
584 aTopP1.PositionX += fHeight;
585 }
586 else
587 {
588 aTopP1.PositionX -= fWidth*fTopFactor/2.0;
589 aTopP1.PositionY += fHeight;
590 }
591 drawing::Position3D aTopP2( aTopP1 );
592 if(bRotateZ)
593 aTopP2.PositionY += fWidth*fTopFactor;
594 else
595 aTopP2.PositionX += fWidth*fTopFactor;
596 drawing::Position3D aTopP3( aTopP2 );
597 drawing::Position3D aTopP4( aTopP1 );
598 aTopP3.PositionZ += fDepth*fTopFactor;
599 aTopP4.PositionZ += fDepth*fTopFactor;
600
601 Stripe aStripeBottom( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
602
603 drawing::Position3D aNormalsBottomP1( aBottomP1 );
604 drawing::Position3D aNormalsBottomP2( aBottomP2 );
605 drawing::Position3D aNormalsBottomP3( aBottomP3 );
606 drawing::Position3D aNormalsBottomP4( aBottomP4 );
607 drawing::Position3D aNormalsTopP1( aBottomP1 );
608 drawing::Position3D aNormalsTopP2( aBottomP2 );
609 drawing::Position3D aNormalsTopP3( aBottomP3 );
610 drawing::Position3D aNormalsTopP4( aBottomP4 );
611 if( bRotateZ )
612 {
613 aNormalsTopP1.PositionX += fHeight;
614 aNormalsTopP2.PositionX += fHeight;
615 aNormalsTopP3.PositionX += fHeight;
616 aNormalsTopP4.PositionX += fHeight;
617 }
618 else
619 {
620 aNormalsTopP1.PositionY += fHeight;
621 aNormalsTopP2.PositionY += fHeight;
622 aNormalsTopP3.PositionY += fHeight;
623 aNormalsTopP4.PositionY += fHeight;
624 }
625
626 bool bInvertPolygon = false;
627 bool bInvertNormals = false;
628
629 if(bRotateZ)
630 {
631 //bars
632 if(fHeight>=0.0)
633 {
634 nRotatedTexture = 2;
635 bInvertNormals = true;
636 aStripeBottom = Stripe( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
637 }
638 else
639 {
640 bInvertPolygon = true;
641 nRotatedTexture = 1;
642 aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
643 }
644 }
645 else
646 {
647 //columns
648 if(fHeight>=0.0)
649 {
650 bInvertPolygon = true;
651 nRotatedTexture = 2;
652 aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
653 }
654 else
655 {
656 nRotatedTexture = 3;
657 bInvertNormals = true;
658 aStripeBottom = Stripe( aBottomP4, aBottomP3, aBottomP2, aBottomP1 );
659 }
660 }
661 aStripeBottom.InvertNormal(true);
662
663 Stripe aStripe1( aTopP2, aTopP1, aBottomP1, aBottomP2 );
664 Stripe aStripe2( aTopP3, aTopP2, aBottomP2, aBottomP3 );
665 Stripe aStripe3( aTopP4, aTopP3, aBottomP3, aBottomP4 );
666 Stripe aStripe4( aTopP1, aTopP4, aBottomP4, aBottomP1 );
667
668 if( bInvertPolygon )
669 {
670 aStripe1 = Stripe( aBottomP1, aTopP1, aTopP2, aBottomP2 );
671 aStripe2 = Stripe( aBottomP2, aTopP2, aTopP3, aBottomP3 );
672 aStripe3 = Stripe( aBottomP3, aTopP3, aTopP4, aBottomP4 );
673 aStripe4 = Stripe( aBottomP4, aTopP4, aTopP1, aBottomP1 );
674 }
675
676 Stripe aNormalsStripe1( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP2, aNormalsTopP2 );
677 Stripe aNormalsStripe2( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP3, aNormalsTopP3 );
678 Stripe aNormalsStripe3( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP4, aNormalsTopP4 );
679 Stripe aNormalsStripe4( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP1, aNormalsTopP1 );
680
681 if( bInvertNormals )
682 {
683 aNormalsStripe1 = Stripe( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP1, aNormalsTopP1 );
684 aNormalsStripe2 = Stripe( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP2, aNormalsTopP2 );
685 aNormalsStripe3 = Stripe( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP3, aNormalsTopP3 );
686 aNormalsStripe4 = Stripe( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP4, aNormalsTopP4 );
687 }
688
689 aStripe1.SetManualNormal( aNormalsStripe1.getNormal() );
690 aStripe2.SetManualNormal( aNormalsStripe2.getNormal() );
691 aStripe3.SetManualNormal( aNormalsStripe3.getNormal() );
692 aStripe4.SetManualNormal( aNormalsStripe4.getNormal() );
693
694 const bool bFlatNormals = false;
695 ShapeFactory::createStripe( xGroup, aStripe1, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
696 ShapeFactory::createStripe( xGroup, aStripe2, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
697 ShapeFactory::createStripe( xGroup, aStripe3, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
698 ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
699 ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
700
701 return Reference< drawing::XShape >( xGroup, uno::UNO_QUERY );
702 }
703
704 uno::Reference<drawing::XShape>
createCone(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,double fTopHeight,sal_Int32 nRotateZAngleHundredthDegree)705 ShapeFactory::createCone(
706 const uno::Reference<drawing::XShapes>& xTarget
707 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
708 , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree )
709 {
710 return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree );
711 }
712
713 uno::Reference<drawing::XShape>
impl_createConeOrCylinder(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,double fTopHeight,sal_Int32 nRotateZAngleHundredthDegree,bool bCylinder)714 ShapeFactory::impl_createConeOrCylinder(
715 const uno::Reference<drawing::XShapes>& xTarget
716 , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
717 , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
718 , bool bCylinder )
719 {
720 if( !xTarget.is() )
721 return 0;
722
723 //create shape
724 uno::Reference< drawing::XShape > xShape(
725 m_xShapeFactory->createInstance( C2U(
726 "com.sun.star.drawing.Shape3DLatheObject") ), uno::UNO_QUERY );
727 xTarget->add(xShape);
728
729 double fWidth = rSize.DirectionX/2.0; //The depth will be corrrected within Matrix
730 double fRadius = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
731 double fHeight = rSize.DirectionY;
732
733 //set properties
734 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
735 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
736 if( xProp.is())
737 {
738 try
739 {
740 //PercentDiagonal
741 sal_Int16 nPercentDiagonal = 5;
742 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
743 , uno::makeAny( nPercentDiagonal ) );
744
745 //Polygon
746 sal_Int32 nVerticalSegmentCount = 0;
747 uno::Any aPPolygon = bCylinder ? createPolyPolygon_Cylinder(
748 fHeight, fRadius, nVerticalSegmentCount)
749 : createPolyPolygon_Cone(
750 fHeight, fRadius, fTopHeight, nVerticalSegmentCount);
751 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D ), aPPolygon );
752
753 //Matrix for position
754 {
755 ::basegfx::B3DHomMatrix aM;
756 if(nRotateZAngleHundredthDegree!=0)
757 aM.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
758 //stretch the symmetric objects to given depth
759 aM.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX);
760 aM.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ);
761 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
762 xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
763 , uno::makeAny(aHM) );
764 }
765
766 //Segments
767 xProp->setPropertyValue( C2U( UNO_NAME_3D_HORZ_SEGS )
768 , uno::makeAny(CHART_3DOBJECT_SEGMENTCOUNT) );
769 xProp->setPropertyValue( C2U( UNO_NAME_3D_VERT_SEGS )
770 , uno::makeAny((sal_Int32)nVerticalSegmentCount) );//depends on point count of the used polygon
771
772 //Reduced lines
773 xProp->setPropertyValue( C2U( UNO_NAME_3D_REDUCED_LINE_GEOMETRY )
774 , uno::makeAny((sal_Bool)sal_True) );
775 }
776 catch( uno::Exception& e )
777 {
778 ASSERT_EXCEPTION( e );
779 }
780 }
781 return xShape;
782 }
783
784 //------------------------------------------------------------------------------------------------------------
785 //------------------------------------------------------------------------------------------------------------
786 //------------------------------------------------------------------------------------------------------------
787
appendAndCloseBezierCoords(drawing::PolyPolygonBezierCoords & rReturn,const drawing::PolyPolygonBezierCoords & rAdd,sal_Bool bAppendInverse)788 void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, sal_Bool bAppendInverse )
789 {
790 if(!rAdd.Coordinates.getLength())
791 return;
792 sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
793 if(!nAddCount)
794 return;
795
796 sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
797
798 rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1);
799 rReturn.Flags[0].realloc(nOldCount+nAddCount+1);
800
801 for(sal_Int32 nN=0;nN<nAddCount; nN++ )
802 {
803 sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
804 rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd];
805 rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd];
806 }
807
808 //close
809 rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0];
810 rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0];
811 }
812
813 //------------------------------------------------------------------------------------------------------------
814
getCircularArcBezierCoords(double fStartAngleRadian,double fWidthAngleRadian,double fUnitRadius,const::basegfx::B2DHomMatrix & rTransformationFromUnitCircle,const double fAngleSubdivisionRadian)815 drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
816 double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
817 , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
818 , const double fAngleSubdivisionRadian )
819 {
820 //at least one polygon is created using two normal and two control points
821 //if the angle is larger it is separated into multiple sub angles
822
823 drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
824 sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
825 if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
826 nSegmentCount++;
827
828 double fFirstSegmentAngle = fAngleSubdivisionRadian;
829 double fLastSegmentAngle = fAngleSubdivisionRadian;
830 if(nSegmentCount==1)
831 {
832 fFirstSegmentAngle = fWidthAngleRadian;
833 fLastSegmentAngle = 0.0;
834 }
835 else
836 {
837 double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
838 if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) )
839 fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian;
840
841 if(nSegmentCount>1)
842 {
843 fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
844 if( fLastSegmentAngle<0 )
845 nSegmentCount--;
846 if( fLastSegmentAngle>fAngleSubdivisionRadian )
847 {
848 fLastSegmentAngle-=fAngleSubdivisionRadian;
849 nSegmentCount++;
850 }
851 }
852 }
853
854 sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
855
856 aReturn.Coordinates = drawing::PointSequenceSequence(1);
857 aReturn.Flags = drawing::FlagSequenceSequence(1);
858
859 drawing::PointSequence aPoints(nPointCount);
860 drawing::FlagSequence aFlags(nPointCount);
861
862 //
863
864 //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
865 ::basegfx::B2DPoint P0,P1,P2,P3;
866 ::basegfx::B2DPoint POrigin = rTransformationFromUnitCircle * ::basegfx::B2DPoint(0.0, 0.0);
867
868 sal_Int32 nPoint=0;
869 double fCurrentRotateAngle = fStartAngleRadian;
870 for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
871 {
872 double fCurrentSegmentAngle = fAngleSubdivisionRadian;
873 if(nSegment==0)//first segment gets only a smaller peace until the next subdevision
874 fCurrentSegmentAngle = fFirstSegmentAngle;
875 else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
876 fCurrentSegmentAngle = fLastSegmentAngle;
877
878 //first create untransformed points for a unit circle arc:
879 const double fCos = cos(fCurrentSegmentAngle/2.0);
880 const double fSin = sin(fCurrentSegmentAngle/2.0);
881 P0.setX(fCos);
882 P3.setX(fCos);
883 P0.setY(-fSin);
884 P3.setY(-P0.getY());
885
886 P1.setX((4.0-fCos)/3.0);
887 P2.setX(P1.getX());
888 P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
889 P2.setY(-P1.getY());
890 //transform thus startangle equals NULL
891 ::basegfx::B2DHomMatrix aStart;
892 aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
893 fCurrentRotateAngle+=fCurrentSegmentAngle;
894
895 aStart.scale( fUnitRadius, fUnitRadius );
896
897 //apply given transformation to get final points
898 P0 = rTransformationFromUnitCircle*(aStart*P0);
899 P1 = rTransformationFromUnitCircle*(aStart*P1);
900 P2 = rTransformationFromUnitCircle*(aStart*P2);
901 P3 = rTransformationFromUnitCircle*(aStart*P3);
902
903 aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
904 aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
905 aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
906
907 aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
908 aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
909 aFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
910
911 aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
912 aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
913 aFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
914
915 if(nSegment==(nSegmentCount-1))
916 {
917 aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
918 aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
919 aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
920 }
921 }
922
923 aReturn.Coordinates[0] = aPoints;
924 aReturn.Flags[0] = aFlags;
925
926 return aReturn;
927 }
928
929 //------------------------------------------------------------------------------------------------------------
930
getRingBezierCoords(double fUnitCircleInnerRadius,double fUnitCircleOuterRadius,double fStartAngleRadian,double fWidthAngleRadian,::basegfx::B2DHomMatrix aTransformationFromUnitCircle,const double fAngleSubdivisionRadian)931 drawing::PolyPolygonBezierCoords getRingBezierCoords(
932 double fUnitCircleInnerRadius
933 , double fUnitCircleOuterRadius
934 , double fStartAngleRadian, double fWidthAngleRadian
935 , ::basegfx::B2DHomMatrix aTransformationFromUnitCircle
936 , const double fAngleSubdivisionRadian )
937 {
938 drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
939
940 aReturn.Coordinates = drawing::PointSequenceSequence(1);
941 aReturn.Flags = drawing::FlagSequenceSequence(1);
942
943 drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
944 fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
945 aReturn.Coordinates[0] = aOuterArc.Coordinates[0];
946 aReturn.Flags[0] = aOuterArc.Flags[0];
947
948 drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
949 fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
950 appendAndCloseBezierCoords( aReturn, aInnerArc, sal_True );
951
952 //fill rMarkHandlePoints
953 /*
954 {
955 rMarkHandlePoints.realloc(1);
956 rMarkHandlePoints[0].realloc(6);
957 sal_Int32 nHandleCount=0;
958 sal_Int32 nOuterArcCount = aOuterArc.Coordinates[0].getLength();
959 if(nOuterArcCount>0)
960 rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][0];
961 if(nOuterArcCount>1)
962 rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][nOuterArcCount-1];
963 sal_Int32 nInnerArcCount = aInnerArc.Coordinates[0].getLength();
964 if(nInnerArcCount>0)
965 rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][0];
966 if(nInnerArcCount>1)
967 rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][nInnerArcCount-1];
968 rMarkHandlePoints[0].realloc(nHandleCount);
969 }
970 */
971
972 return aReturn;
973 }
974
975 //------------------------------------------------------------------------------------------------------------
976
977 uno::Reference< drawing::XShape >
createPieSegment2D(const uno::Reference<drawing::XShapes> & xTarget,double fUnitCircleStartAngleDegree,double fUnitCircleWidthAngleDegree,double fUnitCircleInnerRadius,double fUnitCircleOuterRadius,const drawing::Direction3D & rOffset,const drawing::HomogenMatrix & rUnitCircleToScene)978 ShapeFactory::createPieSegment2D(
979 const uno::Reference< drawing::XShapes >& xTarget
980 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
981 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
982 , const drawing::Direction3D& rOffset
983 , const drawing::HomogenMatrix& rUnitCircleToScene )
984 {
985 if( !xTarget.is() )
986 return 0;
987
988 while(fUnitCircleWidthAngleDegree>360)
989 fUnitCircleWidthAngleDegree -= 360.0;
990 while(fUnitCircleWidthAngleDegree<0)
991 fUnitCircleWidthAngleDegree += 360.0;
992
993 //create shape
994 uno::Reference< drawing::XShape > xShape(
995 m_xShapeFactory->createInstance(
996 C2U("com.sun.star.drawing.ClosedBezierShape") ), uno::UNO_QUERY );
997 xTarget->add(xShape); //need to add the shape before setting of properties
998
999 //set properties
1000 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1001 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1002 if( xProp.is())
1003 {
1004 try
1005 {
1006 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
1007 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
1008
1009 const double fAngleSubdivisionRadian = F_PI/10.0;
1010
1011 drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
1012 fUnitCircleInnerRadius, fUnitCircleOuterRadius
1013 , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
1014 , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
1015
1016 xProp->setPropertyValue( C2U( "PolyPolygonBezier" ), uno::makeAny( aCoords ) );
1017
1018 //add shape for markhandles
1019 /*
1020 drawing::PointSequenceSequence aMarkHandlePoints(1); to be filled within getRingBezierCoords
1021 if( xGroup.is() )
1022 {
1023 VLineProperties aHandleLineProperties;
1024 aHandleLineProperties.LineStyle = uno::makeAny( drawing::LineStyle_NONE );
1025 uno::Reference< drawing::XShape > xHandleShape =
1026 this->createLine2D( xGroup, aMarkHandlePoints, &aHandleLineProperties );
1027 this->setShapeName( xHandleShape, C2U("HandlesOnly") );
1028 }
1029 */
1030 }
1031 catch( uno::Exception& e )
1032 {
1033 ASSERT_EXCEPTION( e );
1034 }
1035 }
1036
1037 return xShape;
1038 }
1039
1040 //------------------------------------------------------------------------------------------------------------
1041
1042 uno::Reference< drawing::XShape >
createPieSegment(const uno::Reference<drawing::XShapes> & xTarget,double fUnitCircleStartAngleDegree,double fUnitCircleWidthAngleDegree,double fUnitCircleInnerRadius,double fUnitCircleOuterRadius,const drawing::Direction3D & rOffset,const drawing::HomogenMatrix & rUnitCircleToScene,double fDepth)1043 ShapeFactory::createPieSegment(
1044 const uno::Reference< drawing::XShapes >& xTarget
1045 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
1046 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
1047 , const drawing::Direction3D& rOffset
1048 , const drawing::HomogenMatrix& rUnitCircleToScene
1049 , double fDepth )
1050 {
1051 if( !xTarget.is() )
1052 return 0;
1053
1054 while(fUnitCircleWidthAngleDegree>360)
1055 fUnitCircleWidthAngleDegree -= 360.0;
1056 while(fUnitCircleWidthAngleDegree<0)
1057 fUnitCircleWidthAngleDegree += 360.0;
1058
1059 //create shape
1060 uno::Reference< drawing::XShape > xShape(
1061 m_xShapeFactory->createInstance( C2U(
1062 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
1063 xTarget->add(xShape); //need to add the shape before setting of properties
1064
1065 //set properties
1066 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1067 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1068 if( xProp.is())
1069 {
1070 try
1071 {
1072 ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
1073 aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
1074
1075 const double fAngleSubdivisionRadian = F_PI/32.0;
1076
1077 drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
1078 fUnitCircleInnerRadius, fUnitCircleOuterRadius
1079 , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
1080 , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
1081
1082 //depth
1083 xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
1084 , uno::makeAny((sal_Int32)fDepth) );
1085
1086 //PercentDiagonal
1087 sal_Int16 nPercentDiagonal = 0;
1088 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
1089 , uno::makeAny( nPercentDiagonal ) );
1090
1091 //Polygon
1092 drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
1093 ShapeFactory::closePolygon( aPoly );
1094 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
1095 , uno::makeAny( aPoly ) );
1096
1097 //DoubleSided
1098 xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
1099 , uno::makeAny( (sal_Bool)true) );
1100
1101 //Reduced lines
1102 xProp->setPropertyValue( C2U( UNO_NAME_3D_REDUCED_LINE_GEOMETRY )
1103 , uno::makeAny((sal_Bool)sal_True) );
1104
1105 //TextureProjectionMode
1106 xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_Y )
1107 , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
1108
1109 //TextureProjectionMode
1110 xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_X )
1111 , uno::makeAny( drawing::TextureProjectionMode_PARALLEL ) );
1112 xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_Y )
1113 , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
1114 }
1115 catch( uno::Exception& e )
1116 {
1117 ASSERT_EXCEPTION( e );
1118 }
1119 }
1120 return xShape;
1121 }
1122
1123 //------------------------------------------------------------------------------------------------------------
1124 //------------------------------------------------------------------------------------------------------------
1125 //------------------------------------------------------------------------------------------------------------
1126
1127 uno::Reference< drawing::XShape >
createStripe(const uno::Reference<drawing::XShapes> & xTarget,const Stripe & rStripe,const uno::Reference<beans::XPropertySet> & xSourceProp,const tPropertyNameMap & rPropertyNameMap,sal_Bool bDoubleSided,short nRotatedTexture,bool bFlatNormals)1128 ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& xTarget
1129 , const Stripe& rStripe
1130 , const uno::Reference< beans::XPropertySet >& xSourceProp
1131 , const tPropertyNameMap& rPropertyNameMap
1132 , sal_Bool bDoubleSided
1133 , short nRotatedTexture
1134 , bool bFlatNormals )
1135 {
1136 if( !xTarget.is() )
1137 return 0;
1138
1139 //create shape
1140 uno::Reference< drawing::XShape > xShape(
1141 m_xShapeFactory->createInstance( C2U(
1142 "com.sun.star.drawing.Shape3DPolygonObject" ) ), uno::UNO_QUERY );
1143 xTarget->add(xShape);
1144
1145 //set properties
1146 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1147 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1148 if( xProp.is())
1149 {
1150 try
1151 {
1152 //Polygon
1153 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
1154 , rStripe.getPolyPolygonShape3D() );
1155
1156 //TexturePolygon
1157 xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTUREPOLYGON3D )
1158 , rStripe.getTexturePolygon( nRotatedTexture ) );
1159
1160 //Normals Polygon
1161 xProp->setPropertyValue( C2U( UNO_NAME_3D_NORMALSPOLYGON3D )
1162 , rStripe.getNormalsPolygon() );
1163 //NormalsKind
1164 if(bFlatNormals)
1165 xProp->setPropertyValue( C2U( UNO_NAME_3D_NORMALS_KIND )
1166 , uno::makeAny( drawing::NormalsKind_FLAT ) );
1167
1168 //LineOnly
1169 xProp->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY )
1170 , uno::makeAny( (sal_Bool)false) );
1171
1172 //DoubleSided
1173 xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
1174 , uno::makeAny(bDoubleSided) );
1175
1176 if( xSourceProp.is())
1177 PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
1178 }
1179 catch( uno::Exception& e )
1180 {
1181 ASSERT_EXCEPTION( e );
1182 }
1183 }
1184 return xShape;
1185 }
1186
1187 uno::Reference< drawing::XShape >
createArea3D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::PolyPolygonShape3D & rPolyPolygon,double fDepth)1188 ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget
1189 , const drawing::PolyPolygonShape3D& rPolyPolygon
1190 , double fDepth )
1191 {
1192 if( !xTarget.is() )
1193 return 0;
1194
1195 if( !rPolyPolygon.SequenceX.getLength())
1196 return 0;
1197
1198 //create shape
1199 uno::Reference< drawing::XShape > xShape(
1200 m_xShapeFactory->createInstance( C2U(
1201 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
1202 xTarget->add(xShape);
1203
1204 //set properties
1205 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1206 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1207 if( xProp.is())
1208 {
1209 try
1210 {
1211 //depth
1212 xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
1213 , uno::makeAny((sal_Int32)fDepth) );
1214
1215 //PercentDiagonal
1216 sal_Int16 nPercentDiagonal = 0;
1217 xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
1218 , uno::makeAny( nPercentDiagonal ) );
1219
1220 //Polygon
1221 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
1222 , uno::makeAny( rPolyPolygon ) );
1223
1224 //DoubleSided
1225 xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
1226 , uno::makeAny( (sal_Bool)true) );
1227
1228 //the z component of the polygon is now ignored by the drawing layer,
1229 //so we nned to translate the object via transformation matrix
1230
1231 //Matrix for position
1232 if( rPolyPolygon.SequenceZ.getLength()&& rPolyPolygon.SequenceZ[0].getLength() )
1233 {
1234 ::basegfx::B3DHomMatrix aM;
1235 aM.translate( 0
1236 , 0
1237 , rPolyPolygon.SequenceZ[0][0] );
1238 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
1239 xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
1240 , uno::makeAny(aHM) );
1241 }
1242 }
1243 catch( uno::Exception& e )
1244 {
1245 ASSERT_EXCEPTION( e );
1246 }
1247 }
1248 return xShape;
1249 }
1250
1251 uno::Reference< drawing::XShape >
createArea2D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::PolyPolygonShape3D & rPolyPolygon)1252 ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget
1253 , const drawing::PolyPolygonShape3D& rPolyPolygon )
1254 {
1255 if( !xTarget.is() )
1256 return 0;
1257
1258 //create shape
1259 uno::Reference< drawing::XShape > xShape(
1260 m_xShapeFactory->createInstance( C2U(
1261 "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
1262 xTarget->add(xShape);
1263
1264 //set properties
1265 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1266 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1267 if( xProp.is())
1268 {
1269 try
1270 {
1271 //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
1272 drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) );
1273
1274 //Polygon
1275 xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
1276 , uno::makeAny( aPoints ) );
1277
1278 //ZOrder
1279 //an area should always be behind other shapes
1280 xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_ZORDER )
1281 , uno::makeAny( sal_Int32(0) ) );
1282 }
1283 catch( uno::Exception& e )
1284 {
1285 ASSERT_EXCEPTION( e );
1286 }
1287 }
1288 return xShape;
1289 }
1290
1291 enum SymbolType { SYMBOL_SQUARE=0
1292 , SYMBOL_DIAMOND
1293 , SYMBOL_ARROW_DOWN
1294 , SYMBOL_ARROW_UP
1295 , SYMBOL_ARROW_RIGHT
1296 , SYMBOL_ARROW_LEFT
1297 , SYMBOL_BOWTIE
1298 , SYMBOL_SANDGLASS
1299 , SYMBOL_CIRCLE
1300 , SYMBOL_STAR
1301 , SYMBOL_X
1302 , SYMBOL_PLUS
1303 , SYMBOL_ASTERISK
1304 , SYMBOL_HORIZONTAL_BAR
1305 , SYMBOL_VERTICAL_BAR
1306 , SYMBOL_COUNT
1307 };
1308
getSymbolCount()1309 sal_Int32 ShapeFactory::getSymbolCount()
1310 {
1311 return SYMBOL_COUNT;
1312 }
1313
createPolyPolygon_Symbol(const drawing::Position3D & rPos,const drawing::Direction3D & rSize,sal_Int32 nStandardSymbol)1314 drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Position3D& rPos
1315 , const drawing::Direction3D& rSize
1316 , sal_Int32 nStandardSymbol )
1317 {
1318 if(nStandardSymbol<0)
1319 nStandardSymbol*=-1;
1320 nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
1321 SymbolType eSymbolType=static_cast<SymbolType>(nStandardSymbol);
1322
1323 const double& fX = rPos.PositionX;
1324 const double& fY = rPos.PositionY;
1325
1326 const double fWidthH = rSize.DirectionX/2.0; //fWidthH stands for Half Width
1327 const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
1328
1329 // double fMaxSize = fHeightH > fWidthH ? fHeightH : fWidthH; //assumes non negative
1330 const sal_Int32 nQuarterCount = 35; // points inside a quadrant, used in case circle
1331
1332 sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
1333 switch( eSymbolType )
1334 {
1335 case SYMBOL_SQUARE:
1336 case SYMBOL_DIAMOND:
1337 case SYMBOL_BOWTIE:
1338 case SYMBOL_SANDGLASS:
1339 case SYMBOL_HORIZONTAL_BAR:
1340 case SYMBOL_VERTICAL_BAR:
1341 nPointCount = 5;
1342 break;
1343 case SYMBOL_X:
1344 nPointCount = 13;
1345 break;
1346 case SYMBOL_PLUS:
1347 nPointCount = 13;
1348 break;
1349 case SYMBOL_STAR:
1350 nPointCount = 9;
1351 break;
1352 case SYMBOL_ASTERISK:
1353 nPointCount = 19;
1354 break;
1355 case SYMBOL_CIRCLE:
1356 nPointCount = 5 + 4 * nQuarterCount;
1357 break;
1358 default:
1359 break;
1360 }
1361
1362 //--------------------------------------
1363 drawing::PolyPolygonShape3D aPP;
1364
1365 aPP.SequenceX.realloc(1);
1366 aPP.SequenceY.realloc(1);
1367 aPP.SequenceZ.realloc(1);
1368
1369 drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
1370 drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
1371 drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
1372
1373 pOuterSequenceX->realloc(nPointCount);
1374 pOuterSequenceY->realloc(nPointCount);
1375 pOuterSequenceZ->realloc(nPointCount);
1376
1377 double* pInnerSequenceX = pOuterSequenceX->getArray();
1378 double* pInnerSequenceY = pOuterSequenceY->getArray();
1379 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
1380
1381 for(sal_Int32 nN = nPointCount; nN--;)
1382 *pInnerSequenceZ++ = 0.0;
1383
1384 switch(eSymbolType)
1385 {
1386 case SYMBOL_SQUARE:
1387 {
1388 *pInnerSequenceX++ = fX-fWidthH;
1389 *pInnerSequenceY++ = fY-fHeightH;
1390
1391 *pInnerSequenceX++ = fX-fWidthH;
1392 *pInnerSequenceY++ = fY+fHeightH;
1393
1394 *pInnerSequenceX++ = fX+fWidthH;
1395 *pInnerSequenceY++ = fY+fHeightH;
1396
1397 *pInnerSequenceX++ = fX+fWidthH;
1398 *pInnerSequenceY++ = fY-fHeightH;
1399
1400 *pInnerSequenceX++ = fX-fWidthH;
1401 *pInnerSequenceY++ = fY-fHeightH;
1402 break;
1403 }
1404 case SYMBOL_ARROW_UP:
1405 {
1406 *pInnerSequenceX++ = fX-fWidthH;
1407 *pInnerSequenceY++ = fY+fHeightH;
1408
1409 *pInnerSequenceX++ = fX+fWidthH;
1410 *pInnerSequenceY++ = fY+fHeightH;
1411
1412 *pInnerSequenceX++ = fX;
1413 *pInnerSequenceY++ = fY-fHeightH;
1414
1415 *pInnerSequenceX++ = fX-fWidthH;
1416 *pInnerSequenceY++ = fY+fHeightH;
1417 break;
1418 }
1419 case SYMBOL_ARROW_DOWN:
1420 {
1421 *pInnerSequenceX++ = fX-fWidthH;
1422 *pInnerSequenceY++ = fY-fHeightH;
1423
1424 *pInnerSequenceX++ = fX;
1425 *pInnerSequenceY++ = fY+fHeightH;
1426
1427 *pInnerSequenceX++ = fX+fWidthH;
1428 *pInnerSequenceY++ = fY-fHeightH;
1429
1430 *pInnerSequenceX++ = fX-fWidthH;
1431 *pInnerSequenceY++ = fY-fHeightH;
1432 break;
1433 }
1434 case SYMBOL_ARROW_RIGHT:
1435 {
1436 *pInnerSequenceX++ = fX-fWidthH;
1437 *pInnerSequenceY++ = fY-fHeightH;
1438
1439 *pInnerSequenceX++ = fX-fWidthH;
1440 *pInnerSequenceY++ = fY+fHeightH;
1441
1442 *pInnerSequenceX++ = fX+fWidthH;
1443 *pInnerSequenceY++ = fY;
1444
1445 *pInnerSequenceX++ = fX-fWidthH;
1446 *pInnerSequenceY++ = fY-fHeightH;
1447 break;
1448 }
1449 case SYMBOL_ARROW_LEFT:
1450 {
1451 *pInnerSequenceX++ = fX-fWidthH;
1452 *pInnerSequenceY++ = fY;
1453
1454 *pInnerSequenceX++ = fX+fWidthH;
1455 *pInnerSequenceY++ = fY+fHeightH;
1456
1457 *pInnerSequenceX++ = fX+fWidthH;
1458 *pInnerSequenceY++ = fY-fHeightH;
1459
1460 *pInnerSequenceX++ = fX-fWidthH;
1461 *pInnerSequenceY++ = fY;
1462 break;
1463 }
1464 case SYMBOL_BOWTIE:
1465 {
1466 *pInnerSequenceX++ = fX-fWidthH;
1467 *pInnerSequenceY++ = fY-fHeightH;
1468
1469 *pInnerSequenceX++ = fX-fWidthH;
1470 *pInnerSequenceY++ = fY+fHeightH;
1471
1472 *pInnerSequenceX++ = fX+fWidthH;
1473 *pInnerSequenceY++ = fY-fHeightH;
1474
1475 *pInnerSequenceX++ = fX+fWidthH;
1476 *pInnerSequenceY++ = fY+fHeightH;
1477
1478 *pInnerSequenceX++ = fX-fWidthH;
1479 *pInnerSequenceY++ = fY-fHeightH;
1480 break;
1481 }
1482 case SYMBOL_SANDGLASS:
1483 {
1484 *pInnerSequenceX++ = fX-fWidthH;
1485 *pInnerSequenceY++ = fY+fHeightH;
1486
1487 *pInnerSequenceX++ = fX+fWidthH;
1488 *pInnerSequenceY++ = fY+fHeightH;
1489
1490 *pInnerSequenceX++ = fX-fWidthH;
1491 *pInnerSequenceY++ = fY-fHeightH;
1492
1493
1494 *pInnerSequenceX++ = fX+fWidthH;
1495 *pInnerSequenceY++ = fY-fHeightH;
1496
1497 *pInnerSequenceX++ = fX-fWidthH;
1498 *pInnerSequenceY++ = fY+fHeightH;
1499 break;
1500 }
1501 case SYMBOL_DIAMOND:
1502 {
1503 *pInnerSequenceX++ = fX-fWidthH;
1504 *pInnerSequenceY++ = fY;
1505
1506 *pInnerSequenceX++ = fX;
1507 *pInnerSequenceY++ = fY+fHeightH;
1508
1509 *pInnerSequenceX++ = fX+fWidthH;
1510 *pInnerSequenceY++ = fY;
1511
1512 *pInnerSequenceX++ = fX;
1513 *pInnerSequenceY++ = fY-fHeightH;
1514
1515 *pInnerSequenceX++ = fX-fWidthH;
1516 *pInnerSequenceY++ = fY;
1517 break;
1518 }
1519 case SYMBOL_HORIZONTAL_BAR:
1520 {
1521 *pInnerSequenceX++ = fX-fWidthH;
1522 *pInnerSequenceY++ = fY-0.2*fHeightH;
1523
1524 *pInnerSequenceX++ = fX+fWidthH;
1525 *pInnerSequenceY++ = fY-0.2*fHeightH;
1526
1527
1528 *pInnerSequenceX++ = fX+fWidthH;
1529 *pInnerSequenceY++ = fY+0.2*fHeightH;
1530
1531 *pInnerSequenceX++ = fX-fWidthH;
1532 *pInnerSequenceY++ = fY+0.2*fHeightH;
1533
1534 *pInnerSequenceX++ = fX-fWidthH;
1535 *pInnerSequenceY++ = fY-0.2*fHeightH;
1536 break;
1537 }
1538 case SYMBOL_VERTICAL_BAR:
1539 {
1540 *pInnerSequenceX++ = fX-0.2*fWidthH;
1541 *pInnerSequenceY++ = fY-fHeightH;
1542
1543 *pInnerSequenceX++ = fX+0.2*fWidthH;
1544 *pInnerSequenceY++ = fY-fHeightH;
1545
1546
1547 *pInnerSequenceX++ = fX+0.2*fWidthH;
1548 *pInnerSequenceY++ = fY+fHeightH;
1549
1550 *pInnerSequenceX++ = fX-0.2*fWidthH;
1551 *pInnerSequenceY++ = fY+fHeightH;
1552
1553 *pInnerSequenceX++ = fX-0.2*fWidthH;
1554 *pInnerSequenceY++ = fY-fHeightH;
1555
1556 break;
1557 }
1558 case SYMBOL_CIRCLE:
1559 {
1560 double fOmega = 1.5707963267948966192 / (nQuarterCount + 1.0);
1561 // one point in the middle of each edge to get full size bounding rectangle
1562 *pInnerSequenceX++ = fX + fWidthH;
1563 *pInnerSequenceY++ = fY;
1564 // 0 to PI/2
1565 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1566 {
1567 *pInnerSequenceX++ = fX + fWidthH * cos( i * fOmega );
1568 *pInnerSequenceY++ = fY - fHeightH * sin( i * fOmega );
1569 }
1570 // PI/2 to PI
1571 *pInnerSequenceX++ = fX;
1572 *pInnerSequenceY++ = fY - fHeightH;
1573 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1574 {
1575 *pInnerSequenceX++ = fX - fWidthH * sin( i * fOmega);
1576 *pInnerSequenceY++ = fY - fHeightH * cos( i * fOmega);
1577 }
1578 // PI to 3/2*PI
1579 *pInnerSequenceX++ = fX - fWidthH;
1580 *pInnerSequenceY++ = fY;
1581 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1582 {
1583 *pInnerSequenceX++ = fX - fWidthH * cos( i * fOmega);
1584 *pInnerSequenceY++ = fY + fHeightH * sin( i * fOmega);
1585 }
1586 // 3/2*PI to 2*PI
1587 *pInnerSequenceX++ = fX;
1588 *pInnerSequenceY++ = fY + fHeightH;
1589 for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1590 {
1591 *pInnerSequenceX++ = fX + fWidthH * sin(i * fOmega);
1592 *pInnerSequenceY++ = fY + fHeightH * cos(i * fOmega);
1593 }
1594 // close polygon
1595 *pInnerSequenceX++ = fX + fWidthH;
1596 *pInnerSequenceY++ = fY;
1597 break;
1598 }
1599 case SYMBOL_STAR:
1600 {
1601 *pInnerSequenceX++ = fX;
1602 *pInnerSequenceY++ = fY-fHeightH;
1603
1604 *pInnerSequenceX++ = fX+0.2*fWidthH;
1605 *pInnerSequenceY++ = fY-0.2*fHeightH;
1606
1607 *pInnerSequenceX++ = fX+fWidthH;
1608 *pInnerSequenceY++ = fY;
1609
1610 *pInnerSequenceX++ = fX+0.2*fWidthH;
1611 *pInnerSequenceY++ = fY+0.2*fHeightH;
1612
1613 *pInnerSequenceX++ = fX;
1614 *pInnerSequenceY++ = fY+fHeightH;
1615
1616 *pInnerSequenceX++ = fX-0.2*fWidthH;
1617 *pInnerSequenceY++ = fY+0.2*fHeightH;
1618
1619 *pInnerSequenceX++ = fX-fWidthH;
1620 *pInnerSequenceY++ = fY;
1621
1622 *pInnerSequenceX++ = fX-0.2*fWidthH;
1623 *pInnerSequenceY++ = fY-0.2*fHeightH;
1624
1625 *pInnerSequenceX++ = fX;
1626 *pInnerSequenceY++ = fY-fHeightH;
1627 break;
1628 }
1629 case SYMBOL_X:
1630 {
1631 const double fScaleX = fWidthH / 128.0;
1632 const double fScaleY = fHeightH / 128.0;
1633 const double fSmall = sqrt(200.0);
1634 const double fLarge = 128.0 - fSmall;
1635
1636 *pInnerSequenceX++ = fX;
1637 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1638
1639 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1640 *pInnerSequenceY++ = fY - fHeightH;
1641
1642 *pInnerSequenceX++ = fX - fWidthH;
1643 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1644
1645 *pInnerSequenceX++ = fX - fScaleX * fSmall;
1646 *pInnerSequenceY++ = fY;
1647
1648 *pInnerSequenceX++ = fX - fWidthH;
1649 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1650
1651 *pInnerSequenceX++ = fX - fScaleX * fLarge;
1652 *pInnerSequenceY++ = fY + fHeightH;
1653
1654 *pInnerSequenceX++ = fX;
1655 *pInnerSequenceY++ = fY + fScaleY * fSmall;
1656
1657 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1658 *pInnerSequenceY++ = fY + fHeightH;
1659
1660 *pInnerSequenceX++ = fX + fWidthH;
1661 *pInnerSequenceY++ = fY + fScaleY * fLarge;
1662
1663 *pInnerSequenceX++ = fX + fScaleX * fSmall;
1664 *pInnerSequenceY++ = fY;
1665
1666 *pInnerSequenceX++ = fX + fWidthH;
1667 *pInnerSequenceY++ = fY - fScaleY * fLarge;
1668
1669 *pInnerSequenceX++ = fX + fScaleX * fLarge;
1670 *pInnerSequenceY++ = fY - fHeightH;
1671
1672 *pInnerSequenceX++ = fX;
1673 *pInnerSequenceY++ = fY - fScaleY * fSmall;
1674 break;
1675
1676 }
1677 case SYMBOL_PLUS:
1678 {
1679 const double fScaleX = fWidthH / 128.0;
1680 const double fScaleY = fHeightH / 128.0;
1681 const double fHalf = 10.0; //half line width on 256 size square
1682 const double fdX = fScaleX * fHalf;
1683 const double fdY = fScaleY * fHalf;
1684
1685 *pInnerSequenceX++ = fX-fdX;
1686 *pInnerSequenceY++ = fY-fHeightH;
1687
1688 *pInnerSequenceX++ = fX-fdX;
1689 *pInnerSequenceY++ = fY-fdY;
1690
1691 *pInnerSequenceX++ = fX-fWidthH;
1692 *pInnerSequenceY++ = fY-fdY;
1693
1694 *pInnerSequenceX++ = fX-fWidthH;
1695 *pInnerSequenceY++ = fY+fdY;
1696
1697 *pInnerSequenceX++ = fX-fdX;
1698 *pInnerSequenceY++ = fY+fdY;
1699
1700 *pInnerSequenceX++ = fX-fdX;
1701 *pInnerSequenceY++ = fY+fHeightH;
1702
1703 *pInnerSequenceX++ = fX+fdX;
1704 *pInnerSequenceY++ = fY+fHeightH;
1705
1706 *pInnerSequenceX++ = fX+fdX;
1707 *pInnerSequenceY++ = fY+fdY;
1708
1709 *pInnerSequenceX++ = fX+fWidthH;
1710 *pInnerSequenceY++ = fY+fdY;
1711
1712 *pInnerSequenceX++ = fX+fWidthH;
1713 *pInnerSequenceY++ = fY-fdY;
1714
1715 *pInnerSequenceX++ = fX+fdX;
1716 *pInnerSequenceY++ = fY-fdY;
1717
1718 *pInnerSequenceX++ = fX+fdY;
1719 *pInnerSequenceY++ = fY-fHeightH;
1720
1721 *pInnerSequenceX++ = fX-fdX;
1722 *pInnerSequenceY++ = fY-fHeightH;
1723 break;
1724
1725 }
1726 case SYMBOL_ASTERISK:
1727 {
1728 const double fHalf = 10.0; // half line width on 256 size square
1729 const double fTwoY = fHalf * sqrt(3.0);
1730 const double fFourY = (128.0 - 2.0 * fHalf ) / sqrt(3.0);
1731 const double fThreeX = 128.0 - fHalf;
1732 const double fThreeY = fHalf * sqrt(3.0) + fFourY;
1733 const double fFiveX = 2.0 * fHalf;
1734
1735 const double fScaleX = fWidthH / 128.0;
1736 const double fScaleY = fHeightH / 128.0;
1737
1738 //1
1739 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1740 *pInnerSequenceY++ = fY-fHeightH;
1741 //2
1742 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1743 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1744 //3
1745 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1746 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1747 //4
1748 *pInnerSequenceX++ = fX-fWidthH;
1749 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1750 //5
1751 *pInnerSequenceX++ = fX-fScaleX * fFiveX;
1752 *pInnerSequenceY++ = fY;
1753 //6 as 4
1754 *pInnerSequenceX++ = fX-fWidthH;
1755 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1756 //7 as 3
1757 *pInnerSequenceX++ = fX-fScaleX * fThreeX;
1758 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1759 //8 as 2
1760 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1761 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1762 //9 as 1
1763 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1764 *pInnerSequenceY++ = fY+fHeightH;
1765 //10 as 1
1766 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1767 *pInnerSequenceY++ = fY+fHeightH;
1768 //11 as 2
1769 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1770 *pInnerSequenceY++ = fY+fScaleY * fTwoY;
1771 //12 as 3
1772 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1773 *pInnerSequenceY++ = fY+fScaleY * fThreeY;
1774 //13 as 4
1775 *pInnerSequenceX++ = fX+fWidthH;
1776 *pInnerSequenceY++ = fY+fScaleY * fFourY;
1777 //14 as 5
1778 *pInnerSequenceX++ = fX+fScaleX * fFiveX;
1779 *pInnerSequenceY++ = fY;
1780 //15 as 4
1781 *pInnerSequenceX++ = fX+fWidthH;
1782 *pInnerSequenceY++ = fY-fScaleY * fFourY;
1783 //16 as 3
1784 *pInnerSequenceX++ = fX+fScaleX * fThreeX;
1785 *pInnerSequenceY++ = fY-fScaleY * fThreeY;
1786 //17 as 2
1787 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1788 *pInnerSequenceY++ = fY-fScaleY * fTwoY;
1789 // 18 as 1
1790 *pInnerSequenceX++ = fX+fScaleX * fHalf;
1791 *pInnerSequenceY++ = fY-fHeightH;
1792 // 19 = 1, closing
1793 *pInnerSequenceX++ = fX-fScaleX * fHalf;
1794 *pInnerSequenceY++ = fY-fHeightH;
1795 break;
1796 }
1797 default: //case SYMBOL_SQUARE:
1798 {
1799 *pInnerSequenceX++ = fX-fWidthH;
1800 *pInnerSequenceY++ = fY-fHeightH;
1801
1802 *pInnerSequenceX++ = fX-fWidthH;
1803 *pInnerSequenceY++ = fY+fHeightH;
1804
1805 *pInnerSequenceX++ = fX+fWidthH;
1806 *pInnerSequenceY++ = fY+fHeightH;
1807
1808 *pInnerSequenceX++ = fX+fWidthH;
1809 *pInnerSequenceY++ = fY-fHeightH;
1810
1811 *pInnerSequenceX++ = fX-fWidthH;
1812 *pInnerSequenceY++ = fY-fHeightH;
1813 break;
1814 }
1815 }
1816 //return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
1817 return aPP;
1818 }
1819
1820 uno::Reference< drawing::XShape >
createSymbol2D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,sal_Int32 nStandardSymbol,sal_Int32 nBorderColor,sal_Int32 nFillColor)1821 ShapeFactory::createSymbol2D(
1822 const uno::Reference< drawing::XShapes >& xTarget
1823 , const drawing::Position3D& rPosition
1824 , const drawing::Direction3D& rSize
1825 , sal_Int32 nStandardSymbol
1826 , sal_Int32 nBorderColor
1827 , sal_Int32 nFillColor )
1828 {
1829 if( !xTarget.is() )
1830 return 0;
1831
1832 //create shape
1833 uno::Reference< drawing::XShape > xShape(
1834 m_xShapeFactory->createInstance( C2U(
1835 "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
1836 xTarget->add(xShape);
1837
1838 //set properties
1839 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1840 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1841 if( xProp.is())
1842 {
1843 try
1844 {
1845 drawing::PointSequenceSequence aPoints( PolyToPointSequence(
1846 createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) ));
1847
1848 //Polygon
1849 xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
1850 , uno::makeAny( aPoints ) );
1851
1852 //LineColor
1853 xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
1854 , uno::makeAny( nBorderColor ) );
1855
1856 //FillColor
1857 xProp->setPropertyValue( C2U( UNO_NAME_FILLCOLOR )
1858 , uno::makeAny( nFillColor ) );
1859 }
1860 catch( uno::Exception& e )
1861 {
1862 ASSERT_EXCEPTION( e );
1863 }
1864 }
1865 return xShape;
1866 }
1867
1868 uno::Reference< drawing::XShape >
createGraphic2D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize,const uno::Reference<graphic::XGraphic> & xGraphic)1869 ShapeFactory::createGraphic2D(
1870 const uno::Reference< drawing::XShapes >& xTarget
1871 , const drawing::Position3D& rPosition
1872 , const drawing::Direction3D& rSize
1873 , const uno::Reference< graphic::XGraphic >& xGraphic )
1874 {
1875 if( !xTarget.is() || !xGraphic.is() )
1876 return 0;
1877
1878 // @todo: change this to a rectangle shape with a fill bitmap for
1879 // performance reasons (ask AW, said CL)
1880
1881 //create shape
1882 uno::Reference< drawing::XShape > xShape(
1883 m_xShapeFactory->createInstance( C2U(
1884 "com.sun.star.drawing.GraphicObjectShape") ), uno::UNO_QUERY );
1885 xTarget->add(xShape);
1886
1887 try
1888 {
1889 // assume position is upper left corner. Transform to center.
1890 drawing::Position3D aCenterPosition(
1891 rPosition.PositionX - (rSize.DirectionX / 2.0),
1892 rPosition.PositionY - (rSize.DirectionY / 2.0),
1893 rPosition.PositionZ );
1894 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1895 xShape->setSize( Direction3DToAWTSize( rSize ));
1896 }
1897 catch( const uno::Exception & e )
1898 {
1899 ASSERT_EXCEPTION( e );
1900 }
1901 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1902 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1903 if( xProp.is())
1904 {
1905 try
1906 {
1907 xProp->setPropertyValue( C2U("Graphic"), uno::makeAny( xGraphic ));
1908 }
1909 catch( uno::Exception& e )
1910 {
1911 ASSERT_EXCEPTION( e );
1912 }
1913 }
1914 return xShape;
1915 }
1916
1917 uno::Reference< drawing::XShapes >
createGroup2D(const uno::Reference<drawing::XShapes> & xTarget,::rtl::OUString aName)1918 ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget
1919 , ::rtl::OUString aName )
1920 {
1921 if( !xTarget.is() )
1922 return 0;
1923 try
1924 {
1925 //create and add to target
1926 uno::Reference< drawing::XShape > xShape(
1927 m_xShapeFactory->createInstance( C2U(
1928 "com.sun.star.drawing.GroupShape" ) ), uno::UNO_QUERY );
1929 xTarget->add(xShape);
1930
1931 //set name
1932 if( !aName.isEmpty() )
1933 setShapeName( xShape , aName );
1934
1935 {//workaround
1936 //need this null size as otherwise empty group shapes where painted with a gray border
1937 xShape->setSize(awt::Size(0,0));
1938 }
1939
1940 //return
1941 uno::Reference< drawing::XShapes > xShapes =
1942 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1943 return xShapes;
1944 }
1945 catch( uno::Exception& e )
1946 {
1947 ASSERT_EXCEPTION( e );
1948 }
1949 return 0;
1950 }
1951
1952 uno::Reference< drawing::XShapes >
createGroup3D(const uno::Reference<drawing::XShapes> & xTarget,::rtl::OUString aName)1953 ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget
1954 , ::rtl::OUString aName )
1955 {
1956 if( !xTarget.is() )
1957 return 0;
1958 try
1959 {
1960 //create shape
1961 uno::Reference< drawing::XShape > xShape(
1962 m_xShapeFactory->createInstance( C2U(
1963 "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY );
1964
1965 xTarget->add(xShape);
1966
1967 //it is necessary to set the transform matrix to initialize the scene properly (bug #106316#)
1968 //otherwise all objects which are placed into this Group will not be visible
1969 //the following should be unnecessary after a the bug is fixed
1970 {
1971 //set properties
1972 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
1973 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
1974 if( xProp.is())
1975 {
1976 try
1977 {
1978 ::basegfx::B3DHomMatrix aM;
1979 xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
1980 , uno::makeAny(B3DHomMatrixToHomogenMatrix(aM)) );
1981 }
1982 catch( uno::Exception& e )
1983 {
1984 ASSERT_EXCEPTION( e );
1985 }
1986 }
1987 }
1988
1989 //set name
1990 if( !aName.isEmpty() )
1991 setShapeName( xShape , aName );
1992
1993 //return
1994 uno::Reference< drawing::XShapes > xShapes =
1995 uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
1996 return xShapes;
1997 }
1998 catch( uno::Exception& e )
1999 {
2000 ASSERT_EXCEPTION( e );
2001 }
2002 return 0;
2003 }
2004
2005 uno::Reference< drawing::XShape >
createCircle2D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::Position3D & rPosition,const drawing::Direction3D & rSize)2006 ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget
2007 , const drawing::Position3D& rPosition
2008 , const drawing::Direction3D& rSize )
2009 {
2010 if( !xTarget.is() )
2011 return 0;
2012
2013 //create shape
2014 uno::Reference< drawing::XShape > xShape(
2015 m_xShapeFactory->createInstance( C2U(
2016 "com.sun.star.drawing.EllipseShape") ), uno::UNO_QUERY );
2017 xTarget->add(xShape);
2018
2019 try
2020 {
2021 drawing::Position3D aCenterPosition(
2022 rPosition.PositionX - (rSize.DirectionX / 2.0),
2023 rPosition.PositionY - (rSize.DirectionY / 2.0),
2024 rPosition.PositionZ );
2025 xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
2026 xShape->setSize( Direction3DToAWTSize( rSize ));
2027 }
2028 catch( const uno::Exception & e )
2029 {
2030 ASSERT_EXCEPTION( e );
2031 }
2032
2033 //set properties
2034 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2035 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
2036 if( xProp.is())
2037 {
2038 try
2039 {
2040 drawing::CircleKind eKind = drawing::CircleKind_FULL;
2041 xProp->setPropertyValue( C2U( UNO_NAME_CIRCKIND )
2042 , uno::makeAny( eKind ) );
2043 }
2044 catch( uno::Exception& e )
2045 {
2046 ASSERT_EXCEPTION( e );
2047 }
2048 }
2049 return xShape;
2050 }
2051
2052 uno::Reference< drawing::XShape >
createLine3D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::PolyPolygonShape3D & rPoints,const VLineProperties & rLineProperties)2053 ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget
2054 , const drawing::PolyPolygonShape3D& rPoints
2055 , const VLineProperties& rLineProperties )
2056 {
2057 if( !xTarget.is() )
2058 return 0;
2059
2060 if(!rPoints.SequenceX.getLength())
2061 return NULL;
2062
2063 //create shape
2064 uno::Reference< drawing::XShape > xShape(
2065 m_xShapeFactory->createInstance( C2U(
2066 "com.sun.star.drawing.Shape3DPolygonObject") ), uno::UNO_QUERY );
2067 xTarget->add(xShape);
2068
2069 //set properties
2070 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2071 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
2072 if( xProp.is())
2073 {
2074 try
2075 {
2076 //Polygon
2077 xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
2078 , uno::makeAny( rPoints ) );
2079
2080 //LineOnly
2081 xProp->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY )
2082 , uno::makeAny( (sal_Bool)true ) );
2083
2084 //Transparency
2085 if(rLineProperties.Transparence.hasValue())
2086 xProp->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE )
2087 , rLineProperties.Transparence );
2088
2089 //LineStyle
2090 if(rLineProperties.LineStyle.hasValue())
2091 xProp->setPropertyValue( C2U( UNO_NAME_LINESTYLE )
2092 , rLineProperties.LineStyle );
2093
2094 //LineWidth
2095 if(rLineProperties.Width.hasValue())
2096 xProp->setPropertyValue( C2U( UNO_NAME_LINEWIDTH )
2097 , rLineProperties.Width );
2098
2099 //LineColor
2100 if(rLineProperties.Color.hasValue())
2101 xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
2102 , rLineProperties.Color );
2103 //, uno::makeAny( sal_Int32( Color(COL_RED).GetColor()) ) );
2104 }
2105 catch( uno::Exception& e )
2106 {
2107 ASSERT_EXCEPTION( e );
2108 }
2109 }
2110 return xShape;
2111 }
2112
2113 uno::Reference< drawing::XShape >
createLine2D(const uno::Reference<drawing::XShapes> & xTarget,const drawing::PointSequenceSequence & rPoints,const VLineProperties * pLineProperties)2114 ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget
2115 , const drawing::PointSequenceSequence& rPoints
2116 , const VLineProperties* pLineProperties )
2117 {
2118 if( !xTarget.is() )
2119 return 0;
2120
2121 if(!rPoints.getLength())
2122 return NULL;
2123
2124 //create shape
2125 uno::Reference< drawing::XShape > xShape(
2126 m_xShapeFactory->createInstance( C2U(
2127 //"com.sun.star.drawing.LineShape") ), uno::UNO_QUERY );
2128 "com.sun.star.drawing.PolyLineShape") ), uno::UNO_QUERY );
2129 //"com.sun.star.drawing.PolyLinePathShape") ), uno::UNO_QUERY );
2130 //"com.sun.star.drawing.PolyPolygonPathShape") ), uno::UNO_QUERY );
2131 //"com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
2132 xTarget->add(xShape);
2133
2134 //set properties
2135 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2136 DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
2137 if( xProp.is())
2138 {
2139 try
2140 {
2141 //Polygon
2142 xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
2143 , uno::makeAny( rPoints ) );
2144
2145 if(pLineProperties)
2146 {
2147 //Transparency
2148 if(pLineProperties->Transparence.hasValue())
2149 xProp->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE )
2150 , pLineProperties->Transparence );
2151
2152 //LineStyle
2153 if(pLineProperties->LineStyle.hasValue())
2154 xProp->setPropertyValue( C2U( UNO_NAME_LINESTYLE )
2155 , pLineProperties->LineStyle );
2156
2157 //LineWidth
2158 if(pLineProperties->Width.hasValue())
2159 xProp->setPropertyValue( C2U( UNO_NAME_LINEWIDTH )
2160 , pLineProperties->Width );
2161
2162 //LineColor
2163 if(pLineProperties->Color.hasValue())
2164 xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
2165 , pLineProperties->Color );
2166
2167 //LineDashName
2168 if(pLineProperties->DashName.hasValue())
2169 xProp->setPropertyValue( C2U( "LineDashName" )
2170 , pLineProperties->DashName );
2171 }
2172 }
2173 catch( uno::Exception& e )
2174 {
2175 ASSERT_EXCEPTION( e );
2176 }
2177 }
2178 return xShape;
2179 }
2180
makeTransformation(const awt::Point & rScreenPosition2D,double fRotationAnglePi)2181 uno::Any ShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
2182 {
2183 ::basegfx::B2DHomMatrix aM;
2184 //As autogrow is active the rectangle is automatically expanded to that side
2185 //to which the text is not adjusted.
2186 // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
2187 aM.rotate( fRotationAnglePi );
2188 aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
2189 uno::Any aATransformation = uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) );
2190 return aATransformation;
2191 }
2192
makeShapeInvisible(const uno::Reference<drawing::XShape> & xShape)2193 void ShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape )
2194 {
2195 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
2196 DBG_ASSERT(xShapeProp.is(), "created shape offers no XPropertySet");
2197 if( xShapeProp.is())
2198 {
2199 try
2200 {
2201 xShapeProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE ));
2202 xShapeProp->setPropertyValue( C2U("FillStyle"), uno::makeAny( drawing::FillStyle_NONE ));
2203 }
2204 catch( uno::Exception& e )
2205 {
2206 ASSERT_EXCEPTION( e );
2207 }
2208 }
2209 }
2210
createInvisibleRectangle(const uno::Reference<drawing::XShapes> & xTarget,const awt::Size & rSize)2211 uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle(
2212 const uno::Reference< drawing::XShapes >& xTarget
2213 , const awt::Size& rSize )
2214 {
2215 try
2216 {
2217 if(!xTarget.is())
2218 return 0;
2219
2220 uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
2221 C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
2222 if( xTarget.is() && xShape.is())
2223 {
2224 xTarget->add( xShape );
2225 ShapeFactory::makeShapeInvisible( xShape );
2226 xShape->setSize( rSize );
2227 }
2228 return xShape;
2229 }
2230 catch( uno::Exception & ex )
2231 {
2232 ASSERT_EXCEPTION( ex );
2233 }
2234 return 0;
2235 }
2236
2237 uno::Reference< drawing::XShape >
createText(const uno::Reference<drawing::XShapes> & xTarget,const::rtl::OUString & rText,const tNameSequence & rPropNames,const tAnySequence & rPropValues,const uno::Any & rATransformation)2238 ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
2239 , const ::rtl::OUString& rText
2240 , const tNameSequence& rPropNames
2241 , const tAnySequence& rPropValues
2242 , const uno::Any& rATransformation )
2243 {
2244 if( !xTarget.is() )
2245 return 0;
2246
2247 if( rText.isEmpty() )
2248 return 0;
2249
2250 //create shape and add to page
2251 uno::Reference< drawing::XShape > xShape(
2252 m_xShapeFactory->createInstance( C2U(
2253 "com.sun.star.drawing.TextShape" ) ), uno::UNO_QUERY );
2254 xTarget->add(xShape);
2255
2256 //set text
2257 uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY );
2258 if( xTextRange.is() )
2259 xTextRange->setString( rText );
2260
2261 uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2262 if( xProp.is() )
2263 {
2264 //set properties
2265 PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
2266
2267 //set position matrix
2268 //the matrix needs to be set at the end behind autogrow and such position influencing properties
2269 try
2270 {
2271 xProp->setPropertyValue( C2U( "Transformation" ), rATransformation );
2272 }
2273 catch( uno::Exception& e )
2274 {
2275 ASSERT_EXCEPTION( e );
2276 }
2277 }
2278 return xShape;
2279 }
2280
getStackedString(const rtl::OUString & rString,bool bStacked)2281 rtl::OUString ShapeFactory::getStackedString( const rtl::OUString& rString, bool bStacked )
2282 {
2283 sal_Int32 nLen = rString.getLength();
2284 if(!bStacked || !nLen)
2285 return rString;
2286
2287 rtl::OUStringBuffer aStackStr;
2288 rtl::OUStringBuffer aSource(rString);
2289
2290 //add a newline after each letter
2291 //as we do not no letters here add a newline after each char
2292 for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
2293 {
2294 if( nPosSrc )
2295 aStackStr.append( sal_Unicode('\r') );
2296 aStackStr.append( aSource.charAt( nPosSrc ) );
2297 }
2298 return aStackStr.makeStringAndClear();
2299 }
2300
hasPolygonAnyLines(drawing::PolyPolygonShape3D & rPoly)2301 bool ShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly)
2302 {
2303 // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
2304 for( sal_Int32 nIdx = 0, nCount = rPoly.SequenceX.getLength(); nIdx < nCount; ++nIdx )
2305 if( rPoly.SequenceX[ nIdx ].getLength() > 1 )
2306 return true;
2307 return false;
2308 }
2309
isPolygonEmptyOrSinglePoint(drawing::PolyPolygonShape3D & rPoly)2310 bool ShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly)
2311 {
2312 // true, if empty polypolygon or one polygon with one point
2313 return (rPoly.SequenceX.getLength() == 0) ||
2314 ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
2315 }
2316
closePolygon(drawing::PolyPolygonShape3D & rPoly)2317 void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
2318 {
2319 DBG_ASSERT( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
2320 //add a last point == first point
2321 if(isPolygonEmptyOrSinglePoint(rPoly))
2322 return;
2323 drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
2324 AddPointToPoly( rPoly, aFirst );
2325 }
2326
calculateNewSizeRespectingAspectRatio(const awt::Size & rTargetSize,const awt::Size & rSourceSizeWithCorrectAspectRatio)2327 awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
2328 const awt::Size& rTargetSize
2329 , const awt::Size& rSourceSizeWithCorrectAspectRatio )
2330 {
2331 awt::Size aNewSize;
2332
2333 double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
2334 double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
2335 double fFactor = std::min(fFactorWidth,fFactorHeight);
2336 aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
2337 aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);
2338
2339 return aNewSize;
2340 }
2341
calculateTopLeftPositionToCenterObject(const awt::Point & rTargetAreaPosition,const awt::Size & rTargetAreaSize,const awt::Size & rObjectSize)2342 awt::Point ShapeFactory::calculateTopLeftPositionToCenterObject(
2343 const awt::Point& rTargetAreaPosition
2344 , const awt::Size& rTargetAreaSize
2345 , const awt::Size& rObjectSize )
2346 {
2347 awt::Point aNewPosition(rTargetAreaPosition);
2348 aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
2349 aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
2350 return aNewPosition;
2351 }
2352
getRectangleOfShape(const uno::Reference<drawing::XShape> & xShape)2353 ::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape(
2354 const uno::Reference< drawing::XShape >& xShape )
2355 {
2356 ::basegfx::B2IRectangle aRet;
2357
2358 if( xShape.is() )
2359 {
2360 awt::Point aPos = xShape->getPosition();
2361 awt::Size aSize = xShape->getSize();
2362 aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
2363 }
2364 return aRet;
2365
2366 }
2367
getSizeAfterRotation(const uno::Reference<drawing::XShape> & xShape,double fRotationAngleDegree)2368 awt::Size ShapeFactory::getSizeAfterRotation(
2369 const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
2370 {
2371 awt::Size aRet(0,0);
2372 if(xShape.is())
2373 {
2374 const awt::Size aSize( xShape->getSize() );
2375
2376 if( ::rtl::math::approxEqual( fRotationAngleDegree, 0.0 ) )
2377 aRet = aSize;
2378 else
2379 {
2380 while(fRotationAngleDegree>=360.0)
2381 fRotationAngleDegree-=360.0;
2382 while(fRotationAngleDegree<0.0)
2383 fRotationAngleDegree+=360.0;
2384 if(fRotationAngleDegree>270.0)
2385 fRotationAngleDegree=360.0-fRotationAngleDegree;
2386 else if(fRotationAngleDegree>180.0)
2387 fRotationAngleDegree=fRotationAngleDegree-180.0;
2388 else if(fRotationAngleDegree>90.0)
2389 fRotationAngleDegree=180.0-fRotationAngleDegree;
2390
2391 const double fAnglePi = fRotationAngleDegree*F_PI/180.0;
2392
2393 aRet.Height = static_cast<sal_Int32>(
2394 aSize.Width*rtl::math::sin( fAnglePi )
2395 + aSize.Height*rtl::math::cos( fAnglePi ));
2396 aRet.Width = static_cast<sal_Int32>(
2397 aSize.Width*rtl::math::cos( fAnglePi )
2398 + aSize.Height*rtl::math::sin( fAnglePi ));
2399 }
2400 }
2401 return aRet;
2402 }
2403
removeSubShapes(const uno::Reference<drawing::XShapes> & xShapes)2404 void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
2405 {
2406 if( xShapes.is() )
2407 {
2408 sal_Int32 nSubCount = xShapes->getCount();
2409 uno::Reference< drawing::XShape > xShape;
2410 for( sal_Int32 nS = nSubCount; nS--; )
2411 {
2412 if( xShapes->getByIndex( nS ) >>= xShape )
2413 xShapes->remove( xShape );
2414 }
2415 }
2416 }
2417
2418 //.............................................................................
2419 } //namespace chart
2420 //.............................................................................
2421