1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "CommonConverters.hxx"
31 #include <com/sun/star/drawing/DoubleSequence.hpp>
32 #include <com/sun/star/text/WritingMode2.hpp>
33 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
34 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
35 #include <rtl/math.hxx>
36 #include <basegfx/matrix/b3dhommatrix.hxx>
37 
38 #include <cstdarg>
39 
40 
41 //.............................................................................
42 namespace chart
43 {
44 //.............................................................................
45 
46 using namespace ::com::sun::star;
47 
48 //-----------------------------------------------------------------------------
49 //-----------------------------------------------------------------------------
50 //  diverse methods for class conversions; e.g. ::basegfx::B3DHomMatrix to HomogenMatrix
51 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
53 
54 drawing::HomogenMatrix B3DHomMatrixToHomogenMatrix( const ::basegfx::B3DHomMatrix& rM )
55 {
56     drawing::HomogenMatrix aHM;
57     aHM.Line1.Column1 = rM.get(0, 0);
58 	aHM.Line1.Column2 = rM.get(0, 1);
59 	aHM.Line1.Column3 = rM.get(0, 2);
60 	aHM.Line1.Column4 = rM.get(0, 3);
61 	aHM.Line2.Column1 = rM.get(1, 0);
62 	aHM.Line2.Column2 = rM.get(1, 1);
63 	aHM.Line2.Column3 = rM.get(1, 2);
64 	aHM.Line2.Column4 = rM.get(1, 3);
65 	aHM.Line3.Column1 = rM.get(2, 0);
66 	aHM.Line3.Column2 = rM.get(2, 1);
67 	aHM.Line3.Column3 = rM.get(2, 2);
68 	aHM.Line3.Column4 = rM.get(2, 3);
69 	aHM.Line4.Column1 = rM.get(3, 0);
70 	aHM.Line4.Column2 = rM.get(3, 1);
71 	aHM.Line4.Column3 = rM.get(3, 2);
72 	aHM.Line4.Column4 = rM.get(3, 3);
73     return aHM;
74 }
75 
76 ::basegfx::B3DHomMatrix HomogenMatrixToB3DHomMatrix( const drawing::HomogenMatrix& rHM )
77 {
78     ::basegfx::B3DHomMatrix aM;
79     aM.set(0, 0, rHM.Line1.Column1);
80 	aM.set(0, 1, rHM.Line1.Column2);
81 	aM.set(0, 2, rHM.Line1.Column3);
82 	aM.set(0, 3, rHM.Line1.Column4);
83 	aM.set(1, 0, rHM.Line2.Column1);
84 	aM.set(1, 1, rHM.Line2.Column2);
85 	aM.set(1, 2, rHM.Line2.Column3);
86 	aM.set(1, 3, rHM.Line2.Column4);
87 	aM.set(2, 0, rHM.Line3.Column1);
88 	aM.set(2, 1, rHM.Line3.Column2);
89 	aM.set(2, 2, rHM.Line3.Column3);
90 	aM.set(2, 3, rHM.Line3.Column4);
91 	aM.set(3, 0, rHM.Line4.Column1);
92 	aM.set(3, 1, rHM.Line4.Column2);
93 	aM.set(3, 2, rHM.Line4.Column3);
94 	aM.set(3, 3, rHM.Line4.Column4);
95     return aM;
96 }
97 
98 ::basegfx::B2DHomMatrix IgnoreZ( const ::basegfx::B3DHomMatrix& rM )
99 {
100 	::basegfx::B2DHomMatrix aM;
101     aM.set(0, 0, rM.get(0, 0));
102 	aM.set(0, 1, rM.get(0, 1));
103 	aM.set(0, 2, rM.get(0, 3));
104 	aM.set(1, 0, rM.get(1, 0));
105 	aM.set(1, 1, rM.get(1, 1));
106 	aM.set(1, 2, rM.get(1, 3));
107 	aM.set(2, 0, rM.get(3, 0));
108 	aM.set(2, 1, rM.get(3, 1));
109 	aM.set(2, 2, rM.get(3, 3));
110     return aM;
111 }
112 
113 
114 drawing::HomogenMatrix3 B2DHomMatrixToHomogenMatrix3( const ::basegfx::B2DHomMatrix& rM )
115 {
116     drawing::HomogenMatrix3 aHM;
117     aHM.Line1.Column1 = rM.get(0, 0);
118 	aHM.Line1.Column2 = rM.get(0, 1);
119 	aHM.Line1.Column3 = rM.get(0, 2);
120 	aHM.Line2.Column1 = rM.get(1, 0);
121 	aHM.Line2.Column2 = rM.get(1, 1);
122 	aHM.Line2.Column3 = rM.get(1, 2);
123 	aHM.Line3.Column1 = rM.get(2, 0);
124 	aHM.Line3.Column2 = rM.get(2, 1);
125 	aHM.Line3.Column3 = rM.get(2, 2);
126     return aHM;
127 }
128 
129 ::basegfx::B3DPoint Position3DToB3DPoint( const drawing::Position3D& rPosition )
130 {
131     return ::basegfx::B3DPoint(
132 		rPosition.PositionX ,
133 		rPosition.PositionY ,
134 		rPosition.PositionZ );
135 }
136 
137 drawing::Direction3D B3DVectorToDirection3D( const ::basegfx::B3DVector& rVector)
138 {
139     return drawing::Direction3D(
140           rVector.getX()
141         , rVector.getY()
142         , rVector.getZ()
143         );
144 }
145 
146 drawing::Position3D B3DPointToPosition3D( const ::basegfx::B3DPoint& rPoint)
147 {
148         return drawing::Position3D(
149           rPoint.getX()
150         , rPoint.getY()
151         , rPoint.getZ()
152         );
153 }
154 
155 ::basegfx::B3DVector Direction3DToB3DVector( const drawing::Direction3D& rDirection)
156 {
157     return ::basegfx::B3DVector(
158           rDirection.DirectionX
159         , rDirection.DirectionY
160         , rDirection.DirectionZ
161         );
162 }
163 
164 void AddPointToPoly( drawing::PolyPolygonShape3D& rPoly, const drawing::Position3D& rPos, sal_Int32 nPolygonIndex )
165 {
166     if(nPolygonIndex<0)
167     {
168         OSL_ENSURE( false, "The polygon index needs to be > 0");
169         nPolygonIndex=0;
170     }
171 
172     //make sure that we have enough polygons
173     if(nPolygonIndex >= rPoly.SequenceX.getLength() )
174     {
175         rPoly.SequenceX.realloc(nPolygonIndex+1);
176         rPoly.SequenceY.realloc(nPolygonIndex+1);
177         rPoly.SequenceZ.realloc(nPolygonIndex+1);
178     }
179 
180     drawing::DoubleSequence* pOuterSequenceX = &rPoly.SequenceX.getArray()[nPolygonIndex];
181     drawing::DoubleSequence* pOuterSequenceY = &rPoly.SequenceY.getArray()[nPolygonIndex];
182     drawing::DoubleSequence* pOuterSequenceZ = &rPoly.SequenceZ.getArray()[nPolygonIndex];
183 
184     sal_Int32 nOldPointCount = pOuterSequenceX->getLength();
185 
186     pOuterSequenceX->realloc(nOldPointCount+1);
187     pOuterSequenceY->realloc(nOldPointCount+1);
188     pOuterSequenceZ->realloc(nOldPointCount+1);
189 
190     double* pInnerSequenceX = pOuterSequenceX->getArray();
191     double* pInnerSequenceY = pOuterSequenceY->getArray();
192     double* pInnerSequenceZ = pOuterSequenceZ->getArray();
193 
194     pInnerSequenceX[nOldPointCount] = rPos.PositionX;
195     pInnerSequenceY[nOldPointCount] = rPos.PositionY;
196     pInnerSequenceZ[nOldPointCount] = rPos.PositionZ;
197 }
198 
199 drawing::Position3D getPointFromPoly( const drawing::PolyPolygonShape3D& rPolygon, sal_Int32 nPointIndex, sal_Int32 nPolyIndex )
200 {
201     drawing::Position3D aRet(0.0,0.0,0.0);
202 
203     if( nPolyIndex>=0 && nPolyIndex<rPolygon.SequenceX.getLength())
204     {
205         if(nPointIndex<rPolygon.SequenceX[nPolyIndex].getLength())
206         {
207             aRet.PositionX = rPolygon.SequenceX[nPolyIndex][nPointIndex];
208             aRet.PositionY = rPolygon.SequenceY[nPolyIndex][nPointIndex];
209             aRet.PositionZ = rPolygon.SequenceZ[nPolyIndex][nPointIndex];
210         }
211         else
212         {
213             ;DBG_ERROR("polygon was accessed with a wrong index");
214         }
215     }
216     else
217     {
218         ;DBG_ERROR("polygon was accessed with a wrong index");
219     }
220     return aRet;
221 }
222 
223 void addPolygon( drawing::PolyPolygonShape3D& rRet, const drawing::PolyPolygonShape3D& rAdd )
224 {
225     sal_Int32 nAddOuterCount = rAdd.SequenceX.getLength();
226     sal_Int32 nOuterCount = rRet.SequenceX.getLength() + nAddOuterCount;
227     rRet.SequenceX.realloc( nOuterCount );
228     rRet.SequenceY.realloc( nOuterCount );
229     rRet.SequenceZ.realloc( nOuterCount );
230 
231     sal_Int32 nIndex = 0;
232     sal_Int32 nOuter = nOuterCount - nAddOuterCount;
233     for( ; nOuter < nOuterCount; nOuter++ )
234     {
235         if( nIndex >= nAddOuterCount )
236             break;
237 
238         rRet.SequenceX[nOuter] = rAdd.SequenceX[nIndex];
239         rRet.SequenceY[nOuter] = rAdd.SequenceY[nIndex];
240         rRet.SequenceZ[nOuter] = rAdd.SequenceZ[nIndex];
241 
242         nIndex++;
243     }
244 }
245 
246 void appendPoly( drawing::PolyPolygonShape3D& rRet, const drawing::PolyPolygonShape3D& rAdd )
247 {
248     sal_Int32 nOuterCount = Max( rRet.SequenceX.getLength(), rAdd.SequenceX.getLength() );
249 	rRet.SequenceX.realloc(nOuterCount);
250 	rRet.SequenceY.realloc(nOuterCount);
251 	rRet.SequenceZ.realloc(nOuterCount);
252 
253     for( sal_Int32 nOuter=0;nOuter<nOuterCount;nOuter++ )
254     {
255         sal_Int32 nOldPointCount = rRet.SequenceX[nOuter].getLength();
256         sal_Int32 nAddPointCount = 0;
257         if(nOuter<rAdd.SequenceX.getLength())
258             nAddPointCount = rAdd.SequenceX[nOuter].getLength();
259         if(!nAddPointCount)
260             continue;
261 
262         sal_Int32 nNewPointCount = nOldPointCount + nAddPointCount;
263 
264         rRet.SequenceX[nOuter].realloc(nNewPointCount);
265         rRet.SequenceY[nOuter].realloc(nNewPointCount);
266 	    rRet.SequenceZ[nOuter].realloc(nNewPointCount);
267 
268         sal_Int32 nPointTarget=nOldPointCount;
269         sal_Int32 nPointSource=nAddPointCount;
270         for( ; nPointSource-- ; nPointTarget++ )
271         {
272 	        rRet.SequenceX[nOuter][nPointTarget] = rAdd.SequenceX[nOuter][nPointSource];
273             rRet.SequenceY[nOuter][nPointTarget] = rAdd.SequenceY[nOuter][nPointSource];
274             rRet.SequenceZ[nOuter][nPointTarget] = rAdd.SequenceZ[nOuter][nPointSource];
275         }
276     }
277 }
278 
279 drawing::PolyPolygonShape3D BezierToPoly(
280     const drawing::PolyPolygonBezierCoords& rBezier )
281 {
282     const drawing::PointSequenceSequence& rPointSequence = rBezier.Coordinates;
283 //     const drawing::FlagSequenceSequence& rFlags = rBezier.Flags;
284 
285     drawing::PolyPolygonShape3D aRet;
286     aRet.SequenceX.realloc( rPointSequence.getLength() );
287     aRet.SequenceY.realloc( rPointSequence.getLength() );
288     aRet.SequenceZ.realloc( rPointSequence.getLength() );
289 
290     sal_Int32 nRealOuter = 0;
291     for(sal_Int32 nN = 0; nN < rPointSequence.getLength(); nN++)
292     {
293         sal_Int32 nInnerLength = rPointSequence[nN].getLength();
294         aRet.SequenceX[nN].realloc( nInnerLength );
295         aRet.SequenceY[nN].realloc( nInnerLength );
296         aRet.SequenceZ[nN].realloc( nInnerLength );
297 
298         bool bHasOuterFlags = nN < rBezier.Flags.getLength();
299 
300         sal_Int32 nRealInner = 0;
301         for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
302         {
303             bool bHasInnerFlags = bHasOuterFlags && (nM < rBezier.Flags[nN].getLength());
304 
305             if( !bHasInnerFlags || (rBezier.Flags[nN][nM] == drawing::PolygonFlags_NORMAL) )
306             {
307                 aRet.SequenceX[nRealOuter][nRealInner] = rPointSequence[nN][nM].X;
308                 aRet.SequenceY[nRealOuter][nRealInner] = rPointSequence[nN][nM].Y;
309                 aRet.SequenceZ[nRealOuter][nRealInner] = 0.0;
310                 nRealInner++;
311             }
312         }
313 
314         aRet.SequenceX[nRealOuter].realloc( nRealInner );
315         aRet.SequenceY[nRealOuter].realloc( nRealInner );
316         aRet.SequenceZ[nRealOuter].realloc( nRealInner );
317 
318         if( nRealInner>0 )
319             nRealOuter++;
320     }
321 
322     aRet.SequenceX.realloc( nRealOuter );
323     aRet.SequenceY.realloc( nRealOuter );
324     aRet.SequenceZ.realloc( nRealOuter );
325 
326     return aRet;
327 }
328 
329 drawing::PointSequenceSequence PolyToPointSequence(
330                 const drawing::PolyPolygonShape3D& rPolyPolygon )
331 {
332     drawing::PointSequenceSequence aRet;
333     aRet.realloc( rPolyPolygon.SequenceX.getLength() );
334 
335     for(sal_Int32 nN = 0; nN < rPolyPolygon.SequenceX.getLength(); nN++)
336     {
337         sal_Int32 nInnerLength = rPolyPolygon.SequenceX[nN].getLength();
338         aRet[nN].realloc( nInnerLength );
339         for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
340         {
341             aRet[nN][nM].X = static_cast<sal_Int32>(rPolyPolygon.SequenceX[nN][nM]);
342             aRet[nN][nM].Y = static_cast<sal_Int32>(rPolyPolygon.SequenceY[nN][nM]);
343         }
344     }
345     return aRet;
346 }
347 
348 void appendPointSequence( drawing::PointSequenceSequence& rTarget
349                         , drawing::PointSequenceSequence& rAdd )
350 {
351     sal_Int32 nAddCount = rAdd.getLength();
352     if(!nAddCount)
353         return;
354     sal_Int32 nOldCount = rTarget.getLength();
355 
356     rTarget.realloc(nOldCount+nAddCount);
357     for(sal_Int32 nS=0; nS<nAddCount; nS++ )
358         rTarget[nOldCount+nS]=rAdd[nS];
359 }
360 
361 drawing::Position3D  operator+( const drawing::Position3D& rPos
362                            , const drawing::Direction3D& rDirection)
363 {
364     return drawing::Position3D(
365           rPos.PositionX + rDirection.DirectionX
366         , rPos.PositionY + rDirection.DirectionY
367         , rPos.PositionZ + rDirection.DirectionZ
368         );
369 }
370 
371 drawing::Direction3D  operator-( const drawing::Position3D& rPos1
372                            , const drawing::Position3D& rPos2)
373 {
374     return drawing::Direction3D(
375           rPos1.PositionX - rPos2.PositionX
376         , rPos1.PositionY - rPos2.PositionY
377         , rPos1.PositionZ - rPos2.PositionZ
378         );
379 }
380 
381 bool operator==( const drawing::Position3D& rPos1
382                            , const drawing::Position3D& rPos2)
383 {
384     return rPos1.PositionX == rPos2.PositionX
385         && rPos1.PositionY == rPos2.PositionY
386         && rPos1.PositionZ == rPos2.PositionZ;
387 }
388 
389 awt::Point Position3DToAWTPoint( const drawing::Position3D& rPos )
390 {
391     awt::Point aRet;
392     aRet.X = static_cast<sal_Int32>(rPos.PositionX);
393     aRet.Y = static_cast<sal_Int32>(rPos.PositionY);
394     return aRet;
395 }
396 
397 awt::Point ToPoint( const awt::Rectangle& rRectangle )
398 {
399     return awt::Point( rRectangle.X, rRectangle.Y );
400 }
401 
402 awt::Size ToSize( const awt::Rectangle& rRectangle )
403 {
404     return awt::Size( rRectangle.Width, rRectangle.Height );
405 }
406 
407 awt::Size Direction3DToAWTSize( const drawing::Direction3D& rDirection )
408 {
409     awt::Size aRet;
410     aRet.Width = static_cast<sal_Int32>(rDirection.DirectionX);
411     aRet.Height = static_cast<sal_Int32>(rDirection.DirectionY);
412     return aRet;
413 }
414 
415 uno::Sequence< double > B3DPointToSequence( const ::basegfx::B3DPoint& rPoint )
416 {
417     uno::Sequence< double > aRet(3);
418     aRet[0] = rPoint.getX();
419     aRet[1] = rPoint.getY();
420     aRet[2] = rPoint.getZ();
421     return aRet;
422 }
423 
424 drawing::Position3D SequenceToPosition3D( const uno::Sequence< double >& rSeq )
425 {
426     OSL_ENSURE(rSeq.getLength()==3,"The sequence needs to have length 3 for conversion into vector");
427 
428     drawing::Position3D aRet;
429     aRet.PositionX = rSeq.getLength()>0?rSeq[0]:0.0;
430     aRet.PositionY = rSeq.getLength()>1?rSeq[1]:0.0;
431     aRet.PositionZ = rSeq.getLength()>2?rSeq[2]:0.0;
432     return aRet;
433 }
434 
435 uno::Sequence< double > Position3DToSequence( const drawing::Position3D& rPosition )
436 {
437     uno::Sequence< double > aRet(3);
438     aRet[0] = rPosition.PositionX;
439     aRet[1] = rPosition.PositionY;
440     aRet[2] = rPosition.PositionZ;
441     return aRet;
442 }
443 
444 using namespace ::com::sun::star::chart2;
445 
446 uno::Sequence< double > DataSequenceToDoubleSequence(
447     const uno::Reference< data::XDataSequence >& xDataSequence )
448 {
449     uno::Sequence< double > aResult;
450     OSL_ASSERT( xDataSequence.is());
451     if(!xDataSequence.is())
452         return aResult;
453 
454     uno::Reference< data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
455     if( xNumericalDataSequence.is() )
456     {
457         aResult = xNumericalDataSequence->getNumericalData();
458     }
459     else
460     {
461         uno::Sequence< uno::Any > aValues = xDataSequence->getData();
462         aResult.realloc(aValues.getLength());
463         for(sal_Int32 nN=aValues.getLength();nN--;)
464         {
465             if( !(aValues[nN] >>= aResult[nN]) )
466                 ::rtl::math::setNan( &aResult[nN] );
467         }
468     }
469 
470     return aResult;
471 }
472 
473 uno::Sequence< rtl::OUString > DataSequenceToStringSequence(
474     const uno::Reference< data::XDataSequence >& xDataSequence )
475 {
476     uno::Sequence< rtl::OUString > aResult;
477     if(!xDataSequence.is())
478         return aResult;
479 
480     uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
481     if( xTextualDataSequence.is() )
482     {
483         aResult = xTextualDataSequence->getTextualData();
484     }
485     else
486     {
487         uno::Sequence< uno::Any > aValues = xDataSequence->getData();
488         aResult.realloc(aValues.getLength());
489 
490         for(sal_Int32 nN=aValues.getLength();nN--;)
491             aValues[nN] >>= aResult[nN];
492     }
493 
494     return aResult;
495 }
496 
497 sal_Bool hasDoubleValue( const uno::Any& rAny )
498 {
499     sal_Bool bRet = sal_False;
500     double fValue = 0.0;
501     if( rAny >>= fValue )
502         bRet = sal_True;
503     return bRet;
504 }
505 
506 sal_Bool hasLongOrShortValue( const uno::Any& rAny )
507 {
508     sal_Bool bRet = sal_False;
509     sal_Int32 n32 = 0;
510     if( rAny >>= n32 )
511         bRet = sal_True;
512     else
513     {
514         sal_Int16 n16 = 0;
515         if( rAny >>= n16 )
516             bRet = sal_True;
517     }
518     return bRet;
519 }
520 sal_Int16 getShortForLongAlso( const uno::Any& rAny )
521 {
522     sal_Int16 nRet = 0;
523 
524     if( !(rAny >>= nRet) )
525     {
526         sal_Int32 n32 = 0;
527         if( rAny >>= n32 )
528             nRet = static_cast<sal_Int16>(n32);
529     }
530     return nRet;
531 }
532 
533 bool replaceParamterInString( rtl::OUString & rInOutResourceString,
534                             const rtl::OUString & rParamToReplace,
535                             const rtl::OUString & rReplaceWith )
536 {
537     sal_Int32 nPos = rInOutResourceString.indexOf( rParamToReplace );
538     if( nPos == -1 )
539         return false;
540 
541     rInOutResourceString = rInOutResourceString.replaceAt( nPos
542                         , rParamToReplace.getLength(), rReplaceWith );
543     return true;
544 }
545 
546 //.............................................................................
547 } //namespace chart
548 //.............................................................................
549