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 // must be first 32*cdf0e10cSrcweir #include <canvas/debug.hxx> 33*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 34*cdf0e10cSrcweir #include <gdimtftools.hxx> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #include <com/sun/star/document/XExporter.hpp> 37*cdf0e10cSrcweir #include <com/sun/star/document/XFilter.hpp> 38*cdf0e10cSrcweir #include <com/sun/star/graphic/XGraphic.hpp> 39*cdf0e10cSrcweir #include <com/sun/star/graphic/XGraphicRenderer.hpp> 40*cdf0e10cSrcweir #include <com/sun/star/drawing/XShape.hpp> 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir #include <cppuhelper/basemutex.hxx> 43*cdf0e10cSrcweir #include <cppuhelper/compbase1.hxx> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #include <comphelper/uno3.hxx> 46*cdf0e10cSrcweir #include <cppuhelper/implbase1.hxx> 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir #include <tools/stream.hxx> 49*cdf0e10cSrcweir #include <vcl/svapp.hxx> 50*cdf0e10cSrcweir #include <vcl/canvastools.hxx> 51*cdf0e10cSrcweir #include <vcl/metaact.hxx> 52*cdf0e10cSrcweir #include <vcl/virdev.hxx> 53*cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 54*cdf0e10cSrcweir #include <vcl/metaact.hxx> 55*cdf0e10cSrcweir #include <vcl/animate.hxx> 56*cdf0e10cSrcweir #include <vcl/graph.hxx> 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir #include <unotools/streamwrap.hxx> 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir #include "tools.hxx" 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir using namespace ::com::sun::star; 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir // free support functions 66*cdf0e10cSrcweir // ====================== 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir namespace slideshow 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir namespace internal 71*cdf0e10cSrcweir { 72*cdf0e10cSrcweir // TODO(E2): Detect the case when svx/drawing layer is not 73*cdf0e10cSrcweir // in-process, or even not on the same machine, and 74*cdf0e10cSrcweir // fallback to metafile streaming! 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir // For fixing #i48102#, have to be a _lot_ more selective 77*cdf0e10cSrcweir // on which metafiles to convert to bitmaps. The problem 78*cdf0e10cSrcweir // here is that we _always_ get the shape content as a 79*cdf0e10cSrcweir // metafile, even if we have a bitmap graphic shape. Thus, 80*cdf0e10cSrcweir // calling GetBitmapEx on such a Graphic (see below) will 81*cdf0e10cSrcweir // result in one poorly scaled bitmap into another, 82*cdf0e10cSrcweir // somewhat arbitrarily sized bitmap. 83*cdf0e10cSrcweir bool hasUnsupportedActions( const GDIMetaFile& rMtf ) 84*cdf0e10cSrcweir { 85*cdf0e10cSrcweir // search metafile for RasterOp action 86*cdf0e10cSrcweir MetaAction* pCurrAct; 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir // TODO(Q3): avoid const-cast 89*cdf0e10cSrcweir for( pCurrAct = const_cast<GDIMetaFile&>(rMtf).FirstAction(); 90*cdf0e10cSrcweir pCurrAct; 91*cdf0e10cSrcweir pCurrAct = const_cast<GDIMetaFile&>(rMtf).NextAction() ) 92*cdf0e10cSrcweir { 93*cdf0e10cSrcweir switch( pCurrAct->GetType() ) 94*cdf0e10cSrcweir { 95*cdf0e10cSrcweir case META_RASTEROP_ACTION: 96*cdf0e10cSrcweir // overpaint is okay - that's the default, anyway 97*cdf0e10cSrcweir if( ROP_OVERPAINT == 98*cdf0e10cSrcweir static_cast<MetaRasterOpAction*>(pCurrAct)->GetRasterOp() ) 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir break; 101*cdf0e10cSrcweir } 102*cdf0e10cSrcweir // FALLTHROUGH intended 103*cdf0e10cSrcweir case META_MOVECLIPREGION_ACTION: 104*cdf0e10cSrcweir // FALLTHROUGH intended 105*cdf0e10cSrcweir case META_REFPOINT_ACTION: 106*cdf0e10cSrcweir // FALLTHROUGH intended 107*cdf0e10cSrcweir case META_WALLPAPER_ACTION: 108*cdf0e10cSrcweir return true; // at least one unsupported 109*cdf0e10cSrcweir // action encountered 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir } 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir return false; // no unsupported action found 114*cdf0e10cSrcweir } 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir namespace { 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir typedef ::cppu::WeakComponentImplHelper1< graphic::XGraphicRenderer > DummyRenderer_Base; 119*cdf0e10cSrcweir 120*cdf0e10cSrcweir class DummyRenderer : 121*cdf0e10cSrcweir public DummyRenderer_Base, 122*cdf0e10cSrcweir public cppu::BaseMutex 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir public: 125*cdf0e10cSrcweir DummyRenderer() : 126*cdf0e10cSrcweir DummyRenderer_Base( m_aMutex ), 127*cdf0e10cSrcweir mxGraphic() 128*cdf0e10cSrcweir { 129*cdf0e10cSrcweir } 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir //--- XGraphicRenderer ----------------------------------- 132*cdf0e10cSrcweir virtual void SAL_CALL render( const uno::Reference< graphic::XGraphic >& rGraphic ) throw (uno::RuntimeException) 133*cdf0e10cSrcweir { 134*cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 135*cdf0e10cSrcweir mxGraphic = rGraphic; 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir /** Retrieve GDIMetaFile from renderer 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir @param bForeignSource 141*cdf0e10cSrcweir When true, the source of the metafile might be a 142*cdf0e10cSrcweir foreign application. The metafile is checked 143*cdf0e10cSrcweir against unsupported content, and, if necessary, 144*cdf0e10cSrcweir returned as a pre-rendererd bitmap. 145*cdf0e10cSrcweir */ 146*cdf0e10cSrcweir GDIMetaFile getMtf( bool bForeignSource ) const 147*cdf0e10cSrcweir { 148*cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir Graphic aGraphic( mxGraphic ); 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir if( aGraphic.GetType() == GRAPHIC_BITMAP || 153*cdf0e10cSrcweir (bForeignSource && 154*cdf0e10cSrcweir hasUnsupportedActions(aGraphic.GetGDIMetaFile()) ) ) 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir // wrap bitmap into GDIMetafile 157*cdf0e10cSrcweir GDIMetaFile aMtf; 158*cdf0e10cSrcweir ::Point aEmptyPoint; 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir ::BitmapEx aBmpEx( aGraphic.GetBitmapEx() ); 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir aMtf.AddAction( new MetaBmpExAction( aEmptyPoint, 163*cdf0e10cSrcweir aBmpEx ) ); 164*cdf0e10cSrcweir aMtf.SetPrefSize( aBmpEx.GetPrefSize() ); 165*cdf0e10cSrcweir aMtf.SetPrefMapMode( aBmpEx.GetPrefMapMode() ); 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir return aMtf; 168*cdf0e10cSrcweir } 169*cdf0e10cSrcweir else 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir return aGraphic.GetGDIMetaFile(); 172*cdf0e10cSrcweir } 173*cdf0e10cSrcweir } 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir private: 176*cdf0e10cSrcweir uno::Reference< graphic::XGraphic > mxGraphic; 177*cdf0e10cSrcweir }; 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir } // anon namespace 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir // Quick'n'dirty way: tunnel Graphic (only works for 182*cdf0e10cSrcweir // in-process slideshow, of course) 183*cdf0e10cSrcweir bool getMetaFile( const uno::Reference< lang::XComponent >& xSource, 184*cdf0e10cSrcweir const uno::Reference< drawing::XDrawPage >& xContainingPage, 185*cdf0e10cSrcweir GDIMetaFile& rMtf, 186*cdf0e10cSrcweir int mtfLoadFlags, 187*cdf0e10cSrcweir const uno::Reference< uno::XComponentContext >& rxContext ) 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE( rxContext.is(), 190*cdf0e10cSrcweir "getMetaFile(): Invalid context" ); 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir // create dummy XGraphicRenderer, which receives the 193*cdf0e10cSrcweir // generated XGraphic from the GraphicExporter 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir // TODO(P3): Move creation of DummyRenderer out of the 196*cdf0e10cSrcweir // loop! Either by making it static, or transforming 197*cdf0e10cSrcweir // the whole thing here into a class. 198*cdf0e10cSrcweir DummyRenderer* pRenderer( new DummyRenderer() ); 199*cdf0e10cSrcweir uno::Reference< graphic::XGraphicRenderer > xRenderer( pRenderer ); 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir // -> stuff that into UnoGraphicExporter. 202*cdf0e10cSrcweir uno::Reference<lang::XMultiComponentFactory> xFactory( 203*cdf0e10cSrcweir rxContext->getServiceManager() ); 204*cdf0e10cSrcweir 205*cdf0e10cSrcweir OSL_ENSURE( xFactory.is(), "### no UNO?!" ); 206*cdf0e10cSrcweir if( !xFactory.is() ) 207*cdf0e10cSrcweir return false; 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir // creating the graphic exporter 210*cdf0e10cSrcweir uno::Reference< document::XExporter > xExporter( 211*cdf0e10cSrcweir xFactory->createInstanceWithContext( 212*cdf0e10cSrcweir OUSTR("com.sun.star.drawing.GraphicExportFilter"), 213*cdf0e10cSrcweir rxContext), 214*cdf0e10cSrcweir uno::UNO_QUERY ); 215*cdf0e10cSrcweir uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY ); 216*cdf0e10cSrcweir 217*cdf0e10cSrcweir OSL_ENSURE( xExporter.is() && xFilter.is(), "### no graphic exporter?!" ); 218*cdf0e10cSrcweir if( !xExporter.is() || !xFilter.is() ) 219*cdf0e10cSrcweir return false; 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir uno::Sequence< beans::PropertyValue > aProps(3); 222*cdf0e10cSrcweir aProps[0].Name = OUSTR("FilterName"); 223*cdf0e10cSrcweir aProps[0].Value <<= OUSTR("SVM"); 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir aProps[1].Name = OUSTR("GraphicRenderer"); 226*cdf0e10cSrcweir aProps[1].Value <<= xRenderer; 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir uno::Sequence< beans::PropertyValue > aFilterData(5); 229*cdf0e10cSrcweir aFilterData[0].Name = OUSTR("VerboseComments"); 230*cdf0e10cSrcweir aFilterData[0].Value <<= ((mtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0); 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir aFilterData[1].Name = OUSTR("ScrollText"); 233*cdf0e10cSrcweir aFilterData[1].Value <<= ((mtfLoadFlags & MTF_LOAD_SCROLL_TEXT_MTF) != 0); 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir aFilterData[2].Name = OUSTR("ExportOnlyBackground"); 236*cdf0e10cSrcweir aFilterData[2].Value <<= ((mtfLoadFlags & MTF_LOAD_BACKGROUND_ONLY) != 0); 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir aFilterData[3].Name = OUSTR("Version"); 239*cdf0e10cSrcweir aFilterData[3].Value <<= static_cast<sal_Int32>( SOFFICE_FILEFORMAT_50 ); 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir aFilterData[4].Name = OUSTR("CurrentPage"); 242*cdf0e10cSrcweir aFilterData[4].Value <<= uno::Reference< uno::XInterface >( xContainingPage, 243*cdf0e10cSrcweir uno::UNO_QUERY_THROW ); 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir aProps[2].Name = OUSTR("FilterData"); 246*cdf0e10cSrcweir aProps[2].Value <<= aFilterData; 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir xExporter->setSourceDocument( xSource ); 249*cdf0e10cSrcweir if( !xFilter->filter( aProps ) ) 250*cdf0e10cSrcweir return false; 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir rMtf = pRenderer->getMtf( (mtfLoadFlags & MTF_LOAD_FOREIGN_SOURCE) != 0 ); 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir // pRenderer is automatically destroyed when xRenderer 255*cdf0e10cSrcweir // goes out of scope 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir // TODO(E3): Error handling. Exporter might have 258*cdf0e10cSrcweir // generated nothing, a bitmap, threw an exception, 259*cdf0e10cSrcweir // whatever. 260*cdf0e10cSrcweir return true; 261*cdf0e10cSrcweir } 262*cdf0e10cSrcweir 263*cdf0e10cSrcweir void removeTextActions( GDIMetaFile& rMtf ) 264*cdf0e10cSrcweir { 265*cdf0e10cSrcweir // search metafile for text output 266*cdf0e10cSrcweir MetaAction* pCurrAct; 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir int nActionIndex(0); 269*cdf0e10cSrcweir pCurrAct = rMtf.FirstAction(); 270*cdf0e10cSrcweir while( pCurrAct ) 271*cdf0e10cSrcweir { 272*cdf0e10cSrcweir switch( pCurrAct->GetType() ) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir case META_TEXTCOLOR_ACTION: 275*cdf0e10cSrcweir case META_TEXTFILLCOLOR_ACTION: 276*cdf0e10cSrcweir case META_TEXTLINECOLOR_ACTION: 277*cdf0e10cSrcweir case META_TEXTALIGN_ACTION: 278*cdf0e10cSrcweir case META_FONT_ACTION: 279*cdf0e10cSrcweir case META_LAYOUTMODE_ACTION: 280*cdf0e10cSrcweir case META_TEXT_ACTION: 281*cdf0e10cSrcweir case META_TEXTARRAY_ACTION: 282*cdf0e10cSrcweir case META_TEXTRECT_ACTION: 283*cdf0e10cSrcweir case META_STRETCHTEXT_ACTION: 284*cdf0e10cSrcweir case META_TEXTLINE_ACTION: 285*cdf0e10cSrcweir { 286*cdf0e10cSrcweir // remove every text-related actions 287*cdf0e10cSrcweir pCurrAct = rMtf.NextAction(); 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir rMtf.RemoveAction( nActionIndex ); 290*cdf0e10cSrcweir break; 291*cdf0e10cSrcweir } 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir default: 294*cdf0e10cSrcweir pCurrAct = rMtf.NextAction(); 295*cdf0e10cSrcweir ++nActionIndex; 296*cdf0e10cSrcweir break; 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir sal_Int32 getNextActionOffset( MetaAction * pCurrAct ) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir // Special handling for actions that represent 304*cdf0e10cSrcweir // more than one indexable action 305*cdf0e10cSrcweir // =========================================== 306*cdf0e10cSrcweir 307*cdf0e10cSrcweir switch (pCurrAct->GetType()) { 308*cdf0e10cSrcweir case META_TEXT_ACTION: { 309*cdf0e10cSrcweir MetaTextAction * pAct = static_cast<MetaTextAction *>(pCurrAct); 310*cdf0e10cSrcweir return (pAct->GetLen() == (sal_uInt16)STRING_LEN 311*cdf0e10cSrcweir ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen()); 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir case META_TEXTARRAY_ACTION: { 314*cdf0e10cSrcweir MetaTextArrayAction * pAct = 315*cdf0e10cSrcweir static_cast<MetaTextArrayAction *>(pCurrAct); 316*cdf0e10cSrcweir return (pAct->GetLen() == (sal_uInt16)STRING_LEN 317*cdf0e10cSrcweir ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen()); 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir case META_STRETCHTEXT_ACTION: { 320*cdf0e10cSrcweir MetaStretchTextAction * pAct = 321*cdf0e10cSrcweir static_cast<MetaStretchTextAction *>(pCurrAct); 322*cdf0e10cSrcweir return (pAct->GetLen() == (sal_uInt16)STRING_LEN 323*cdf0e10cSrcweir ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen()); 324*cdf0e10cSrcweir } 325*cdf0e10cSrcweir case META_FLOATTRANSPARENT_ACTION: { 326*cdf0e10cSrcweir MetaFloatTransparentAction * pAct = 327*cdf0e10cSrcweir static_cast<MetaFloatTransparentAction*>(pCurrAct); 328*cdf0e10cSrcweir // TODO(F2): Recurse into action metafile 329*cdf0e10cSrcweir // (though this is currently not used from the 330*cdf0e10cSrcweir // DrawingLayer - shape transparency gradients 331*cdf0e10cSrcweir // don't affect shape text) 332*cdf0e10cSrcweir return pAct->GetGDIMetaFile().GetActionCount(); 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir default: 335*cdf0e10cSrcweir return 1; 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir } 338*cdf0e10cSrcweir 339*cdf0e10cSrcweir bool getAnimationFromGraphic( VectorOfMtfAnimationFrames& o_rFrames, 340*cdf0e10cSrcweir ::std::size_t& o_rLoopCount, 341*cdf0e10cSrcweir CycleMode& o_eCycleMode, 342*cdf0e10cSrcweir const Graphic& rGraphic ) 343*cdf0e10cSrcweir { 344*cdf0e10cSrcweir o_rFrames.clear(); 345*cdf0e10cSrcweir 346*cdf0e10cSrcweir if( !rGraphic.IsAnimated() ) 347*cdf0e10cSrcweir return false; 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir // some loop invariants 350*cdf0e10cSrcweir Animation aAnimation( rGraphic.GetAnimation() ); 351*cdf0e10cSrcweir const Point aEmptyPoint; 352*cdf0e10cSrcweir const Size aAnimSize( aAnimation.GetDisplaySizePixel() ); 353*cdf0e10cSrcweir 354*cdf0e10cSrcweir // setup VDev, into which all bitmaps are painted (want to 355*cdf0e10cSrcweir // normalize animations to n bitmaps of same size. An Animation, 356*cdf0e10cSrcweir // though, can contain bitmaps of varying sizes and different 357*cdf0e10cSrcweir // update modes) 358*cdf0e10cSrcweir VirtualDevice aVDev; 359*cdf0e10cSrcweir aVDev.SetOutputSizePixel( aAnimSize ); 360*cdf0e10cSrcweir aVDev.EnableMapMode( sal_False ); 361*cdf0e10cSrcweir 362*cdf0e10cSrcweir // setup mask VDev (alpha VDev is currently rather slow) 363*cdf0e10cSrcweir VirtualDevice aVDevMask; 364*cdf0e10cSrcweir aVDevMask.SetOutputSizePixel( aAnimSize ); 365*cdf0e10cSrcweir aVDevMask.EnableMapMode( sal_False ); 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir switch( aAnimation.GetCycleMode() ) 368*cdf0e10cSrcweir { 369*cdf0e10cSrcweir case CYCLE_NOT: 370*cdf0e10cSrcweir o_rLoopCount = 1; 371*cdf0e10cSrcweir o_eCycleMode = CYCLE_LOOP; 372*cdf0e10cSrcweir break; 373*cdf0e10cSrcweir 374*cdf0e10cSrcweir case CYCLE_FALLBACK: 375*cdf0e10cSrcweir // FALLTHROUGH intended 376*cdf0e10cSrcweir case CYCLE_NORMAL: 377*cdf0e10cSrcweir o_rLoopCount = aAnimation.GetLoopCount(); 378*cdf0e10cSrcweir o_eCycleMode = CYCLE_LOOP; 379*cdf0e10cSrcweir break; 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir case CYCLE_REVERS: 382*cdf0e10cSrcweir // FALLTHROUGH intended 383*cdf0e10cSrcweir case CYCLE_REVERS_FALLBACK: 384*cdf0e10cSrcweir o_rLoopCount = aAnimation.GetLoopCount(); 385*cdf0e10cSrcweir o_eCycleMode = CYCLE_PINGPONGLOOP; 386*cdf0e10cSrcweir break; 387*cdf0e10cSrcweir 388*cdf0e10cSrcweir default: 389*cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE(false, 390*cdf0e10cSrcweir "getAnimationFromGraphic(): Unexpected case" ); 391*cdf0e10cSrcweir break; 392*cdf0e10cSrcweir } 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir for( sal_uInt16 i=0, nCount=aAnimation.Count(); i<nCount; ++i ) 395*cdf0e10cSrcweir { 396*cdf0e10cSrcweir const AnimationBitmap& rAnimBmp( aAnimation.Get(i) ); 397*cdf0e10cSrcweir switch(rAnimBmp.eDisposal) 398*cdf0e10cSrcweir { 399*cdf0e10cSrcweir case DISPOSE_NOT: 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir aVDev.DrawBitmapEx(rAnimBmp.aPosPix, 402*cdf0e10cSrcweir rAnimBmp.aBmpEx); 403*cdf0e10cSrcweir Bitmap aMask = rAnimBmp.aBmpEx.GetMask(); 404*cdf0e10cSrcweir 405*cdf0e10cSrcweir if( aMask.IsEmpty() ) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir const Point aEmpty; 408*cdf0e10cSrcweir const Rectangle aRect(aEmptyPoint, 409*cdf0e10cSrcweir aVDevMask.GetOutputSizePixel()); 410*cdf0e10cSrcweir const Wallpaper aWallpaper(COL_BLACK); 411*cdf0e10cSrcweir aVDevMask.DrawWallpaper(aRect, 412*cdf0e10cSrcweir aWallpaper); 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir else 415*cdf0e10cSrcweir { 416*cdf0e10cSrcweir BitmapEx aTmpMask = BitmapEx(aMask, 417*cdf0e10cSrcweir aMask); 418*cdf0e10cSrcweir aVDevMask.DrawBitmapEx(rAnimBmp.aPosPix, 419*cdf0e10cSrcweir aTmpMask ); 420*cdf0e10cSrcweir } 421*cdf0e10cSrcweir break; 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir case DISPOSE_BACK: 425*cdf0e10cSrcweir { 426*cdf0e10cSrcweir // #i70772# react on no mask 427*cdf0e10cSrcweir const Bitmap aMask(rAnimBmp.aBmpEx.GetMask()); 428*cdf0e10cSrcweir const Bitmap aContent(rAnimBmp.aBmpEx.GetBitmap()); 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir aVDevMask.Erase(); 431*cdf0e10cSrcweir aVDev.DrawBitmap(rAnimBmp.aPosPix, aContent); 432*cdf0e10cSrcweir 433*cdf0e10cSrcweir if(aMask.IsEmpty()) 434*cdf0e10cSrcweir { 435*cdf0e10cSrcweir const Rectangle aRect(rAnimBmp.aPosPix, aContent.GetSizePixel()); 436*cdf0e10cSrcweir aVDevMask.SetFillColor(COL_BLACK); 437*cdf0e10cSrcweir aVDevMask.SetLineColor(); 438*cdf0e10cSrcweir aVDevMask.DrawRect(aRect); 439*cdf0e10cSrcweir } 440*cdf0e10cSrcweir else 441*cdf0e10cSrcweir { 442*cdf0e10cSrcweir aVDevMask.DrawBitmap(rAnimBmp.aPosPix, aMask); 443*cdf0e10cSrcweir } 444*cdf0e10cSrcweir break; 445*cdf0e10cSrcweir } 446*cdf0e10cSrcweir 447*cdf0e10cSrcweir case DISPOSE_FULL: 448*cdf0e10cSrcweir { 449*cdf0e10cSrcweir aVDev.DrawBitmapEx(rAnimBmp.aPosPix, 450*cdf0e10cSrcweir rAnimBmp.aBmpEx); 451*cdf0e10cSrcweir break; 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir case DISPOSE_PREVIOUS : 455*cdf0e10cSrcweir { 456*cdf0e10cSrcweir aVDev.DrawBitmapEx(rAnimBmp.aPosPix, 457*cdf0e10cSrcweir rAnimBmp.aBmpEx); 458*cdf0e10cSrcweir aVDevMask.DrawBitmap(rAnimBmp.aPosPix, 459*cdf0e10cSrcweir rAnimBmp.aBmpEx.GetMask()); 460*cdf0e10cSrcweir break; 461*cdf0e10cSrcweir } 462*cdf0e10cSrcweir } 463*cdf0e10cSrcweir 464*cdf0e10cSrcweir // extract current aVDev content into a new animation 465*cdf0e10cSrcweir // frame 466*cdf0e10cSrcweir GDIMetaFileSharedPtr pMtf( new GDIMetaFile() ); 467*cdf0e10cSrcweir pMtf->AddAction( 468*cdf0e10cSrcweir new MetaBmpExAction( aEmptyPoint, 469*cdf0e10cSrcweir BitmapEx( 470*cdf0e10cSrcweir aVDev.GetBitmap( 471*cdf0e10cSrcweir aEmptyPoint, 472*cdf0e10cSrcweir aAnimSize ), 473*cdf0e10cSrcweir aVDevMask.GetBitmap( 474*cdf0e10cSrcweir aEmptyPoint, 475*cdf0e10cSrcweir aAnimSize )))); 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir // setup mtf dimensions and pref map mode (for 478*cdf0e10cSrcweir // simplicity, keep it all in pixel. the metafile 479*cdf0e10cSrcweir // renderer scales it down to (1, 1) box anyway) 480*cdf0e10cSrcweir pMtf->SetPrefMapMode( MapMode() ); 481*cdf0e10cSrcweir pMtf->SetPrefSize( aAnimSize ); 482*cdf0e10cSrcweir 483*cdf0e10cSrcweir // #115934# 484*cdf0e10cSrcweir // Take care of special value for MultiPage TIFFs. ATM these shall just 485*cdf0e10cSrcweir // show their first page for _quite_ some time. 486*cdf0e10cSrcweir sal_Int32 nWaitTime100thSeconds( rAnimBmp.nWait ); 487*cdf0e10cSrcweir if( ANIMATION_TIMEOUT_ON_CLICK == nWaitTime100thSeconds ) 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir // ATM the huge value would block the timer, so use a long 490*cdf0e10cSrcweir // time to show first page (whole day) 491*cdf0e10cSrcweir nWaitTime100thSeconds = 100 * 60 * 60 * 24; 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir 494*cdf0e10cSrcweir // There are animated GIFs with no WaitTime set. Take 0.1 sec, the 495*cdf0e10cSrcweir // same duration that is used by the edit view. 496*cdf0e10cSrcweir if( nWaitTime100thSeconds == 0 ) 497*cdf0e10cSrcweir nWaitTime100thSeconds = 10; 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir o_rFrames.push_back( MtfAnimationFrame( pMtf, 500*cdf0e10cSrcweir nWaitTime100thSeconds / 100.0 ) ); 501*cdf0e10cSrcweir } 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir return !o_rFrames.empty(); 504*cdf0e10cSrcweir } 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir bool getRectanglesFromScrollMtf( ::basegfx::B2DRectangle& o_rScrollRect, 507*cdf0e10cSrcweir ::basegfx::B2DRectangle& o_rPaintRect, 508*cdf0e10cSrcweir const GDIMetaFileSharedPtr& rMtf ) 509*cdf0e10cSrcweir { 510*cdf0e10cSrcweir // extract bounds: scroll rect, paint rect 511*cdf0e10cSrcweir bool bScrollRectSet(false); 512*cdf0e10cSrcweir bool bPaintRectSet(false); 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir for ( MetaAction * pCurrAct = rMtf->FirstAction(); 515*cdf0e10cSrcweir pCurrAct != 0; pCurrAct = rMtf->NextAction() ) 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir if (pCurrAct->GetType() == META_COMMENT_ACTION) 518*cdf0e10cSrcweir { 519*cdf0e10cSrcweir MetaCommentAction * pAct = 520*cdf0e10cSrcweir static_cast<MetaCommentAction *>(pCurrAct); 521*cdf0e10cSrcweir // skip comment if not a special XTEXT comment 522*cdf0e10cSrcweir if (pAct->GetComment().CompareIgnoreCaseToAscii( 523*cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("XTEXT") ) == COMPARE_EQUAL) 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir if (pAct->GetComment().CompareIgnoreCaseToAscii( 526*cdf0e10cSrcweir "XTEXT_SCROLLRECT" ) == COMPARE_EQUAL) { 527*cdf0e10cSrcweir o_rScrollRect = ::vcl::unotools::b2DRectangleFromRectangle( 528*cdf0e10cSrcweir *reinterpret_cast<Rectangle const *>( 529*cdf0e10cSrcweir pAct->GetData() ) ); 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir bScrollRectSet = true; 532*cdf0e10cSrcweir } 533*cdf0e10cSrcweir else if (pAct->GetComment().CompareIgnoreCaseToAscii( 534*cdf0e10cSrcweir "XTEXT_PAINTRECT" ) == COMPARE_EQUAL) { 535*cdf0e10cSrcweir o_rPaintRect = ::vcl::unotools::b2DRectangleFromRectangle( 536*cdf0e10cSrcweir *reinterpret_cast<Rectangle const *>( 537*cdf0e10cSrcweir pAct->GetData() ) ); 538*cdf0e10cSrcweir 539*cdf0e10cSrcweir bPaintRectSet = true; 540*cdf0e10cSrcweir } 541*cdf0e10cSrcweir } 542*cdf0e10cSrcweir } 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir 545*cdf0e10cSrcweir return bScrollRectSet && bPaintRectSet; 546*cdf0e10cSrcweir } 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir } 549*cdf0e10cSrcweir } 550*cdf0e10cSrcweir 551