xref: /aoo42x/main/slideshow/source/engine/tools.cxx (revision 70f497fb)
1*70f497fbSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*70f497fbSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*70f497fbSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*70f497fbSAndrew Rist  * distributed with this work for additional information
6*70f497fbSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*70f497fbSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*70f497fbSAndrew Rist  * "License"); you may not use this file except in compliance
9*70f497fbSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*70f497fbSAndrew Rist  *
11*70f497fbSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*70f497fbSAndrew Rist  *
13*70f497fbSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*70f497fbSAndrew Rist  * software distributed under the License is distributed on an
15*70f497fbSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*70f497fbSAndrew Rist  * KIND, either express or implied.  See the License for the
17*70f497fbSAndrew Rist  * specific language governing permissions and limitations
18*70f497fbSAndrew Rist  * under the License.
19*70f497fbSAndrew Rist  *
20*70f497fbSAndrew Rist  *************************************************************/
21*70f497fbSAndrew Rist 
22*70f497fbSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_slideshow.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <canvas/debug.hxx>
28cdf0e10cSrcweir #include <tools/diagnose_ex.h>
29cdf0e10cSrcweir #include <canvas/canvastools.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <math.h>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <com/sun/star/beans/NamedValue.hpp>
34cdf0e10cSrcweir #include <com/sun/star/awt/Rectangle.hpp>
35cdf0e10cSrcweir #include <com/sun/star/animations/ValuePair.hpp>
36cdf0e10cSrcweir #include <com/sun/star/drawing/FillStyle.hpp>
37cdf0e10cSrcweir #include <com/sun/star/drawing/LineStyle.hpp>
38cdf0e10cSrcweir #include <com/sun/star/awt/FontSlant.hpp>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
41cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
42cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
43cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx>
44cdf0e10cSrcweir #include <basegfx/vector/b2ivector.hxx>
45cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
46cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
47cdf0e10cSrcweir #include <basegfx/tools/lerp.hxx>
48cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include <cppcanvas/basegfxfactory.hxx>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #include "unoview.hxx"
53cdf0e10cSrcweir #include "smilfunctionparser.hxx"
54cdf0e10cSrcweir #include "tools.hxx"
55cdf0e10cSrcweir 
56cdf0e10cSrcweir #include <limits>
57cdf0e10cSrcweir 
58cdf0e10cSrcweir 
59cdf0e10cSrcweir using namespace ::com::sun::star;
60cdf0e10cSrcweir 
61cdf0e10cSrcweir namespace slideshow
62cdf0e10cSrcweir {
63cdf0e10cSrcweir     namespace internal
64cdf0e10cSrcweir     {
65cdf0e10cSrcweir         namespace
66cdf0e10cSrcweir         {
67cdf0e10cSrcweir             class NamedValueStringComparator
68cdf0e10cSrcweir             {
69cdf0e10cSrcweir             public:
NamedValueStringComparator(const::rtl::OUString & rSearchString)70cdf0e10cSrcweir                 NamedValueStringComparator( const ::rtl::OUString& rSearchString ) :
71cdf0e10cSrcweir                     mrSearchString( rSearchString )
72cdf0e10cSrcweir                 {
73cdf0e10cSrcweir                 }
74cdf0e10cSrcweir 
operator ()(const beans::NamedValue & rValue)75cdf0e10cSrcweir                 bool operator()( const beans::NamedValue& rValue )
76cdf0e10cSrcweir                 {
77cdf0e10cSrcweir                     return rValue.Name == mrSearchString;
78cdf0e10cSrcweir                 }
79cdf0e10cSrcweir 
80cdf0e10cSrcweir             private:
81cdf0e10cSrcweir                 const ::rtl::OUString&		mrSearchString;
82cdf0e10cSrcweir             };
83cdf0e10cSrcweir 
84cdf0e10cSrcweir             class NamedValueComparator
85cdf0e10cSrcweir             {
86cdf0e10cSrcweir             public:
NamedValueComparator(const beans::NamedValue & rKey)87cdf0e10cSrcweir                 NamedValueComparator( const beans::NamedValue& rKey ) :
88cdf0e10cSrcweir                     mrKey( rKey )
89cdf0e10cSrcweir                 {
90cdf0e10cSrcweir                 }
91cdf0e10cSrcweir 
operator ()(const beans::NamedValue & rValue)92cdf0e10cSrcweir                 bool operator()( const beans::NamedValue& rValue )
93cdf0e10cSrcweir                 {
94cdf0e10cSrcweir                     return rValue.Name == mrKey.Name && rValue.Value == mrKey.Value;
95cdf0e10cSrcweir                 }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir             private:
98cdf0e10cSrcweir                 const beans::NamedValue&	mrKey;
99cdf0e10cSrcweir             };
100cdf0e10cSrcweir 
getAttributedShapeTransformation(const::basegfx::B2DRectangle & rShapeBounds,const ShapeAttributeLayerSharedPtr & pAttr)101cdf0e10cSrcweir             ::basegfx::B2DHomMatrix getAttributedShapeTransformation( const ::basegfx::B2DRectangle&		rShapeBounds,
102cdf0e10cSrcweir                                                                       const ShapeAttributeLayerSharedPtr&	pAttr )
103cdf0e10cSrcweir             {
104cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix 	aTransform;
105cdf0e10cSrcweir                 const ::basegfx::B2DSize&	rSize( rShapeBounds.getRange() );
106cdf0e10cSrcweir 
107cdf0e10cSrcweir                 const double nShearX( pAttr->isShearXAngleValid() ?
108cdf0e10cSrcweir                                       pAttr->getShearXAngle() :
109cdf0e10cSrcweir                                       0.0 );
110cdf0e10cSrcweir                 const double nShearY( pAttr->isShearYAngleValid() ?
111cdf0e10cSrcweir                                       pAttr->getShearYAngle() :
112cdf0e10cSrcweir                                       0.0 );
113cdf0e10cSrcweir                 const double nRotation( pAttr->isRotationAngleValid() ?
114cdf0e10cSrcweir                                         pAttr->getRotationAngle()*M_PI/180.0 :
115cdf0e10cSrcweir                                         0.0 );
116cdf0e10cSrcweir 
117cdf0e10cSrcweir                 // scale, shear and rotation pivot point is the shape
118cdf0e10cSrcweir                 // center - adapt origin accordingly
119cdf0e10cSrcweir                 aTransform.translate( -0.5, -0.5 );
120cdf0e10cSrcweir 
121cdf0e10cSrcweir                 // ensure valid size (zero size will inevitably lead
122cdf0e10cSrcweir                 // to a singular transformation matrix)
123cdf0e10cSrcweir                 aTransform.scale( ::basegfx::pruneScaleValue(
124cdf0e10cSrcweir                                       rSize.getX() ),
125cdf0e10cSrcweir                                   ::basegfx::pruneScaleValue(
126cdf0e10cSrcweir                                       rSize.getY() ) );
127cdf0e10cSrcweir 
128cdf0e10cSrcweir                 const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
129cdf0e10cSrcweir                 const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
130cdf0e10cSrcweir                 const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );
131cdf0e10cSrcweir 
132cdf0e10cSrcweir                 if( bNeedRotation || bNeedShearX || bNeedShearY )
133cdf0e10cSrcweir                 {
134cdf0e10cSrcweir                     if( bNeedShearX )
135cdf0e10cSrcweir                         aTransform.shearX( nShearX );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir                     if( bNeedShearY )
138cdf0e10cSrcweir                         aTransform.shearY( nShearY );
139cdf0e10cSrcweir 
140cdf0e10cSrcweir                     if( bNeedRotation )
141cdf0e10cSrcweir                         aTransform.rotate( nRotation );
142cdf0e10cSrcweir                 }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir                 // move left, top corner back to position of the
145cdf0e10cSrcweir                 // shape. Since we've already translated the
146cdf0e10cSrcweir                 // center of the shape to the origin (the
147cdf0e10cSrcweir                 // translate( -0.5, -0.5 ) above), translate to
148cdf0e10cSrcweir                 // center of final shape position here.
149cdf0e10cSrcweir                 aTransform.translate( rShapeBounds.getCenterX(),
150cdf0e10cSrcweir                                       rShapeBounds.getCenterY() );
151cdf0e10cSrcweir 
152cdf0e10cSrcweir                 return aTransform;
153cdf0e10cSrcweir             }
154cdf0e10cSrcweir         }
155cdf0e10cSrcweir 
156cdf0e10cSrcweir         // Value extraction from Any
157cdf0e10cSrcweir         // =========================
158cdf0e10cSrcweir 
159cdf0e10cSrcweir         /// extract unary double value from Any
extractValue(double & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr & rShape,const::basegfx::B2DVector & rSlideBounds)160cdf0e10cSrcweir         bool extractValue( double&						o_rValue,
161cdf0e10cSrcweir                            const uno::Any& 				rSourceAny,
162cdf0e10cSrcweir                            const ShapeSharedPtr&		rShape,
163cdf0e10cSrcweir                            const ::basegfx::B2DVector&	rSlideBounds )
164cdf0e10cSrcweir         {
165cdf0e10cSrcweir             // try to extract numeric value (double, or smaller POD, like float or int)
166cdf0e10cSrcweir             if( (rSourceAny >>= o_rValue) )
167cdf0e10cSrcweir             {
168cdf0e10cSrcweir                 // succeeded
169cdf0e10cSrcweir                 return true;
170cdf0e10cSrcweir             }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir             // try to extract string
173cdf0e10cSrcweir             ::rtl::OUString aString;
174cdf0e10cSrcweir             if( !(rSourceAny >>= aString) )
175cdf0e10cSrcweir                 return false; // nothing left to try
176cdf0e10cSrcweir 
177cdf0e10cSrcweir             // parse the string into an ExpressionNode
178cdf0e10cSrcweir             try
179cdf0e10cSrcweir             {
180cdf0e10cSrcweir                 // Parse string into ExpressionNode, eval node at time 0.0
181cdf0e10cSrcweir                 o_rValue = (*SmilFunctionParser::parseSmilValue(
182cdf0e10cSrcweir                                 aString,
183cdf0e10cSrcweir                                 calcRelativeShapeBounds(rSlideBounds,
184cdf0e10cSrcweir                                                         rShape->getBounds()) ))(0.0);
185cdf0e10cSrcweir             }
186cdf0e10cSrcweir             catch( ParseError& )
187cdf0e10cSrcweir             {
188cdf0e10cSrcweir                 return false;
189cdf0e10cSrcweir             }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir             return true;
192cdf0e10cSrcweir         }
193cdf0e10cSrcweir 
194cdf0e10cSrcweir         /// extract enum/constant group value from Any
extractValue(sal_Int32 & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr &,const::basegfx::B2DVector &)195cdf0e10cSrcweir         bool extractValue( sal_Int32&						o_rValue,
196cdf0e10cSrcweir                            const uno::Any& 					rSourceAny,
197cdf0e10cSrcweir                            const ShapeSharedPtr&			/*rShape*/,
198cdf0e10cSrcweir                            const ::basegfx::B2DVector&		/*rSlideBounds*/ )
199cdf0e10cSrcweir         {
200cdf0e10cSrcweir             // try to extract numeric value (int, or smaller POD, like byte)
201cdf0e10cSrcweir             if( (rSourceAny >>= o_rValue) )
202cdf0e10cSrcweir             {
203cdf0e10cSrcweir                 // succeeded
204cdf0e10cSrcweir                 return true;
205cdf0e10cSrcweir             }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir             // okay, no plain int. Maybe one of the domain-specific enums?
208cdf0e10cSrcweir             drawing::FillStyle eFillStyle;
209cdf0e10cSrcweir             if( (rSourceAny >>= eFillStyle) )
210cdf0e10cSrcweir             {
211cdf0e10cSrcweir                 o_rValue = sal::static_int_cast<sal_Int16>(eFillStyle);
212cdf0e10cSrcweir 
213cdf0e10cSrcweir                 // succeeded
214cdf0e10cSrcweir                 return true;
215cdf0e10cSrcweir             }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir             drawing::LineStyle eLineStyle;
218cdf0e10cSrcweir             if( (rSourceAny >>= eLineStyle) )
219cdf0e10cSrcweir             {
220cdf0e10cSrcweir                 o_rValue = sal::static_int_cast<sal_Int16>(eLineStyle);
221cdf0e10cSrcweir 
222cdf0e10cSrcweir                 // succeeded
223cdf0e10cSrcweir                 return true;
224cdf0e10cSrcweir             }
225cdf0e10cSrcweir 
226cdf0e10cSrcweir             awt::FontSlant eFontSlant;
227cdf0e10cSrcweir             if( (rSourceAny >>= eFontSlant) )
228cdf0e10cSrcweir             {
229cdf0e10cSrcweir                 o_rValue = sal::static_int_cast<sal_Int16>(eFontSlant);
230cdf0e10cSrcweir 
231cdf0e10cSrcweir                 // succeeded
232cdf0e10cSrcweir                 return true;
233cdf0e10cSrcweir             }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir             // nothing left to try. Failure
236cdf0e10cSrcweir             return false;
237cdf0e10cSrcweir         }
238cdf0e10cSrcweir 
239cdf0e10cSrcweir         /// extract enum/constant group value from Any
extractValue(sal_Int16 & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr & rShape,const::basegfx::B2DVector & rSlideBounds)240cdf0e10cSrcweir         bool extractValue( sal_Int16&						o_rValue,
241cdf0e10cSrcweir                            const uno::Any& 					rSourceAny,
242cdf0e10cSrcweir                            const ShapeSharedPtr&			rShape,
243cdf0e10cSrcweir                            const ::basegfx::B2DVector&		rSlideBounds )
244cdf0e10cSrcweir         {
245cdf0e10cSrcweir             sal_Int32 aValue;
246cdf0e10cSrcweir             if( !extractValue(aValue,rSourceAny,rShape,rSlideBounds) )
247cdf0e10cSrcweir                 return false;
248cdf0e10cSrcweir 
249cdf0e10cSrcweir             if( std::numeric_limits<sal_Int16>::max() < aValue ||
250cdf0e10cSrcweir                 std::numeric_limits<sal_Int16>::min() > aValue )
251cdf0e10cSrcweir             {
252cdf0e10cSrcweir                 return false;
253cdf0e10cSrcweir             }
254cdf0e10cSrcweir 
255cdf0e10cSrcweir             o_rValue = static_cast<sal_Int16>(aValue);
256cdf0e10cSrcweir 
257cdf0e10cSrcweir             return true;
258cdf0e10cSrcweir         }
259cdf0e10cSrcweir 
260cdf0e10cSrcweir         /// extract color value from Any
extractValue(RGBColor & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr &,const::basegfx::B2DVector &)261cdf0e10cSrcweir         bool extractValue( RGBColor&					o_rValue,
262cdf0e10cSrcweir                            const uno::Any& 				rSourceAny,
263cdf0e10cSrcweir                            const ShapeSharedPtr&		/*rShape*/,
264cdf0e10cSrcweir                            const ::basegfx::B2DVector&	/*rSlideBounds*/ )
265cdf0e10cSrcweir         {
266cdf0e10cSrcweir             // try to extract numeric value (double, or smaller POD, like float or int)
267cdf0e10cSrcweir             {
268cdf0e10cSrcweir                 double nTmp = 0;
269cdf0e10cSrcweir                 if( (rSourceAny >>= nTmp) )
270cdf0e10cSrcweir                 {
271cdf0e10cSrcweir                     sal_uInt32 aIntColor( static_cast< sal_uInt32 >(nTmp) );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir                     // TODO(F2): Handle color values correctly, here
274cdf0e10cSrcweir                     o_rValue = unoColor2RGBColor( aIntColor );
275cdf0e10cSrcweir 
276cdf0e10cSrcweir                     // succeeded
277cdf0e10cSrcweir                     return true;
278cdf0e10cSrcweir                 }
279cdf0e10cSrcweir             }
280cdf0e10cSrcweir 
281cdf0e10cSrcweir             // try double sequence
282cdf0e10cSrcweir             {
283cdf0e10cSrcweir                 uno::Sequence< double > aTmp;
284cdf0e10cSrcweir                 if( (rSourceAny >>= aTmp) )
285cdf0e10cSrcweir                 {
286cdf0e10cSrcweir                     ENSURE_OR_THROW( aTmp.getLength() == 3,
287cdf0e10cSrcweir                                       "extractValue(): inappropriate length for RGB color value" );
288cdf0e10cSrcweir 
289cdf0e10cSrcweir                     o_rValue = RGBColor( aTmp[0], aTmp[1], aTmp[2] );
290cdf0e10cSrcweir 
291cdf0e10cSrcweir                     // succeeded
292cdf0e10cSrcweir                     return true;
293cdf0e10cSrcweir                 }
294cdf0e10cSrcweir             }
295cdf0e10cSrcweir 
296cdf0e10cSrcweir             // try sal_Int32 sequence
297cdf0e10cSrcweir             {
298cdf0e10cSrcweir                 uno::Sequence< sal_Int32 > aTmp;
299cdf0e10cSrcweir                 if( (rSourceAny >>= aTmp) )
300cdf0e10cSrcweir                 {
301cdf0e10cSrcweir                     ENSURE_OR_THROW( aTmp.getLength() == 3,
302cdf0e10cSrcweir                                       "extractValue(): inappropriate length for RGB color value" );
303cdf0e10cSrcweir 
304cdf0e10cSrcweir                     // truncate to byte
305cdf0e10cSrcweir                     o_rValue = RGBColor( ::cppcanvas::makeColor(
306cdf0e10cSrcweir                                              static_cast<sal_uInt8>(aTmp[0]),
307cdf0e10cSrcweir                                              static_cast<sal_uInt8>(aTmp[1]),
308cdf0e10cSrcweir                                              static_cast<sal_uInt8>(aTmp[2]),
309cdf0e10cSrcweir                                              255 ) );
310cdf0e10cSrcweir 
311cdf0e10cSrcweir                     // succeeded
312cdf0e10cSrcweir                     return true;
313cdf0e10cSrcweir                 }
314cdf0e10cSrcweir             }
315cdf0e10cSrcweir 
316cdf0e10cSrcweir             // try sal_Int8 sequence
317cdf0e10cSrcweir             {
318cdf0e10cSrcweir                 uno::Sequence< sal_Int8 > aTmp;
319cdf0e10cSrcweir                 if( (rSourceAny >>= aTmp) )
320cdf0e10cSrcweir                 {
321cdf0e10cSrcweir                     ENSURE_OR_THROW( aTmp.getLength() == 3,
322cdf0e10cSrcweir                                       "extractValue(): inappropriate length for RGB color value" );
323cdf0e10cSrcweir 
324cdf0e10cSrcweir                     o_rValue = RGBColor( ::cppcanvas::makeColor( aTmp[0], aTmp[1], aTmp[2], 255 ) );
325cdf0e10cSrcweir 
326cdf0e10cSrcweir                     // succeeded
327cdf0e10cSrcweir                     return true;
328cdf0e10cSrcweir                 }
329cdf0e10cSrcweir             }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir             // try to extract string
332cdf0e10cSrcweir             ::rtl::OUString aString;
333cdf0e10cSrcweir             if( !(rSourceAny >>= aString) )
334cdf0e10cSrcweir                 return false; // nothing left to try
335cdf0e10cSrcweir 
336cdf0e10cSrcweir             // TODO(F2): Provide symbolic color values here
337cdf0e10cSrcweir             o_rValue = RGBColor( 0.5, 0.5, 0.5 );
338cdf0e10cSrcweir 
339cdf0e10cSrcweir             return true;
340cdf0e10cSrcweir         }
341cdf0e10cSrcweir 
342cdf0e10cSrcweir         /// extract color value from Any
extractValue(HSLColor & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr &,const::basegfx::B2DVector &)343cdf0e10cSrcweir         bool extractValue( HSLColor&					o_rValue,
344cdf0e10cSrcweir                            const uno::Any& 				rSourceAny,
345cdf0e10cSrcweir                            const ShapeSharedPtr&		/*rShape*/,
346cdf0e10cSrcweir                            const ::basegfx::B2DVector&	/*rSlideBounds*/ )
347cdf0e10cSrcweir         {
348cdf0e10cSrcweir             // try double sequence
349cdf0e10cSrcweir             {
350cdf0e10cSrcweir                 uno::Sequence< double > aTmp;
351cdf0e10cSrcweir                 if( (rSourceAny >>= aTmp) )
352cdf0e10cSrcweir                 {
353cdf0e10cSrcweir                     ENSURE_OR_THROW( aTmp.getLength() == 3,
354cdf0e10cSrcweir                                       "extractValue(): inappropriate length for HSL color value" );
355cdf0e10cSrcweir 
356cdf0e10cSrcweir                     o_rValue = HSLColor( aTmp[0], aTmp[1], aTmp[2] );
357cdf0e10cSrcweir 
358cdf0e10cSrcweir                     // succeeded
359cdf0e10cSrcweir                     return true;
360cdf0e10cSrcweir                 }
361cdf0e10cSrcweir             }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir             // try sal_Int8 sequence
364cdf0e10cSrcweir             {
365cdf0e10cSrcweir                 uno::Sequence< sal_Int8 > aTmp;
366cdf0e10cSrcweir                 if( (rSourceAny >>= aTmp) )
367cdf0e10cSrcweir                 {
368cdf0e10cSrcweir                     ENSURE_OR_THROW( aTmp.getLength() == 3,
369cdf0e10cSrcweir                                       "extractValue(): inappropriate length for HSL color value" );
370cdf0e10cSrcweir 
371cdf0e10cSrcweir                     o_rValue = HSLColor( aTmp[0]*360.0/255.0, aTmp[1]/255.0, aTmp[2]/255.0 );
372cdf0e10cSrcweir 
373cdf0e10cSrcweir                     // succeeded
374cdf0e10cSrcweir                     return true;
375cdf0e10cSrcweir                 }
376cdf0e10cSrcweir             }
377cdf0e10cSrcweir 
378cdf0e10cSrcweir             return false; // nothing left to try
379cdf0e10cSrcweir         }
380cdf0e10cSrcweir 
381cdf0e10cSrcweir         /// extract plain string from Any
extractValue(::rtl::OUString & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr &,const::basegfx::B2DVector &)382cdf0e10cSrcweir         bool extractValue( ::rtl::OUString&				o_rValue,
383cdf0e10cSrcweir                            const uno::Any& 				rSourceAny,
384cdf0e10cSrcweir                            const ShapeSharedPtr&		/*rShape*/,
385cdf0e10cSrcweir                            const ::basegfx::B2DVector&	/*rSlideBounds*/ )
386cdf0e10cSrcweir         {
387cdf0e10cSrcweir             // try to extract string
388cdf0e10cSrcweir             if( !(rSourceAny >>= o_rValue) )
389cdf0e10cSrcweir                 return false; // nothing left to try
390cdf0e10cSrcweir 
391cdf0e10cSrcweir             return true;
392cdf0e10cSrcweir         }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir         /// extract bool value from Any
extractValue(bool & o_rValue,const uno::Any & rSourceAny,const ShapeSharedPtr &,const::basegfx::B2DVector &)395cdf0e10cSrcweir         bool extractValue( bool&						o_rValue,
396cdf0e10cSrcweir                            const uno::Any& 				rSourceAny,
397cdf0e10cSrcweir                            const ShapeSharedPtr&		/*rShape*/,
398cdf0e10cSrcweir                            const ::basegfx::B2DVector&	/*rSlideBounds*/ )
399cdf0e10cSrcweir         {
400cdf0e10cSrcweir             sal_Bool nTmp = sal_Bool();
401cdf0e10cSrcweir             // try to extract bool value
402cdf0e10cSrcweir             if( (rSourceAny >>= nTmp) )
403cdf0e10cSrcweir             {
404cdf0e10cSrcweir                 o_rValue = nTmp;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir                 // succeeded
407cdf0e10cSrcweir                 return true;
408cdf0e10cSrcweir             }
409cdf0e10cSrcweir 
410cdf0e10cSrcweir             // try to extract string
411cdf0e10cSrcweir             ::rtl::OUString aString;
412cdf0e10cSrcweir             if( !(rSourceAny >>= aString) )
413cdf0e10cSrcweir                 return false; // nothing left to try
414cdf0e10cSrcweir 
415cdf0e10cSrcweir             // we also take the strings "true" and "false",
416cdf0e10cSrcweir             // as well as "on" and "off" here
417cdf0e10cSrcweir             if( aString.equalsIgnoreAsciiCaseAscii("true") ||
418cdf0e10cSrcweir                 aString.equalsIgnoreAsciiCaseAscii("on") )
419cdf0e10cSrcweir             {
420cdf0e10cSrcweir                 o_rValue = true;
421cdf0e10cSrcweir                 return true;
422cdf0e10cSrcweir             }
423cdf0e10cSrcweir             if( aString.equalsIgnoreAsciiCaseAscii("false") ||
424cdf0e10cSrcweir                 aString.equalsIgnoreAsciiCaseAscii("off") )
425cdf0e10cSrcweir             {
426cdf0e10cSrcweir                 o_rValue = false;
427cdf0e10cSrcweir                 return true;
428cdf0e10cSrcweir             }
429cdf0e10cSrcweir 
430cdf0e10cSrcweir             // ultimately failed.
431cdf0e10cSrcweir             return false;
432cdf0e10cSrcweir         }
433cdf0e10cSrcweir 
434cdf0e10cSrcweir         /// extract double 2-tuple from Any
extractValue(::basegfx::B2DTuple & o_rPair,const uno::Any & rSourceAny,const ShapeSharedPtr & rShape,const::basegfx::B2DVector & rSlideBounds)435cdf0e10cSrcweir         bool extractValue( ::basegfx::B2DTuple&			o_rPair,
436cdf0e10cSrcweir                            const uno::Any& 				rSourceAny,
437cdf0e10cSrcweir                            const ShapeSharedPtr&		rShape,
438cdf0e10cSrcweir                            const ::basegfx::B2DVector&	rSlideBounds )
439cdf0e10cSrcweir         {
440cdf0e10cSrcweir             animations::ValuePair aPair;
441cdf0e10cSrcweir 
442cdf0e10cSrcweir             if( !(rSourceAny >>= aPair) )
443cdf0e10cSrcweir                 return false;
444cdf0e10cSrcweir 
445cdf0e10cSrcweir             double nFirst;
446cdf0e10cSrcweir             if( !extractValue( nFirst, aPair.First, rShape, rSlideBounds ) )
447cdf0e10cSrcweir                 return false;
448cdf0e10cSrcweir 
449cdf0e10cSrcweir             double nSecond;
450cdf0e10cSrcweir             if( !extractValue( nSecond, aPair.Second, rShape, rSlideBounds ) )
451cdf0e10cSrcweir                 return false;
452cdf0e10cSrcweir 
453cdf0e10cSrcweir             o_rPair.setX( nFirst );
454cdf0e10cSrcweir             o_rPair.setY( nSecond );
455cdf0e10cSrcweir 
456cdf0e10cSrcweir             return true;
457cdf0e10cSrcweir         }
458cdf0e10cSrcweir 
findNamedValue(uno::Sequence<beans::NamedValue> const & rSequence,const beans::NamedValue & rSearchKey)459cdf0e10cSrcweir         bool findNamedValue( uno::Sequence< beans::NamedValue > const& rSequence,
460cdf0e10cSrcweir                              const beans::NamedValue&				rSearchKey )
461cdf0e10cSrcweir         {
462cdf0e10cSrcweir             const beans::NamedValue* 	pArray = rSequence.getConstArray();
463cdf0e10cSrcweir             const size_t 				nLen( rSequence.getLength() );
464cdf0e10cSrcweir 
465cdf0e10cSrcweir             if( nLen == 0 )
466cdf0e10cSrcweir                 return false;
467cdf0e10cSrcweir 
468cdf0e10cSrcweir             const beans::NamedValue* pFound = ::std::find_if( pArray,
469cdf0e10cSrcweir                                                               pArray + nLen,
470cdf0e10cSrcweir                                                               NamedValueComparator( rSearchKey ) );
471cdf0e10cSrcweir 
472cdf0e10cSrcweir             if( pFound == pArray + nLen )
473cdf0e10cSrcweir                 return false;
474cdf0e10cSrcweir 
475cdf0e10cSrcweir             return true;
476cdf0e10cSrcweir         }
477cdf0e10cSrcweir 
findNamedValue(beans::NamedValue * o_pRet,const uno::Sequence<beans::NamedValue> & rSequence,const::rtl::OUString & rSearchString)478cdf0e10cSrcweir         bool findNamedValue( beans::NamedValue* 						o_pRet,
479cdf0e10cSrcweir                              const uno::Sequence< beans::NamedValue >& 	rSequence,
480cdf0e10cSrcweir                              const ::rtl::OUString&						rSearchString )
481cdf0e10cSrcweir         {
482cdf0e10cSrcweir             const beans::NamedValue* 	pArray = rSequence.getConstArray();
483cdf0e10cSrcweir             const size_t 				nLen( rSequence.getLength() );
484cdf0e10cSrcweir 
485cdf0e10cSrcweir             if( nLen == 0 )
486cdf0e10cSrcweir                 return false;
487cdf0e10cSrcweir 
488cdf0e10cSrcweir             const beans::NamedValue* pFound = ::std::find_if( pArray,
489cdf0e10cSrcweir                                                               pArray + nLen,
490cdf0e10cSrcweir                                                               NamedValueStringComparator( rSearchString ) );
491cdf0e10cSrcweir             if( pFound == pArray + nLen )
492cdf0e10cSrcweir                 return false;
493cdf0e10cSrcweir 
494cdf0e10cSrcweir             if( o_pRet )
495cdf0e10cSrcweir                 *o_pRet = *pFound;
496cdf0e10cSrcweir 
497cdf0e10cSrcweir             return true;
498cdf0e10cSrcweir         }
499cdf0e10cSrcweir 
calcRelativeShapeBounds(const basegfx::B2DVector & rPageSize,const basegfx::B2DRange & rShapeBounds)500cdf0e10cSrcweir         basegfx::B2DRange calcRelativeShapeBounds( const basegfx::B2DVector& rPageSize,
501cdf0e10cSrcweir                                                    const basegfx::B2DRange&  rShapeBounds )
502cdf0e10cSrcweir         {
503cdf0e10cSrcweir             return basegfx::B2DRange( rShapeBounds.getMinX() / rPageSize.getX(),
504cdf0e10cSrcweir                                       rShapeBounds.getMinY() / rPageSize.getY(),
505cdf0e10cSrcweir                                       rShapeBounds.getMaxX() / rPageSize.getX(),
506cdf0e10cSrcweir                                       rShapeBounds.getMaxY() / rPageSize.getY() );
507cdf0e10cSrcweir 		}
508cdf0e10cSrcweir 
509cdf0e10cSrcweir         // TODO(F2): Currently, the positional attributes DO NOT mirror the XShape properties.
510cdf0e10cSrcweir         // First and foremost, this is because we must operate with the shape boundrect,
511cdf0e10cSrcweir         // not position and size (the conversion between logic rect, snap rect and boundrect
512cdf0e10cSrcweir         // are non-trivial for draw shapes, and I won't duplicate them here). Thus, shapes
513cdf0e10cSrcweir         // rotated on the page will still have 0.0 rotation angle, as the metafile
514cdf0e10cSrcweir         // representation fetched over the API is our default zero case.
515cdf0e10cSrcweir 
getShapeTransformation(const::basegfx::B2DRectangle & rShapeBounds,const ShapeAttributeLayerSharedPtr & pAttr)516cdf0e10cSrcweir         ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle&		rShapeBounds,
517cdf0e10cSrcweir                                                         const ShapeAttributeLayerSharedPtr&	pAttr )
518cdf0e10cSrcweir         {
519cdf0e10cSrcweir             if( !pAttr )
520cdf0e10cSrcweir             {
521cdf0e10cSrcweir                 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(
522cdf0e10cSrcweir                     rShapeBounds.getWidth(), rShapeBounds.getHeight(),
523cdf0e10cSrcweir                     rShapeBounds.getMinX(), rShapeBounds.getMinY()));
524cdf0e10cSrcweir 
525cdf0e10cSrcweir                 return aTransform;
526cdf0e10cSrcweir             }
527cdf0e10cSrcweir             else
528cdf0e10cSrcweir             {
529cdf0e10cSrcweir                 return getAttributedShapeTransformation( rShapeBounds,
530cdf0e10cSrcweir                                                          pAttr );
531cdf0e10cSrcweir             }
532cdf0e10cSrcweir         }
533cdf0e10cSrcweir 
getSpriteTransformation(const::basegfx::B2DVector & rPixelSize,const::basegfx::B2DVector & rOrigSize,const ShapeAttributeLayerSharedPtr & pAttr)534cdf0e10cSrcweir         ::basegfx::B2DHomMatrix getSpriteTransformation( const ::basegfx::B2DVector&			rPixelSize,
535cdf0e10cSrcweir                                                          const ::basegfx::B2DVector&			rOrigSize,
536cdf0e10cSrcweir                                                          const ShapeAttributeLayerSharedPtr&	pAttr )
537cdf0e10cSrcweir         {
538cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aTransform;
539cdf0e10cSrcweir 
540cdf0e10cSrcweir             if( pAttr )
541cdf0e10cSrcweir             {
542cdf0e10cSrcweir                 const double nShearX( pAttr->isShearXAngleValid() ?
543cdf0e10cSrcweir                                       pAttr->getShearXAngle() :
544cdf0e10cSrcweir                                       0.0 );
545cdf0e10cSrcweir                 const double nShearY( pAttr->isShearYAngleValid() ?
546cdf0e10cSrcweir                                       pAttr->getShearYAngle() :
547cdf0e10cSrcweir                                       0.0 );
548cdf0e10cSrcweir                 const double nRotation( pAttr->isRotationAngleValid() ?
549cdf0e10cSrcweir                                         pAttr->getRotationAngle()*M_PI/180.0 :
550cdf0e10cSrcweir                                         0.0 );
551cdf0e10cSrcweir 
552cdf0e10cSrcweir                 // scale, shear and rotation pivot point is the
553cdf0e10cSrcweir                 // sprite's pixel center - adapt origin accordingly
554cdf0e10cSrcweir                 aTransform.translate( -0.5*rPixelSize.getX(),
555cdf0e10cSrcweir                                       -0.5*rPixelSize.getY() );
556cdf0e10cSrcweir 
557cdf0e10cSrcweir                 const ::basegfx::B2DSize aSize(
558cdf0e10cSrcweir                     pAttr->isWidthValid() ? pAttr->getWidth() : rOrigSize.getX(),
559cdf0e10cSrcweir                     pAttr->isHeightValid() ? pAttr->getHeight() : rOrigSize.getY() );
560cdf0e10cSrcweir 
561cdf0e10cSrcweir                 // ensure valid size (zero size will inevitably lead
562cdf0e10cSrcweir                 // to a singular transformation matrix).
563cdf0e10cSrcweir                 aTransform.scale( ::basegfx::pruneScaleValue(
564cdf0e10cSrcweir                                       aSize.getX() /
565cdf0e10cSrcweir                                       ::basegfx::pruneScaleValue(
566cdf0e10cSrcweir                                           rOrigSize.getX() ) ),
567cdf0e10cSrcweir                                   ::basegfx::pruneScaleValue(
568cdf0e10cSrcweir                                       aSize.getY() /
569cdf0e10cSrcweir                                       ::basegfx::pruneScaleValue(
570cdf0e10cSrcweir                                           rOrigSize.getY() ) ) );
571cdf0e10cSrcweir 
572cdf0e10cSrcweir                 const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
573cdf0e10cSrcweir                 const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
574cdf0e10cSrcweir                 const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );
575cdf0e10cSrcweir 
576cdf0e10cSrcweir                 if( bNeedRotation || bNeedShearX || bNeedShearY )
577cdf0e10cSrcweir                 {
578cdf0e10cSrcweir                     if( bNeedShearX )
579cdf0e10cSrcweir                         aTransform.shearX( nShearX );
580cdf0e10cSrcweir 
581cdf0e10cSrcweir                     if( bNeedShearY )
582cdf0e10cSrcweir                         aTransform.shearY( nShearY );
583cdf0e10cSrcweir 
584cdf0e10cSrcweir                     if( bNeedRotation )
585cdf0e10cSrcweir                         aTransform.rotate( nRotation );
586cdf0e10cSrcweir                 }
587cdf0e10cSrcweir 
588cdf0e10cSrcweir                 // move left, top corner back to original position of
589cdf0e10cSrcweir                 // the sprite (we've translated the center of the
590cdf0e10cSrcweir                 // sprite to the origin above).
591cdf0e10cSrcweir                 aTransform.translate( 0.5*rPixelSize.getX(),
592cdf0e10cSrcweir                                       0.5*rPixelSize.getY() );
593cdf0e10cSrcweir             }
594cdf0e10cSrcweir 
595cdf0e10cSrcweir             // return identity transform for un-attributed
596cdf0e10cSrcweir             // shapes. This renders the sprite as-is, in it's
597cdf0e10cSrcweir             // document-supplied size.
598cdf0e10cSrcweir             return aTransform;
599cdf0e10cSrcweir         }
600cdf0e10cSrcweir 
getShapeUpdateArea(const::basegfx::B2DRectangle & rUnitBounds,const::basegfx::B2DHomMatrix & rShapeTransform,const ShapeAttributeLayerSharedPtr & pAttr)601cdf0e10cSrcweir         ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&		rUnitBounds,
602cdf0e10cSrcweir                                                     const ::basegfx::B2DHomMatrix&		rShapeTransform,
603cdf0e10cSrcweir                                                     const ShapeAttributeLayerSharedPtr&	pAttr )
604cdf0e10cSrcweir         {
605cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aTransform;
606cdf0e10cSrcweir 
607cdf0e10cSrcweir             if( pAttr &&
608cdf0e10cSrcweir                 pAttr->isCharScaleValid() &&
609cdf0e10cSrcweir                 fabs(pAttr->getCharScale()) > 1.0 )
610cdf0e10cSrcweir             {
611cdf0e10cSrcweir                 // enlarge shape bounds. Have to consider the worst
612cdf0e10cSrcweir                 // case here (the text fully fills the shape)
613cdf0e10cSrcweir 
614cdf0e10cSrcweir                 const double nCharScale( pAttr->getCharScale() );
615cdf0e10cSrcweir 
616cdf0e10cSrcweir                 // center of scaling is the middle of the shape
617cdf0e10cSrcweir                 aTransform.translate( -0.5, -0.5 );
618cdf0e10cSrcweir                 aTransform.scale( nCharScale, nCharScale );
619cdf0e10cSrcweir                 aTransform.translate( 0.5, 0.5 );
620cdf0e10cSrcweir             }
621cdf0e10cSrcweir 
622cdf0e10cSrcweir             aTransform *= rShapeTransform;
623cdf0e10cSrcweir 
624cdf0e10cSrcweir             ::basegfx::B2DRectangle aRes;
625cdf0e10cSrcweir 
626cdf0e10cSrcweir             // apply shape transformation to unit rect
627cdf0e10cSrcweir             return ::canvas::tools::calcTransformedRectBounds(
628cdf0e10cSrcweir                 aRes,
629cdf0e10cSrcweir                 rUnitBounds,
630cdf0e10cSrcweir                 aTransform );
631cdf0e10cSrcweir         }
632cdf0e10cSrcweir 
getShapeUpdateArea(const::basegfx::B2DRange & rUnitBounds,const::basegfx::B2DRange & rShapeBounds)633cdf0e10cSrcweir         ::basegfx::B2DRange getShapeUpdateArea( const ::basegfx::B2DRange&		rUnitBounds,
634cdf0e10cSrcweir                                                     const ::basegfx::B2DRange&		rShapeBounds )
635cdf0e10cSrcweir         {
636cdf0e10cSrcweir             return ::basegfx::B2DRectangle(
637cdf0e10cSrcweir                 basegfx::tools::lerp( rShapeBounds.getMinX(),
638cdf0e10cSrcweir                                       rShapeBounds.getMaxX(),
639cdf0e10cSrcweir                                       rUnitBounds.getMinX() ),
640cdf0e10cSrcweir                 basegfx::tools::lerp( rShapeBounds.getMinY(),
641cdf0e10cSrcweir                                       rShapeBounds.getMaxY(),
642cdf0e10cSrcweir                                       rUnitBounds.getMinY() ),
643cdf0e10cSrcweir                 basegfx::tools::lerp( rShapeBounds.getMinX(),
644cdf0e10cSrcweir                                       rShapeBounds.getMaxX(),
645cdf0e10cSrcweir                                       rUnitBounds.getMaxX() ),
646cdf0e10cSrcweir                 basegfx::tools::lerp( rShapeBounds.getMinY(),
647cdf0e10cSrcweir                                       rShapeBounds.getMaxY(),
648cdf0e10cSrcweir                                       rUnitBounds.getMaxY() ) );
649cdf0e10cSrcweir         }
650cdf0e10cSrcweir 
getShapePosSize(const::basegfx::B2DRectangle & rOrigBounds,const ShapeAttributeLayerSharedPtr & pAttr)651cdf0e10cSrcweir         ::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle&			rOrigBounds,
652cdf0e10cSrcweir                                                  const ShapeAttributeLayerSharedPtr&	pAttr )
653cdf0e10cSrcweir         {
654cdf0e10cSrcweir             // an already empty shape bound need no further
655cdf0e10cSrcweir             // treatment. In fact, any changes applied below would
656cdf0e10cSrcweir             // actually remove the special empty state, thus, don't
657cdf0e10cSrcweir             // change!
658cdf0e10cSrcweir             if( !pAttr ||
659cdf0e10cSrcweir                 rOrigBounds.isEmpty() )
660cdf0e10cSrcweir             {
661cdf0e10cSrcweir                 return rOrigBounds;
662cdf0e10cSrcweir             }
663cdf0e10cSrcweir             else
664cdf0e10cSrcweir             {
665cdf0e10cSrcweir                 // cannot use maBounds anymore, attributes might have been
666cdf0e10cSrcweir                 // changed by now.
667cdf0e10cSrcweir                 // Have to use absolute values here, as negative sizes
668cdf0e10cSrcweir                 // (aka mirrored shapes) _still_ have the same bounds,
669cdf0e10cSrcweir                 // only with mirrored content.
670cdf0e10cSrcweir                 ::basegfx::B2DSize aSize;
671cdf0e10cSrcweir                 aSize.setX( fabs( pAttr->isWidthValid() ?
672cdf0e10cSrcweir                                   pAttr->getWidth() :
673cdf0e10cSrcweir                                   rOrigBounds.getWidth() ) );
674cdf0e10cSrcweir                 aSize.setY( fabs( pAttr->isHeightValid() ?
675cdf0e10cSrcweir                                   pAttr->getHeight() :
676cdf0e10cSrcweir                                   rOrigBounds.getHeight() ) );
677cdf0e10cSrcweir 
678cdf0e10cSrcweir                 ::basegfx::B2DPoint aPos;
679cdf0e10cSrcweir                 aPos.setX( pAttr->isPosXValid() ?
680cdf0e10cSrcweir                            pAttr->getPosX() :
681cdf0e10cSrcweir                            rOrigBounds.getCenterX() );
682cdf0e10cSrcweir                 aPos.setY( pAttr->isPosYValid() ?
683cdf0e10cSrcweir                            pAttr->getPosY() :
684cdf0e10cSrcweir                            rOrigBounds.getCenterY() );
685cdf0e10cSrcweir 
686cdf0e10cSrcweir                 // the positional attribute retrieved from the
687cdf0e10cSrcweir                 // ShapeAttributeLayer actually denotes the _middle_
688cdf0e10cSrcweir                 // of the shape (do it as the PPTs do...)
689cdf0e10cSrcweir                 return ::basegfx::B2DRectangle( aPos - 0.5*aSize,
690cdf0e10cSrcweir                                                 aPos + 0.5*aSize );
691cdf0e10cSrcweir             }
692cdf0e10cSrcweir         }
693cdf0e10cSrcweir 
unoColor2RGBColor(sal_Int32 nColor)694cdf0e10cSrcweir         RGBColor unoColor2RGBColor( sal_Int32 nColor )
695cdf0e10cSrcweir         {
696cdf0e10cSrcweir             return RGBColor(
697cdf0e10cSrcweir                 ::cppcanvas::makeColor(
698cdf0e10cSrcweir                     // convert from API color to IntSRGBA color
699cdf0e10cSrcweir                     // (0xAARRGGBB -> 0xRRGGBBAA)
700cdf0e10cSrcweir                     static_cast< sal_uInt8 >( nColor >> 16U ),
701cdf0e10cSrcweir                     static_cast< sal_uInt8 >( nColor >> 8U ),
702cdf0e10cSrcweir                     static_cast< sal_uInt8 >( nColor ),
703cdf0e10cSrcweir                     static_cast< sal_uInt8 >( nColor >> 24U ) ) );
704cdf0e10cSrcweir         }
705cdf0e10cSrcweir 
RGBAColor2UnoColor(::cppcanvas::Color::IntSRGBA aColor)706cdf0e10cSrcweir         sal_Int32 RGBAColor2UnoColor( ::cppcanvas::Color::IntSRGBA aColor )
707cdf0e10cSrcweir         {
708cdf0e10cSrcweir             return ::cppcanvas::makeColorARGB(
709cdf0e10cSrcweir                 // convert from IntSRGBA color to API color
710cdf0e10cSrcweir                 // (0xRRGGBBAA -> 0xAARRGGBB)
711cdf0e10cSrcweir                 static_cast< sal_uInt8 >(0),
712cdf0e10cSrcweir                 ::cppcanvas::getRed(aColor),
713cdf0e10cSrcweir                 ::cppcanvas::getGreen(aColor),
714cdf0e10cSrcweir                 ::cppcanvas::getBlue(aColor));
715cdf0e10cSrcweir         }
716cdf0e10cSrcweir 
717cdf0e10cSrcweir         /*sal_Int32 RGBAColor2UnoColor( ::cppcanvas::Color::IntSRGBA aColor )
718cdf0e10cSrcweir         {
719cdf0e10cSrcweir             return ::cppcanvas::unMakeColor(
720cdf0e10cSrcweir                                                     // convert from IntSRGBA color to API color
721cdf0e10cSrcweir                                                     // (0xRRGGBBAA -> 0xAARRGGBB)
722cdf0e10cSrcweir                                                     static_cast< sal_uInt8 >(0),
723cdf0e10cSrcweir                                                     ::cppcanvas::getRed(aColor),
724cdf0e10cSrcweir                                                     ::cppcanvas::getGreen(aColor),
725cdf0e10cSrcweir                                                     ::cppcanvas::getBlue(aColor));
726cdf0e10cSrcweir         }*/
727cdf0e10cSrcweir 
unSignedToSigned(sal_Int8 nInt)728cdf0e10cSrcweir         sal_Int8 unSignedToSigned(sal_Int8 nInt)
729cdf0e10cSrcweir         {
730cdf0e10cSrcweir             if(nInt < 0 ){
731cdf0e10cSrcweir                 sal_Int8 nInt2 = nInt >> 1U;
732cdf0e10cSrcweir                 return nInt2;
733cdf0e10cSrcweir             }else{
734cdf0e10cSrcweir                 return nInt;
735cdf0e10cSrcweir             }
736cdf0e10cSrcweir         }
737cdf0e10cSrcweir 
fillRect(const::cppcanvas::CanvasSharedPtr & rCanvas,const::basegfx::B2DRectangle & rRect,::cppcanvas::Color::IntSRGBA aFillColor)738cdf0e10cSrcweir         void fillRect( const ::cppcanvas::CanvasSharedPtr& rCanvas,
739cdf0e10cSrcweir                        const ::basegfx::B2DRectangle&	   rRect,
740cdf0e10cSrcweir                        ::cppcanvas::Color::IntSRGBA        aFillColor )
741cdf0e10cSrcweir         {
742cdf0e10cSrcweir             const ::basegfx::B2DPolygon aPoly(
743cdf0e10cSrcweir                 ::basegfx::tools::createPolygonFromRect( rRect ));
744cdf0e10cSrcweir 
745cdf0e10cSrcweir             ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
746cdf0e10cSrcweir                 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( rCanvas,
747cdf0e10cSrcweir                                                                               aPoly ) );
748cdf0e10cSrcweir 
749cdf0e10cSrcweir             if( pPolyPoly )
750cdf0e10cSrcweir             {
751cdf0e10cSrcweir                 pPolyPoly->setRGBAFillColor( aFillColor );
752cdf0e10cSrcweir                 pPolyPoly->draw();
753cdf0e10cSrcweir             }
754cdf0e10cSrcweir         }
755cdf0e10cSrcweir 
initSlideBackground(const::cppcanvas::CanvasSharedPtr & rCanvas,const::basegfx::B2ISize & rSize)756cdf0e10cSrcweir         void initSlideBackground( const ::cppcanvas::CanvasSharedPtr& rCanvas,
757cdf0e10cSrcweir                                   const ::basegfx::B2ISize&			  rSize )
758cdf0e10cSrcweir         {
759cdf0e10cSrcweir             ::cppcanvas::CanvasSharedPtr pCanvas( rCanvas->clone() );
760cdf0e10cSrcweir 
761cdf0e10cSrcweir             // set transformation to identitiy (->device pixel)
762cdf0e10cSrcweir             pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
763cdf0e10cSrcweir 
764cdf0e10cSrcweir             // #i42440# Fill the _full_ background in
765cdf0e10cSrcweir             // black. Since we had to extend the bitmap by one
766cdf0e10cSrcweir             // pixel, and the bitmap is initialized white,
767cdf0e10cSrcweir             // depending on the slide content a one pixel wide
768cdf0e10cSrcweir             // line will show to the bottom and the right.
769cdf0e10cSrcweir             fillRect( pCanvas,
770cdf0e10cSrcweir                       ::basegfx::B2DRectangle( 0.0, 0.0,
771cdf0e10cSrcweir                                                rSize.getX(),
772cdf0e10cSrcweir                                                rSize.getY() ),
773cdf0e10cSrcweir                       0x000000FFU );
774cdf0e10cSrcweir 
775cdf0e10cSrcweir             // fill the bounds rectangle in white. Subtract one pixel
776cdf0e10cSrcweir             // from both width and height, because the slide size is
777cdf0e10cSrcweir             // chosen one pixel larger than given by the drawing
778cdf0e10cSrcweir             // layer. This is because shapes with line style, that
779cdf0e10cSrcweir             // have the size of the slide would otherwise be cut
780cdf0e10cSrcweir             // off. OTOH, every other slide background (solid fill,
781cdf0e10cSrcweir             // gradient, bitmap) render one pixel less, thus revealing
782cdf0e10cSrcweir             // ugly white pixel to the right and the bottom.
783cdf0e10cSrcweir             fillRect( pCanvas,
784cdf0e10cSrcweir                       ::basegfx::B2DRectangle( 0.0, 0.0,
785cdf0e10cSrcweir                                                rSize.getX()-1,
786cdf0e10cSrcweir                                                rSize.getY()-1 ),
787cdf0e10cSrcweir                       0xFFFFFFFFU );
788cdf0e10cSrcweir         }
789cdf0e10cSrcweir 
getAPIShapeBounds(const uno::Reference<drawing::XShape> & xShape)790cdf0e10cSrcweir         ::basegfx::B2DRectangle getAPIShapeBounds( const uno::Reference< drawing::XShape >& xShape )
791cdf0e10cSrcweir         {
792cdf0e10cSrcweir             uno::Reference< beans::XPropertySet > xPropSet( xShape,
793cdf0e10cSrcweir                                                             uno::UNO_QUERY_THROW );
794cdf0e10cSrcweir             // read bound rect
795cdf0e10cSrcweir             awt::Rectangle aTmpRect;
796cdf0e10cSrcweir             if( !(xPropSet->getPropertyValue(
797cdf0e10cSrcweir                       ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BoundRect") ) ) >>= aTmpRect) )
798cdf0e10cSrcweir             {
799cdf0e10cSrcweir                 ENSURE_OR_THROW( false,
800cdf0e10cSrcweir                                   "getAPIShapeBounds(): Could not get \"BoundRect\" property from shape" );
801cdf0e10cSrcweir             }
802cdf0e10cSrcweir 
803cdf0e10cSrcweir             return ::basegfx::B2DRectangle( aTmpRect.X,
804cdf0e10cSrcweir                                             aTmpRect.Y,
805cdf0e10cSrcweir                                             aTmpRect.X+aTmpRect.Width,
806cdf0e10cSrcweir                                             aTmpRect.Y+aTmpRect.Height );
807cdf0e10cSrcweir         }
808cdf0e10cSrcweir 
getAPIShapePrio(const uno::Reference<drawing::XShape> & xShape)809cdf0e10cSrcweir         double getAPIShapePrio( const uno::Reference< drawing::XShape >& xShape )
810cdf0e10cSrcweir         {
811cdf0e10cSrcweir             uno::Reference< beans::XPropertySet > xPropSet( xShape,
812cdf0e10cSrcweir                                                             uno::UNO_QUERY_THROW );
813cdf0e10cSrcweir             // read prio
814cdf0e10cSrcweir             sal_Int32 nPrio(0);
815cdf0e10cSrcweir             if( !(xPropSet->getPropertyValue(
816cdf0e10cSrcweir                       ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ZOrder") ) ) >>= nPrio) )
817cdf0e10cSrcweir             {
818cdf0e10cSrcweir                 ENSURE_OR_THROW( false,
819cdf0e10cSrcweir                                   "getAPIShapePrio(): Could not get \"ZOrder\" property from shape" );
820cdf0e10cSrcweir             }
821cdf0e10cSrcweir 
822cdf0e10cSrcweir             // TODO(F2): Check and adapt the range of possible values here.
823cdf0e10cSrcweir             // Maybe we can also take the total number of shapes here
824cdf0e10cSrcweir             return nPrio / 65535.0;
825cdf0e10cSrcweir         }
826cdf0e10cSrcweir 
getSlideSizePixel(const basegfx::B2DVector & rSlideSize,const UnoViewSharedPtr & pView)827cdf0e10cSrcweir         basegfx::B2IVector getSlideSizePixel( const basegfx::B2DVector& rSlideSize,
828cdf0e10cSrcweir                                               const UnoViewSharedPtr&   pView )
829cdf0e10cSrcweir         {
830cdf0e10cSrcweir             ENSURE_OR_THROW(pView, "getSlideSizePixel(): invalid view");
831cdf0e10cSrcweir 
832cdf0e10cSrcweir             // determine transformed page bounds
833cdf0e10cSrcweir             const basegfx::B2DRange aRect( 0,0,
834cdf0e10cSrcweir                                            rSlideSize.getX(),
835cdf0e10cSrcweir                                            rSlideSize.getY() );
836cdf0e10cSrcweir             basegfx::B2DRange aTmpRect;
837cdf0e10cSrcweir             canvas::tools::calcTransformedRectBounds( aTmpRect,
838cdf0e10cSrcweir                                                       aRect,
839cdf0e10cSrcweir                                                       pView->getTransformation() );
840cdf0e10cSrcweir 
841cdf0e10cSrcweir             // #i42440# Returned slide size is one pixel too small, as
842cdf0e10cSrcweir             // rendering happens one pixel to the right and below the
843cdf0e10cSrcweir             // actual bound rect.
844cdf0e10cSrcweir             return basegfx::B2IVector(
845cdf0e10cSrcweir                 basegfx::fround( aTmpRect.getRange().getX() ) + 1,
846cdf0e10cSrcweir                 basegfx::fround( aTmpRect.getRange().getY() ) + 1 );
847cdf0e10cSrcweir         }
848cdf0e10cSrcweir     }
849cdf0e10cSrcweir }
850