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