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