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_svtools.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <vos/macros.hxx> 32*cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 33*cdf0e10cSrcweir #include <tools/poly.hxx> 34*cdf0e10cSrcweir #include <vcl/outdev.hxx> 35*cdf0e10cSrcweir #include <vcl/window.hxx> 36*cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 37*cdf0e10cSrcweir #include <vcl/metaact.hxx> 38*cdf0e10cSrcweir #include <vcl/metric.hxx> 39*cdf0e10cSrcweir #include <vcl/animate.hxx> 40*cdf0e10cSrcweir #include <vcl/alpha.hxx> 41*cdf0e10cSrcweir #include <vcl/virdev.hxx> 42*cdf0e10cSrcweir #include "grfcache.hxx" 43*cdf0e10cSrcweir #include <svtools/grfmgr.hxx> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir // ----------- 46*cdf0e10cSrcweir // - defines - 47*cdf0e10cSrcweir // ----------- 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #define MAX_PRINTER_EXT 1024 50*cdf0e10cSrcweir #define MAP( cVal0, cVal1, nFrac ) ((sal_uInt8)((((long)(cVal0)<<20L)+nFrac*((long)(cVal1)-(cVal0)))>>20L)) 51*cdf0e10cSrcweir #define WATERMARK_LUM_OFFSET 50 52*cdf0e10cSrcweir #define WATERMARK_CON_OFFSET -70 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir // ----------- 55*cdf0e10cSrcweir // - helpers - 56*cdf0e10cSrcweir // ----------- 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir namespace { 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir void muckWithBitmap( const Point& rDestPoint, 61*cdf0e10cSrcweir const Size& rDestSize, 62*cdf0e10cSrcweir const Size& rRefSize, 63*cdf0e10cSrcweir bool& o_rbNonBitmapActionEncountered ) 64*cdf0e10cSrcweir { 65*cdf0e10cSrcweir const Point aEmptyPoint; 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir if( aEmptyPoint != rDestPoint || 68*cdf0e10cSrcweir rDestSize != rRefSize ) 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir // non-fullscale, or offsetted bmp -> fallback to mtf 71*cdf0e10cSrcweir // rendering 72*cdf0e10cSrcweir o_rbNonBitmapActionEncountered = true; 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir } 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir BitmapEx muckWithBitmap( const BitmapEx& rBmpEx, 77*cdf0e10cSrcweir const Point& rSrcPoint, 78*cdf0e10cSrcweir const Size& rSrcSize, 79*cdf0e10cSrcweir const Point& rDestPoint, 80*cdf0e10cSrcweir const Size& rDestSize, 81*cdf0e10cSrcweir const Size& rRefSize, 82*cdf0e10cSrcweir bool& o_rbNonBitmapActionEncountered ) 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir BitmapEx aBmpEx; 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir muckWithBitmap(rDestPoint, 87*cdf0e10cSrcweir rDestSize, 88*cdf0e10cSrcweir rRefSize, 89*cdf0e10cSrcweir o_rbNonBitmapActionEncountered); 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir if( o_rbNonBitmapActionEncountered ) 92*cdf0e10cSrcweir return aBmpEx; 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir aBmpEx = rBmpEx; 95*cdf0e10cSrcweir 96*cdf0e10cSrcweir if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) || 97*cdf0e10cSrcweir rSrcSize != rBmpEx.GetSizePixel() ) 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir // crop bitmap to given source rectangle (no 100*cdf0e10cSrcweir // need to copy and convert the whole bitmap) 101*cdf0e10cSrcweir const Rectangle aCropRect( rSrcPoint, 102*cdf0e10cSrcweir rSrcSize ); 103*cdf0e10cSrcweir aBmpEx.Crop( aCropRect ); 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir return aBmpEx; 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir } // namespace { 110*cdf0e10cSrcweir 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir // ------------------ 113*cdf0e10cSrcweir // - GraphicManager - 114*cdf0e10cSrcweir // ------------------ 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir GraphicManager::GraphicManager( sal_uLong nCacheSize, sal_uLong nMaxObjCacheSize ) : 117*cdf0e10cSrcweir mpCache( new GraphicCache( *this, nCacheSize, nMaxObjCacheSize ) ) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir 121*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir GraphicManager::~GraphicManager() 124*cdf0e10cSrcweir { 125*cdf0e10cSrcweir for( void* pObj = maObjList.First(); pObj; pObj = maObjList.Next() ) 126*cdf0e10cSrcweir ( (GraphicObject*) pObj )->GraphicManagerDestroyed(); 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir delete mpCache; 129*cdf0e10cSrcweir } 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize ) 134*cdf0e10cSrcweir { 135*cdf0e10cSrcweir mpCache->SetMaxDisplayCacheSize( nNewCacheSize ); 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir sal_uLong GraphicManager::GetMaxCacheSize() const 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir return mpCache->GetMaxDisplayCacheSize(); 143*cdf0e10cSrcweir } 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 146*cdf0e10cSrcweir 147*cdf0e10cSrcweir void GraphicManager::SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, sal_Bool bDestroyGreaterCached ) 148*cdf0e10cSrcweir { 149*cdf0e10cSrcweir mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached ); 150*cdf0e10cSrcweir } 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir sal_uLong GraphicManager::GetMaxObjCacheSize() const 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir return mpCache->GetMaxObjDisplayCacheSize(); 157*cdf0e10cSrcweir } 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir sal_uLong GraphicManager::GetUsedCacheSize() const 162*cdf0e10cSrcweir { 163*cdf0e10cSrcweir return mpCache->GetUsedDisplayCacheSize(); 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir sal_uLong GraphicManager::GetFreeCacheSize() const 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir return mpCache->GetFreeDisplayCacheSize(); 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir void GraphicManager::SetCacheTimeout( sal_uLong nTimeoutSeconds ) 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir mpCache->SetCacheTimeout( nTimeoutSeconds ); 178*cdf0e10cSrcweir } 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir sal_uLong GraphicManager::GetCacheTimeout() const 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir return mpCache->GetCacheTimeout(); 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir void GraphicManager::ClearCache() 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir mpCache->ClearDisplayCache(); 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir void GraphicManager::ReleaseFromCache( const GraphicObject& /*rObj*/ ) 197*cdf0e10cSrcweir { 198*cdf0e10cSrcweir // !!! 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir sal_Bool GraphicManager::IsInCache( OutputDevice* pOut, const Point& rPt, 204*cdf0e10cSrcweir const Size& rSz, const GraphicObject& rObj, 205*cdf0e10cSrcweir const GraphicAttr& rAttr ) const 206*cdf0e10cSrcweir { 207*cdf0e10cSrcweir return mpCache->IsInDisplayCache( pOut, rPt, rSz, rObj, rAttr ); 208*cdf0e10cSrcweir } 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir sal_Bool GraphicManager::DrawObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, 213*cdf0e10cSrcweir GraphicObject& rObj, const GraphicAttr& rAttr, 214*cdf0e10cSrcweir const sal_uLong nFlags, sal_Bool& rCached ) 215*cdf0e10cSrcweir { 216*cdf0e10cSrcweir Point aPt( rPt ); 217*cdf0e10cSrcweir Size aSz( rSz ); 218*cdf0e10cSrcweir sal_Bool bRet = sal_False; 219*cdf0e10cSrcweir 220*cdf0e10cSrcweir rCached = sal_False; 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir if( ( rObj.GetType() == GRAPHIC_BITMAP ) || ( rObj.GetType() == GRAPHIC_GDIMETAFILE ) ) 223*cdf0e10cSrcweir { 224*cdf0e10cSrcweir // create output and fill cache 225*cdf0e10cSrcweir const Size aOutSize( pOut->GetOutputSizePixel() ); 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir if( rObj.IsAnimated() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) || 228*cdf0e10cSrcweir ( !( nFlags & GRFMGR_DRAW_NO_SUBSTITUTE ) && 229*cdf0e10cSrcweir ( ( nFlags & GRFMGR_DRAW_SUBSTITUTE ) || 230*cdf0e10cSrcweir !( nFlags & GRFMGR_DRAW_CACHED ) || 231*cdf0e10cSrcweir ( pOut->GetConnectMetaFile() && !pOut->IsOutputEnabled() ) ) ) ) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir // simple output of transformed graphic 234*cdf0e10cSrcweir const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir if( aGraphic.IsSupportedGraphic() ) 237*cdf0e10cSrcweir { 238*cdf0e10cSrcweir const sal_uInt16 nRot10 = rAttr.GetRotation() % 3600; 239*cdf0e10cSrcweir 240*cdf0e10cSrcweir if( nRot10 ) 241*cdf0e10cSrcweir { 242*cdf0e10cSrcweir Polygon aPoly( Rectangle( aPt, aSz ) ); 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir aPoly.Rotate( aPt, nRot10 ); 245*cdf0e10cSrcweir const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); 246*cdf0e10cSrcweir aPt = aRotBoundRect.TopLeft(); 247*cdf0e10cSrcweir aSz = aRotBoundRect.GetSize(); 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir aGraphic.Draw( pOut, aPt, aSz ); 251*cdf0e10cSrcweir } 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir bRet = sal_True; 254*cdf0e10cSrcweir } 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir if( !bRet ) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir // cached/direct drawing 259*cdf0e10cSrcweir if( !mpCache->DrawDisplayCacheObj( pOut, aPt, aSz, rObj, rAttr ) ) 260*cdf0e10cSrcweir bRet = ImplDraw( pOut, aPt, aSz, rObj, rAttr, nFlags, rCached ); 261*cdf0e10cSrcweir else 262*cdf0e10cSrcweir bRet = rCached = sal_True; 263*cdf0e10cSrcweir } 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir return bRet; 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir void GraphicManager::ImplRegisterObj( const GraphicObject& rObj, Graphic& rSubstitute, 272*cdf0e10cSrcweir const ByteString* pID, const GraphicObject* pCopyObj ) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir maObjList.Insert( (void*) &rObj, LIST_APPEND ); 275*cdf0e10cSrcweir mpCache->AddGraphicObject( rObj, rSubstitute, pID, pCopyObj ); 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir void GraphicManager::ImplUnregisterObj( const GraphicObject& rObj ) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir mpCache->ReleaseGraphicObject( rObj ); 283*cdf0e10cSrcweir maObjList.Remove( (void*) &rObj ); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir void GraphicManager::ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj ) 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir mpCache->GraphicObjectWasSwappedOut( rObj ); 291*cdf0e10cSrcweir } 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir ByteString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const 296*cdf0e10cSrcweir { 297*cdf0e10cSrcweir return mpCache->GetUniqueID( rObj ); 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir sal_Bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ) 303*cdf0e10cSrcweir { 304*cdf0e10cSrcweir return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) ); 305*cdf0e10cSrcweir } 306*cdf0e10cSrcweir 307*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj ) 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir mpCache->GraphicObjectWasSwappedIn( rObj ); 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir sal_Bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, 317*cdf0e10cSrcweir const Size& rSz, GraphicObject& rObj, 318*cdf0e10cSrcweir const GraphicAttr& rAttr, 319*cdf0e10cSrcweir const sal_uLong nFlags, sal_Bool& rCached ) 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir const Graphic& rGraphic = rObj.GetGraphic(); 322*cdf0e10cSrcweir sal_Bool bRet = sal_False; 323*cdf0e10cSrcweir 324*cdf0e10cSrcweir if( rGraphic.IsSupportedGraphic() && !rGraphic.IsSwapOut() ) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir if( GRAPHIC_BITMAP == rGraphic.GetType() ) 327*cdf0e10cSrcweir { 328*cdf0e10cSrcweir const BitmapEx aSrcBmpEx( rGraphic.GetBitmapEx() ); 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir // #i46805# No point in caching a bitmap that is rendered 331*cdf0e10cSrcweir // via RectFill on the OutDev 332*cdf0e10cSrcweir if( !(pOut->GetDrawMode() & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP )) && 333*cdf0e10cSrcweir mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) ) 334*cdf0e10cSrcweir { 335*cdf0e10cSrcweir BitmapEx aDstBmpEx; 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir if( ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags, &aDstBmpEx ) ) 338*cdf0e10cSrcweir { 339*cdf0e10cSrcweir rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx ); 340*cdf0e10cSrcweir bRet = sal_True; 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir } 343*cdf0e10cSrcweir 344*cdf0e10cSrcweir if( !bRet ) 345*cdf0e10cSrcweir bRet = ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags ); 346*cdf0e10cSrcweir } 347*cdf0e10cSrcweir else 348*cdf0e10cSrcweir { 349*cdf0e10cSrcweir const GDIMetaFile& rSrcMtf = rGraphic.GetGDIMetaFile(); 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir if( mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) ) 352*cdf0e10cSrcweir { 353*cdf0e10cSrcweir GDIMetaFile aDstMtf; 354*cdf0e10cSrcweir BitmapEx aContainedBmpEx; 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir if( ImplCreateOutput( pOut, rPt, rSz, rSrcMtf, rAttr, nFlags, aDstMtf, aContainedBmpEx ) ) 357*cdf0e10cSrcweir { 358*cdf0e10cSrcweir if( !!aContainedBmpEx ) 359*cdf0e10cSrcweir { 360*cdf0e10cSrcweir // #117889# Use bitmap output method, if 361*cdf0e10cSrcweir // metafile basically contains only a single 362*cdf0e10cSrcweir // bitmap 363*cdf0e10cSrcweir BitmapEx aDstBmpEx; 364*cdf0e10cSrcweir 365*cdf0e10cSrcweir if( ImplCreateOutput( pOut, rPt, rSz, aContainedBmpEx, rAttr, nFlags, &aDstBmpEx ) ) 366*cdf0e10cSrcweir { 367*cdf0e10cSrcweir rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx ); 368*cdf0e10cSrcweir bRet = sal_True; 369*cdf0e10cSrcweir } 370*cdf0e10cSrcweir } 371*cdf0e10cSrcweir else 372*cdf0e10cSrcweir { 373*cdf0e10cSrcweir rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstMtf ); 374*cdf0e10cSrcweir bRet = sal_True; 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir } 377*cdf0e10cSrcweir } 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir if( !bRet ) 380*cdf0e10cSrcweir { 381*cdf0e10cSrcweir const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir if( aGraphic.IsSupportedGraphic() ) 384*cdf0e10cSrcweir { 385*cdf0e10cSrcweir aGraphic.Draw( pOut, rPt, rSz ); 386*cdf0e10cSrcweir bRet = sal_True; 387*cdf0e10cSrcweir } 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir } 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir return bRet; 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut, 398*cdf0e10cSrcweir const Point& rPt, const Size& rSz, 399*cdf0e10cSrcweir const BitmapEx& rBmpEx, const GraphicAttr& rAttr, 400*cdf0e10cSrcweir const sal_uLong nFlags, BitmapEx* pBmpEx ) 401*cdf0e10cSrcweir { 402*cdf0e10cSrcweir sal_uInt16 nRot10 = rAttr.GetRotation() % 3600; 403*cdf0e10cSrcweir Point aOutPtPix; 404*cdf0e10cSrcweir Size aOutSzPix; 405*cdf0e10cSrcweir Size aUnrotatedSzPix( pOut->LogicToPixel( rSz ) ); 406*cdf0e10cSrcweir sal_Bool bRet = sal_False; 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir if( nRot10 ) 409*cdf0e10cSrcweir { 410*cdf0e10cSrcweir Polygon aPoly( Rectangle( rPt, rSz ) ); 411*cdf0e10cSrcweir 412*cdf0e10cSrcweir aPoly.Rotate( rPt, nRot10 ); 413*cdf0e10cSrcweir const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); 414*cdf0e10cSrcweir aOutPtPix = pOut->LogicToPixel( aRotBoundRect.TopLeft() ); 415*cdf0e10cSrcweir aOutSzPix = pOut->LogicToPixel( aRotBoundRect.GetSize() ); 416*cdf0e10cSrcweir } 417*cdf0e10cSrcweir else 418*cdf0e10cSrcweir { 419*cdf0e10cSrcweir aOutPtPix = pOut->LogicToPixel( rPt ); 420*cdf0e10cSrcweir aOutSzPix = aUnrotatedSzPix; 421*cdf0e10cSrcweir } 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir if( aUnrotatedSzPix.Width() && aUnrotatedSzPix.Height() ) 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir BitmapEx aBmpEx( rBmpEx ); 426*cdf0e10cSrcweir BitmapEx aOutBmpEx; 427*cdf0e10cSrcweir Point aOutPt; 428*cdf0e10cSrcweir Size aOutSz; 429*cdf0e10cSrcweir const Size& rBmpSzPix = rBmpEx.GetSizePixel(); 430*cdf0e10cSrcweir const long nW = rBmpSzPix.Width(); 431*cdf0e10cSrcweir const long nH = rBmpSzPix.Height(); 432*cdf0e10cSrcweir const long nNewW = aUnrotatedSzPix.Width(); 433*cdf0e10cSrcweir const long nNewH = aUnrotatedSzPix.Height(); 434*cdf0e10cSrcweir double fTmp; 435*cdf0e10cSrcweir long* pMapIX = new long[ nNewW ]; 436*cdf0e10cSrcweir long* pMapFX = new long[ nNewW ]; 437*cdf0e10cSrcweir long* pMapIY = new long[ nNewH ]; 438*cdf0e10cSrcweir long* pMapFY = new long[ nNewH ]; 439*cdf0e10cSrcweir long nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1; 440*cdf0e10cSrcweir long nX, nY, nTmp, nTmpX, nTmpY; 441*cdf0e10cSrcweir sal_Bool bHMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0; 442*cdf0e10cSrcweir sal_Bool bVMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0; 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir if( nFlags & GRFMGR_DRAW_BILINEAR ) 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir const double fRevScaleX = ( nNewW > 1L ) ? ( (double) ( nW - 1L ) / ( nNewW - 1L ) ) : 0.0; 447*cdf0e10cSrcweir const double fRevScaleY = ( nNewH > 1L ) ? ( (double) ( nH - 1L ) / ( nNewH - 1L ) ) : 0.0; 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir // create horizontal mapping table 450*cdf0e10cSrcweir for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ ) 451*cdf0e10cSrcweir { 452*cdf0e10cSrcweir fTmp = nX * fRevScaleX; 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir if( bHMirr ) 455*cdf0e10cSrcweir fTmp = nTmpX - fTmp; 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir pMapFX[ nX ] = (long) ( ( fTmp - ( pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. ); 458*cdf0e10cSrcweir } 459*cdf0e10cSrcweir 460*cdf0e10cSrcweir // create vertical mapping table 461*cdf0e10cSrcweir for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ ) 462*cdf0e10cSrcweir { 463*cdf0e10cSrcweir fTmp = nY * fRevScaleY; 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir if( bVMirr ) 466*cdf0e10cSrcweir fTmp = nTmpY - fTmp; 467*cdf0e10cSrcweir 468*cdf0e10cSrcweir pMapFY[ nY ] = (long) ( ( fTmp - ( pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. ); 469*cdf0e10cSrcweir } 470*cdf0e10cSrcweir } 471*cdf0e10cSrcweir else 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir // #98290# Use a different mapping for non-interpolating mode, to avoid missing rows/columns 474*cdf0e10cSrcweir const double fRevScaleX = ( nNewW > 1L ) ? ( (double) nW / nNewW ) : 0.0; 475*cdf0e10cSrcweir const double fRevScaleY = ( nNewH > 1L ) ? ( (double) nH / nNewH ) : 0.0; 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir // create horizontal mapping table 478*cdf0e10cSrcweir for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ ) 479*cdf0e10cSrcweir { 480*cdf0e10cSrcweir fTmp = nX * fRevScaleX; 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir if( bHMirr ) 483*cdf0e10cSrcweir fTmp = nTmpX - fTmp; 484*cdf0e10cSrcweir 485*cdf0e10cSrcweir // #98290# Do not use round to zero, otherwise last column will be missing 486*cdf0e10cSrcweir pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp ); 487*cdf0e10cSrcweir pMapFX[ nX ] = fTmp >= nTmp+1 ? 1048576 : 0; 488*cdf0e10cSrcweir } 489*cdf0e10cSrcweir 490*cdf0e10cSrcweir // create vertical mapping table 491*cdf0e10cSrcweir for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ ) 492*cdf0e10cSrcweir { 493*cdf0e10cSrcweir fTmp = nY * fRevScaleY; 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir if( bVMirr ) 496*cdf0e10cSrcweir fTmp = nTmpY - fTmp; 497*cdf0e10cSrcweir 498*cdf0e10cSrcweir // #98290# Do not use round to zero, otherwise last row will be missing 499*cdf0e10cSrcweir pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp ); 500*cdf0e10cSrcweir pMapFY[ nY ] = fTmp >= nTmp+1 ? 1048576 : 0; 501*cdf0e10cSrcweir } 502*cdf0e10cSrcweir } 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir // calculate output sizes 505*cdf0e10cSrcweir if( !pBmpEx ) 506*cdf0e10cSrcweir { 507*cdf0e10cSrcweir Point aPt; 508*cdf0e10cSrcweir Rectangle aOutRect( aPt, pOut->GetOutputSizePixel() ); 509*cdf0e10cSrcweir Rectangle aBmpRect( aOutPtPix, aOutSzPix ); 510*cdf0e10cSrcweir 511*cdf0e10cSrcweir if( pOut->GetOutDevType() == OUTDEV_WINDOW ) 512*cdf0e10cSrcweir { 513*cdf0e10cSrcweir const Region aPaintRgn( ( (Window*) pOut )->GetPaintRegion() ); 514*cdf0e10cSrcweir if( !aPaintRgn.IsNull() ) 515*cdf0e10cSrcweir aOutRect.Intersection( pOut->LogicToPixel( aPaintRgn.GetBoundRect() ) ); 516*cdf0e10cSrcweir } 517*cdf0e10cSrcweir 518*cdf0e10cSrcweir aOutRect.Intersection( aBmpRect ); 519*cdf0e10cSrcweir 520*cdf0e10cSrcweir if( !aOutRect.IsEmpty() ) 521*cdf0e10cSrcweir { 522*cdf0e10cSrcweir aOutPt = pOut->PixelToLogic( aOutRect.TopLeft() ); 523*cdf0e10cSrcweir aOutSz = pOut->PixelToLogic( aOutRect.GetSize() ); 524*cdf0e10cSrcweir nStartX = aOutRect.Left() - aBmpRect.Left(); 525*cdf0e10cSrcweir nStartY = aOutRect.Top() - aBmpRect.Top(); 526*cdf0e10cSrcweir nEndX = aOutRect.Right() - aBmpRect.Left(); 527*cdf0e10cSrcweir nEndY = aOutRect.Bottom() - aBmpRect.Top(); 528*cdf0e10cSrcweir } 529*cdf0e10cSrcweir else 530*cdf0e10cSrcweir nStartX = -1L; // invalid 531*cdf0e10cSrcweir } 532*cdf0e10cSrcweir else 533*cdf0e10cSrcweir { 534*cdf0e10cSrcweir aOutPt = pOut->PixelToLogic( aOutPtPix ); 535*cdf0e10cSrcweir aOutSz = pOut->PixelToLogic( aOutSzPix ); 536*cdf0e10cSrcweir nStartX = nStartY = 0; 537*cdf0e10cSrcweir nEndX = aOutSzPix.Width() - 1L; 538*cdf0e10cSrcweir nEndY = aOutSzPix.Height() - 1L; 539*cdf0e10cSrcweir } 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir // do transformation 542*cdf0e10cSrcweir if( nStartX >= 0L ) 543*cdf0e10cSrcweir { 544*cdf0e10cSrcweir const sal_Bool bSimple = ( 1 == nW || 1 == nH ); 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir if( nRot10 ) 547*cdf0e10cSrcweir { 548*cdf0e10cSrcweir if( bSimple ) 549*cdf0e10cSrcweir { 550*cdf0e10cSrcweir bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSzPix ); 551*cdf0e10cSrcweir 552*cdf0e10cSrcweir if( bRet ) 553*cdf0e10cSrcweir aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT ); 554*cdf0e10cSrcweir } 555*cdf0e10cSrcweir else 556*cdf0e10cSrcweir { 557*cdf0e10cSrcweir bRet = ImplCreateRotatedScaled( aBmpEx, 558*cdf0e10cSrcweir nRot10, aOutSzPix, aUnrotatedSzPix, 559*cdf0e10cSrcweir pMapIX, pMapFX, pMapIY, pMapFY, nStartX, nEndX, nStartY, nEndY, 560*cdf0e10cSrcweir aOutBmpEx ); 561*cdf0e10cSrcweir } 562*cdf0e10cSrcweir } 563*cdf0e10cSrcweir else 564*cdf0e10cSrcweir { 565*cdf0e10cSrcweir // #105229# Don't scale if output size equals bitmap size 566*cdf0e10cSrcweir // #107226# Copy through only if we're not mirroring 567*cdf0e10cSrcweir if( !bHMirr && !bVMirr && aOutSzPix == rBmpSzPix ) 568*cdf0e10cSrcweir { 569*cdf0e10cSrcweir // #107226# Use original dimensions when just copying through 570*cdf0e10cSrcweir aOutPt = pOut->PixelToLogic( aOutPtPix ); 571*cdf0e10cSrcweir aOutSz = pOut->PixelToLogic( aOutSzPix ); 572*cdf0e10cSrcweir aOutBmpEx = aBmpEx; 573*cdf0e10cSrcweir bRet = sal_True; 574*cdf0e10cSrcweir } 575*cdf0e10cSrcweir else 576*cdf0e10cSrcweir { 577*cdf0e10cSrcweir if( bSimple ) 578*cdf0e10cSrcweir bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) ); 579*cdf0e10cSrcweir else 580*cdf0e10cSrcweir { 581*cdf0e10cSrcweir bRet = ImplCreateScaled( aBmpEx, 582*cdf0e10cSrcweir pMapIX, pMapFX, pMapIY, pMapFY, 583*cdf0e10cSrcweir nStartX, nEndX, nStartY, nEndY, 584*cdf0e10cSrcweir aOutBmpEx ); 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir } 587*cdf0e10cSrcweir } 588*cdf0e10cSrcweir 589*cdf0e10cSrcweir if( bRet ) 590*cdf0e10cSrcweir { 591*cdf0e10cSrcweir // attribute adjustment if neccessary 592*cdf0e10cSrcweir if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsTransparent() ) 593*cdf0e10cSrcweir ImplAdjust( aOutBmpEx, rAttr, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY ); 594*cdf0e10cSrcweir 595*cdf0e10cSrcweir // OutDev adjustment if neccessary 596*cdf0e10cSrcweir if( pOut->GetOutDevType() != OUTDEV_PRINTER && pOut->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 ) 597*cdf0e10cSrcweir aOutBmpEx.Dither( BMP_DITHER_MATRIX ); 598*cdf0e10cSrcweir } 599*cdf0e10cSrcweir } 600*cdf0e10cSrcweir 601*cdf0e10cSrcweir // delete lookup tables 602*cdf0e10cSrcweir delete[] pMapIX; 603*cdf0e10cSrcweir delete[] pMapFX; 604*cdf0e10cSrcweir delete[] pMapIY; 605*cdf0e10cSrcweir delete[] pMapFY; 606*cdf0e10cSrcweir 607*cdf0e10cSrcweir // create output 608*cdf0e10cSrcweir if( bRet ) 609*cdf0e10cSrcweir { 610*cdf0e10cSrcweir if( !pBmpEx ) 611*cdf0e10cSrcweir pOut->DrawBitmapEx( aOutPt, aOutSz, aOutBmpEx ); 612*cdf0e10cSrcweir else 613*cdf0e10cSrcweir { 614*cdf0e10cSrcweir if( !rAttr.IsTransparent() && !aOutBmpEx.IsAlpha() ) 615*cdf0e10cSrcweir aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOut ), aOutBmpEx.GetMask() ); 616*cdf0e10cSrcweir 617*cdf0e10cSrcweir pOut->DrawBitmapEx( aOutPt, aOutSz, *pBmpEx = aOutBmpEx ); 618*cdf0e10cSrcweir } 619*cdf0e10cSrcweir } 620*cdf0e10cSrcweir } 621*cdf0e10cSrcweir 622*cdf0e10cSrcweir return bRet; 623*cdf0e10cSrcweir } 624*cdf0e10cSrcweir 625*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 626*cdf0e10cSrcweir 627*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut, 628*cdf0e10cSrcweir const Point& rPt, const Size& rSz, 629*cdf0e10cSrcweir const GDIMetaFile& rMtf, const GraphicAttr& rAttr, 630*cdf0e10cSrcweir const sal_uLong /*nFlags*/, GDIMetaFile& rOutMtf, BitmapEx& rOutBmpEx ) 631*cdf0e10cSrcweir { 632*cdf0e10cSrcweir const Size aNewSize( rMtf.GetPrefSize() ); 633*cdf0e10cSrcweir 634*cdf0e10cSrcweir rOutMtf = rMtf; 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir // #117889# count bitmap actions, and flag actions that paint, but 637*cdf0e10cSrcweir // are no bitmaps. 638*cdf0e10cSrcweir sal_Int32 nNumBitmaps(0); 639*cdf0e10cSrcweir bool bNonBitmapActionEncountered(false); 640*cdf0e10cSrcweir if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() ) 641*cdf0e10cSrcweir { 642*cdf0e10cSrcweir const double fGrfWH = (double) aNewSize.Width() / aNewSize.Height(); 643*cdf0e10cSrcweir const double fOutWH = (double) rSz.Width() / rSz.Height(); 644*cdf0e10cSrcweir 645*cdf0e10cSrcweir const double fScaleX = fOutWH / fGrfWH; 646*cdf0e10cSrcweir const double fScaleY = 1.0; 647*cdf0e10cSrcweir 648*cdf0e10cSrcweir const MapMode& rPrefMapMode( rMtf.GetPrefMapMode() ); 649*cdf0e10cSrcweir const Size& rSizePix( pOut->LogicToPixel( aNewSize, 650*cdf0e10cSrcweir rPrefMapMode ) ); 651*cdf0e10cSrcweir 652*cdf0e10cSrcweir // taking care of font width default if scaling metafile. 653*cdf0e10cSrcweir // #117889# use existing metafile scan, to determine whether 654*cdf0e10cSrcweir // the metafile basically displays a single bitmap. Note that 655*cdf0e10cSrcweir // the solution, as implemented here, is quite suboptimal (the 656*cdf0e10cSrcweir // cases where a mtf consisting basically of a single bitmap, 657*cdf0e10cSrcweir // that fail to pass the test below, are probably frequent). A 658*cdf0e10cSrcweir // better solution would involve FSAA, but that's currently 659*cdf0e10cSrcweir // expensive, and might trigger bugs on display drivers, if 660*cdf0e10cSrcweir // VDevs get bigger than the actual screen. 661*cdf0e10cSrcweir sal_uInt32 nCurPos; 662*cdf0e10cSrcweir MetaAction* pAct; 663*cdf0e10cSrcweir for( nCurPos = 0, pAct = (MetaAction*)rOutMtf.FirstAction(); pAct; 664*cdf0e10cSrcweir pAct = (MetaAction*)rOutMtf.NextAction(), nCurPos++ ) 665*cdf0e10cSrcweir { 666*cdf0e10cSrcweir MetaAction* pModAct = NULL; 667*cdf0e10cSrcweir switch( pAct->GetType() ) 668*cdf0e10cSrcweir { 669*cdf0e10cSrcweir case META_FONT_ACTION: 670*cdf0e10cSrcweir { 671*cdf0e10cSrcweir MetaFontAction* pA = (MetaFontAction*)pAct; 672*cdf0e10cSrcweir Font aFont( pA->GetFont() ); 673*cdf0e10cSrcweir if ( !aFont.GetWidth() ) 674*cdf0e10cSrcweir { 675*cdf0e10cSrcweir FontMetric aFontMetric( pOut->GetFontMetric( aFont ) ); 676*cdf0e10cSrcweir aFont.SetWidth( aFontMetric.GetWidth() ); 677*cdf0e10cSrcweir pModAct = new MetaFontAction( aFont ); 678*cdf0e10cSrcweir } 679*cdf0e10cSrcweir } 680*cdf0e10cSrcweir // FALLTHROUGH intended 681*cdf0e10cSrcweir case META_NULL_ACTION: 682*cdf0e10cSrcweir // FALLTHROUGH intended 683*cdf0e10cSrcweir 684*cdf0e10cSrcweir // OutDev state changes (which don't affect bitmap 685*cdf0e10cSrcweir // output) 686*cdf0e10cSrcweir case META_LINECOLOR_ACTION: 687*cdf0e10cSrcweir // FALLTHROUGH intended 688*cdf0e10cSrcweir case META_FILLCOLOR_ACTION: 689*cdf0e10cSrcweir // FALLTHROUGH intended 690*cdf0e10cSrcweir case META_TEXTCOLOR_ACTION: 691*cdf0e10cSrcweir // FALLTHROUGH intended 692*cdf0e10cSrcweir case META_TEXTFILLCOLOR_ACTION: 693*cdf0e10cSrcweir // FALLTHROUGH intended 694*cdf0e10cSrcweir case META_TEXTALIGN_ACTION: 695*cdf0e10cSrcweir // FALLTHROUGH intended 696*cdf0e10cSrcweir case META_TEXTLINECOLOR_ACTION: 697*cdf0e10cSrcweir // FALLTHROUGH intended 698*cdf0e10cSrcweir case META_TEXTLINE_ACTION: 699*cdf0e10cSrcweir // FALLTHROUGH intended 700*cdf0e10cSrcweir case META_PUSH_ACTION: 701*cdf0e10cSrcweir // FALLTHROUGH intended 702*cdf0e10cSrcweir case META_POP_ACTION: 703*cdf0e10cSrcweir // FALLTHROUGH intended 704*cdf0e10cSrcweir case META_LAYOUTMODE_ACTION: 705*cdf0e10cSrcweir // FALLTHROUGH intended 706*cdf0e10cSrcweir case META_TEXTLANGUAGE_ACTION: 707*cdf0e10cSrcweir // FALLTHROUGH intended 708*cdf0e10cSrcweir case META_COMMENT_ACTION: 709*cdf0e10cSrcweir break; 710*cdf0e10cSrcweir 711*cdf0e10cSrcweir // bitmap output methods 712*cdf0e10cSrcweir case META_BMP_ACTION: 713*cdf0e10cSrcweir if( !nNumBitmaps && !bNonBitmapActionEncountered ) 714*cdf0e10cSrcweir { 715*cdf0e10cSrcweir MetaBmpAction* pAction = (MetaBmpAction*)pAct; 716*cdf0e10cSrcweir 717*cdf0e10cSrcweir rOutBmpEx = BitmapEx( pAction->GetBitmap() ); 718*cdf0e10cSrcweir muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), 719*cdf0e10cSrcweir rPrefMapMode ), 720*cdf0e10cSrcweir pAction->GetBitmap().GetSizePixel(), 721*cdf0e10cSrcweir rSizePix, 722*cdf0e10cSrcweir bNonBitmapActionEncountered ); 723*cdf0e10cSrcweir ++nNumBitmaps; 724*cdf0e10cSrcweir } 725*cdf0e10cSrcweir break; 726*cdf0e10cSrcweir 727*cdf0e10cSrcweir case META_BMPSCALE_ACTION: 728*cdf0e10cSrcweir if( !nNumBitmaps && !bNonBitmapActionEncountered ) 729*cdf0e10cSrcweir { 730*cdf0e10cSrcweir MetaBmpScaleAction* pAction = (MetaBmpScaleAction*)pAct; 731*cdf0e10cSrcweir 732*cdf0e10cSrcweir rOutBmpEx = BitmapEx( pAction->GetBitmap() ); 733*cdf0e10cSrcweir muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), 734*cdf0e10cSrcweir rPrefMapMode ), 735*cdf0e10cSrcweir pOut->LogicToPixel( pAction->GetSize(), 736*cdf0e10cSrcweir rPrefMapMode ), 737*cdf0e10cSrcweir rSizePix, 738*cdf0e10cSrcweir bNonBitmapActionEncountered ); 739*cdf0e10cSrcweir ++nNumBitmaps; 740*cdf0e10cSrcweir } 741*cdf0e10cSrcweir break; 742*cdf0e10cSrcweir 743*cdf0e10cSrcweir case META_BMPSCALEPART_ACTION: 744*cdf0e10cSrcweir if( !nNumBitmaps && !bNonBitmapActionEncountered ) 745*cdf0e10cSrcweir { 746*cdf0e10cSrcweir MetaBmpScalePartAction* pAction = (MetaBmpScalePartAction*)pAct; 747*cdf0e10cSrcweir 748*cdf0e10cSrcweir rOutBmpEx = muckWithBitmap( BitmapEx( pAction->GetBitmap() ), 749*cdf0e10cSrcweir pAction->GetSrcPoint(), 750*cdf0e10cSrcweir pAction->GetSrcSize(), 751*cdf0e10cSrcweir pOut->LogicToPixel( pAction->GetDestPoint(), 752*cdf0e10cSrcweir rPrefMapMode ), 753*cdf0e10cSrcweir pOut->LogicToPixel( pAction->GetDestSize(), 754*cdf0e10cSrcweir rPrefMapMode ), 755*cdf0e10cSrcweir rSizePix, 756*cdf0e10cSrcweir bNonBitmapActionEncountered ); 757*cdf0e10cSrcweir ++nNumBitmaps; 758*cdf0e10cSrcweir } 759*cdf0e10cSrcweir break; 760*cdf0e10cSrcweir 761*cdf0e10cSrcweir case META_BMPEX_ACTION: 762*cdf0e10cSrcweir if( !nNumBitmaps && !bNonBitmapActionEncountered ) 763*cdf0e10cSrcweir { 764*cdf0e10cSrcweir MetaBmpExAction* pAction = (MetaBmpExAction*)pAct; 765*cdf0e10cSrcweir 766*cdf0e10cSrcweir rOutBmpEx = pAction->GetBitmapEx(); 767*cdf0e10cSrcweir muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), 768*cdf0e10cSrcweir rPrefMapMode ), 769*cdf0e10cSrcweir pAction->GetBitmapEx().GetSizePixel(), 770*cdf0e10cSrcweir rSizePix, 771*cdf0e10cSrcweir bNonBitmapActionEncountered ); 772*cdf0e10cSrcweir ++nNumBitmaps; 773*cdf0e10cSrcweir } 774*cdf0e10cSrcweir break; 775*cdf0e10cSrcweir 776*cdf0e10cSrcweir case META_BMPEXSCALE_ACTION: 777*cdf0e10cSrcweir if( !nNumBitmaps && !bNonBitmapActionEncountered ) 778*cdf0e10cSrcweir { 779*cdf0e10cSrcweir MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*)pAct; 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir rOutBmpEx = pAction->GetBitmapEx(); 782*cdf0e10cSrcweir muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), 783*cdf0e10cSrcweir rPrefMapMode ), 784*cdf0e10cSrcweir pOut->LogicToPixel( pAction->GetSize(), 785*cdf0e10cSrcweir rPrefMapMode ), 786*cdf0e10cSrcweir rSizePix, 787*cdf0e10cSrcweir bNonBitmapActionEncountered ); 788*cdf0e10cSrcweir ++nNumBitmaps; 789*cdf0e10cSrcweir } 790*cdf0e10cSrcweir break; 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir case META_BMPEXSCALEPART_ACTION: 793*cdf0e10cSrcweir if( !nNumBitmaps && !bNonBitmapActionEncountered ) 794*cdf0e10cSrcweir { 795*cdf0e10cSrcweir MetaBmpExScalePartAction* pAction = (MetaBmpExScalePartAction*)pAct; 796*cdf0e10cSrcweir 797*cdf0e10cSrcweir rOutBmpEx = muckWithBitmap( pAction->GetBitmapEx(), 798*cdf0e10cSrcweir pAction->GetSrcPoint(), 799*cdf0e10cSrcweir pAction->GetSrcSize(), 800*cdf0e10cSrcweir pOut->LogicToPixel( pAction->GetDestPoint(), 801*cdf0e10cSrcweir rPrefMapMode ), 802*cdf0e10cSrcweir pOut->LogicToPixel( pAction->GetDestSize(), 803*cdf0e10cSrcweir rPrefMapMode ), 804*cdf0e10cSrcweir rSizePix, 805*cdf0e10cSrcweir bNonBitmapActionEncountered ); 806*cdf0e10cSrcweir ++nNumBitmaps; 807*cdf0e10cSrcweir } 808*cdf0e10cSrcweir break; 809*cdf0e10cSrcweir 810*cdf0e10cSrcweir // these actions actually output something (that's 811*cdf0e10cSrcweir // different from a bitmap) 812*cdf0e10cSrcweir case META_RASTEROP_ACTION: 813*cdf0e10cSrcweir if( ((MetaRasterOpAction*)pAct)->GetRasterOp() == ROP_OVERPAINT ) 814*cdf0e10cSrcweir break; 815*cdf0e10cSrcweir // FALLTHROUGH intended 816*cdf0e10cSrcweir case META_PIXEL_ACTION: 817*cdf0e10cSrcweir // FALLTHROUGH intended 818*cdf0e10cSrcweir case META_POINT_ACTION: 819*cdf0e10cSrcweir // FALLTHROUGH intended 820*cdf0e10cSrcweir case META_LINE_ACTION: 821*cdf0e10cSrcweir // FALLTHROUGH intended 822*cdf0e10cSrcweir case META_RECT_ACTION: 823*cdf0e10cSrcweir // FALLTHROUGH intended 824*cdf0e10cSrcweir case META_ROUNDRECT_ACTION: 825*cdf0e10cSrcweir // FALLTHROUGH intended 826*cdf0e10cSrcweir case META_ELLIPSE_ACTION: 827*cdf0e10cSrcweir // FALLTHROUGH intended 828*cdf0e10cSrcweir case META_ARC_ACTION: 829*cdf0e10cSrcweir // FALLTHROUGH intended 830*cdf0e10cSrcweir case META_PIE_ACTION: 831*cdf0e10cSrcweir // FALLTHROUGH intended 832*cdf0e10cSrcweir case META_CHORD_ACTION: 833*cdf0e10cSrcweir // FALLTHROUGH intended 834*cdf0e10cSrcweir case META_POLYLINE_ACTION: 835*cdf0e10cSrcweir // FALLTHROUGH intended 836*cdf0e10cSrcweir case META_POLYGON_ACTION: 837*cdf0e10cSrcweir // FALLTHROUGH intended 838*cdf0e10cSrcweir case META_POLYPOLYGON_ACTION: 839*cdf0e10cSrcweir // FALLTHROUGH intended 840*cdf0e10cSrcweir 841*cdf0e10cSrcweir case META_TEXT_ACTION: 842*cdf0e10cSrcweir // FALLTHROUGH intended 843*cdf0e10cSrcweir case META_TEXTARRAY_ACTION: 844*cdf0e10cSrcweir // FALLTHROUGH intended 845*cdf0e10cSrcweir case META_STRETCHTEXT_ACTION: 846*cdf0e10cSrcweir // FALLTHROUGH intended 847*cdf0e10cSrcweir case META_TEXTRECT_ACTION: 848*cdf0e10cSrcweir // FALLTHROUGH intended 849*cdf0e10cSrcweir 850*cdf0e10cSrcweir case META_MASK_ACTION: 851*cdf0e10cSrcweir // FALLTHROUGH intended 852*cdf0e10cSrcweir case META_MASKSCALE_ACTION: 853*cdf0e10cSrcweir // FALLTHROUGH intended 854*cdf0e10cSrcweir case META_MASKSCALEPART_ACTION: 855*cdf0e10cSrcweir // FALLTHROUGH intended 856*cdf0e10cSrcweir 857*cdf0e10cSrcweir case META_GRADIENT_ACTION: 858*cdf0e10cSrcweir // FALLTHROUGH intended 859*cdf0e10cSrcweir case META_HATCH_ACTION: 860*cdf0e10cSrcweir // FALLTHROUGH intended 861*cdf0e10cSrcweir case META_WALLPAPER_ACTION: 862*cdf0e10cSrcweir // FALLTHROUGH intended 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir case META_TRANSPARENT_ACTION: 865*cdf0e10cSrcweir // FALLTHROUGH intended 866*cdf0e10cSrcweir case META_EPS_ACTION: 867*cdf0e10cSrcweir // FALLTHROUGH intended 868*cdf0e10cSrcweir case META_FLOATTRANSPARENT_ACTION: 869*cdf0e10cSrcweir // FALLTHROUGH intended 870*cdf0e10cSrcweir case META_GRADIENTEX_ACTION: 871*cdf0e10cSrcweir // FALLTHROUGH intended 872*cdf0e10cSrcweir case META_RENDERGRAPHIC_ACTION: 873*cdf0e10cSrcweir // FALLTHROUGH intended 874*cdf0e10cSrcweir 875*cdf0e10cSrcweir // OutDev state changes that _do_ affect bitmap 876*cdf0e10cSrcweir // output 877*cdf0e10cSrcweir case META_CLIPREGION_ACTION: 878*cdf0e10cSrcweir // FALLTHROUGH intended 879*cdf0e10cSrcweir case META_ISECTRECTCLIPREGION_ACTION: 880*cdf0e10cSrcweir // FALLTHROUGH intended 881*cdf0e10cSrcweir case META_ISECTREGIONCLIPREGION_ACTION: 882*cdf0e10cSrcweir // FALLTHROUGH intended 883*cdf0e10cSrcweir case META_MOVECLIPREGION_ACTION: 884*cdf0e10cSrcweir // FALLTHROUGH intended 885*cdf0e10cSrcweir 886*cdf0e10cSrcweir case META_MAPMODE_ACTION: 887*cdf0e10cSrcweir // FALLTHROUGH intended 888*cdf0e10cSrcweir case META_REFPOINT_ACTION: 889*cdf0e10cSrcweir // FALLTHROUGH intended 890*cdf0e10cSrcweir default: 891*cdf0e10cSrcweir bNonBitmapActionEncountered = true; 892*cdf0e10cSrcweir break; 893*cdf0e10cSrcweir } 894*cdf0e10cSrcweir if ( pModAct ) 895*cdf0e10cSrcweir { 896*cdf0e10cSrcweir rOutMtf.ReplaceAction( pModAct, nCurPos ); 897*cdf0e10cSrcweir pAct->Delete(); 898*cdf0e10cSrcweir } 899*cdf0e10cSrcweir else 900*cdf0e10cSrcweir { 901*cdf0e10cSrcweir if( pAct->GetRefCount() > 1 ) 902*cdf0e10cSrcweir { 903*cdf0e10cSrcweir rOutMtf.ReplaceAction( pModAct = pAct->Clone(), nCurPos ); 904*cdf0e10cSrcweir pAct->Delete(); 905*cdf0e10cSrcweir } 906*cdf0e10cSrcweir else 907*cdf0e10cSrcweir pModAct = pAct; 908*cdf0e10cSrcweir } 909*cdf0e10cSrcweir pModAct->Scale( fScaleX, fScaleY ); 910*cdf0e10cSrcweir } 911*cdf0e10cSrcweir rOutMtf.SetPrefSize( Size( FRound( aNewSize.Width() * fScaleX ), 912*cdf0e10cSrcweir FRound( aNewSize.Height() * fScaleY ) ) ); 913*cdf0e10cSrcweir } 914*cdf0e10cSrcweir 915*cdf0e10cSrcweir if( nNumBitmaps != 1 || bNonBitmapActionEncountered ) 916*cdf0e10cSrcweir { 917*cdf0e10cSrcweir if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsMirrored() || rAttr.IsRotated() || rAttr.IsTransparent() ) 918*cdf0e10cSrcweir ImplAdjust( rOutMtf, rAttr, ADJUSTMENT_ALL ); 919*cdf0e10cSrcweir 920*cdf0e10cSrcweir ImplDraw( pOut, rPt, rSz, rOutMtf, rAttr ); 921*cdf0e10cSrcweir rOutBmpEx = BitmapEx(); 922*cdf0e10cSrcweir } 923*cdf0e10cSrcweir 924*cdf0e10cSrcweir return sal_True; 925*cdf0e10cSrcweir } 926*cdf0e10cSrcweir 927*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 928*cdf0e10cSrcweir 929*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateScaled( const BitmapEx& rBmpEx, 930*cdf0e10cSrcweir long* pMapIX, long* pMapFX, long* pMapIY, long* pMapFY, 931*cdf0e10cSrcweir long nStartX, long nEndX, long nStartY, long nEndY, 932*cdf0e10cSrcweir BitmapEx& rOutBmpEx ) 933*cdf0e10cSrcweir { 934*cdf0e10cSrcweir Bitmap aBmp( rBmpEx.GetBitmap() ); 935*cdf0e10cSrcweir Bitmap aOutBmp; 936*cdf0e10cSrcweir BitmapReadAccess* pAcc = aBmp.AcquireReadAccess(); 937*cdf0e10cSrcweir BitmapWriteAccess* pWAcc; 938*cdf0e10cSrcweir BitmapColor aCol0, aCol1, aColRes; 939*cdf0e10cSrcweir const long nDstW = nEndX - nStartX + 1L; 940*cdf0e10cSrcweir const long nDstH = nEndY - nStartY + 1L; 941*cdf0e10cSrcweir long nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY; 942*cdf0e10cSrcweir long nXDst, nYDst; 943*cdf0e10cSrcweir sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1; 944*cdf0e10cSrcweir sal_Bool bRet = sal_False; 945*cdf0e10cSrcweir 946*cdf0e10cSrcweir DBG_ASSERT( aBmp.GetSizePixel() == rBmpEx.GetSizePixel(), 947*cdf0e10cSrcweir "GraphicManager::ImplCreateScaled(): bmp size inconsistent" ); 948*cdf0e10cSrcweir 949*cdf0e10cSrcweir if( pAcc ) 950*cdf0e10cSrcweir { 951*cdf0e10cSrcweir aOutBmp = Bitmap( Size( nDstW, nDstH ), 24 ); 952*cdf0e10cSrcweir pWAcc = aOutBmp.AcquireWriteAccess(); 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir if( pWAcc ) 955*cdf0e10cSrcweir { 956*cdf0e10cSrcweir if( pAcc->HasPalette() ) 957*cdf0e10cSrcweir { 958*cdf0e10cSrcweir if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 959*cdf0e10cSrcweir { 960*cdf0e10cSrcweir Scanline pLine0, pLine1; 961*cdf0e10cSrcweir 962*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 963*cdf0e10cSrcweir { 964*cdf0e10cSrcweir nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; 965*cdf0e10cSrcweir pLine0 = pAcc->GetScanline( nTmpY ); 966*cdf0e10cSrcweir pLine1 = pAcc->GetScanline( ++nTmpY ); 967*cdf0e10cSrcweir 968*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 969*cdf0e10cSrcweir { 970*cdf0e10cSrcweir nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; 971*cdf0e10cSrcweir 972*cdf0e10cSrcweir const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTmpX ] ); 973*cdf0e10cSrcweir const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTmpX ] ); 974*cdf0e10cSrcweir const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTmpX ] ); 975*cdf0e10cSrcweir const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTmpX ] ); 976*cdf0e10cSrcweir 977*cdf0e10cSrcweir cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX ); 978*cdf0e10cSrcweir cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX ); 979*cdf0e10cSrcweir cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX ); 980*cdf0e10cSrcweir 981*cdf0e10cSrcweir cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX ); 982*cdf0e10cSrcweir cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX ); 983*cdf0e10cSrcweir cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX ); 984*cdf0e10cSrcweir 985*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 986*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 987*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 988*cdf0e10cSrcweir pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 989*cdf0e10cSrcweir } 990*cdf0e10cSrcweir } 991*cdf0e10cSrcweir } 992*cdf0e10cSrcweir else 993*cdf0e10cSrcweir { 994*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 995*cdf0e10cSrcweir { 996*cdf0e10cSrcweir nTmpY = pMapIY[ nY ], nTmpFY = pMapFY[ nY ]; 997*cdf0e10cSrcweir 998*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 999*cdf0e10cSrcweir { 1000*cdf0e10cSrcweir nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; 1001*cdf0e10cSrcweir 1002*cdf0e10cSrcweir aCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, nTmpX ) ); 1003*cdf0e10cSrcweir aCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, ++nTmpX ) ); 1004*cdf0e10cSrcweir cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); 1005*cdf0e10cSrcweir cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); 1006*cdf0e10cSrcweir cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); 1007*cdf0e10cSrcweir 1008*cdf0e10cSrcweir aCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( ++nTmpY, nTmpX ) ); 1009*cdf0e10cSrcweir aCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY--, --nTmpX ) ); 1010*cdf0e10cSrcweir cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); 1011*cdf0e10cSrcweir cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); 1012*cdf0e10cSrcweir cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); 1013*cdf0e10cSrcweir 1014*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 1015*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 1016*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 1017*cdf0e10cSrcweir pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1018*cdf0e10cSrcweir } 1019*cdf0e10cSrcweir } 1020*cdf0e10cSrcweir } 1021*cdf0e10cSrcweir } 1022*cdf0e10cSrcweir else 1023*cdf0e10cSrcweir { 1024*cdf0e10cSrcweir if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 1025*cdf0e10cSrcweir { 1026*cdf0e10cSrcweir Scanline pLine0, pLine1, pTmp0, pTmp1; 1027*cdf0e10cSrcweir long nOff; 1028*cdf0e10cSrcweir 1029*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1030*cdf0e10cSrcweir { 1031*cdf0e10cSrcweir nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; 1032*cdf0e10cSrcweir pLine0 = pAcc->GetScanline( nTmpY ); 1033*cdf0e10cSrcweir pLine1 = pAcc->GetScanline( ++nTmpY ); 1034*cdf0e10cSrcweir 1035*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1036*cdf0e10cSrcweir { 1037*cdf0e10cSrcweir nOff = 3L * ( nTmpX = pMapIX[ nX ] ); 1038*cdf0e10cSrcweir nTmpFX = pMapFX[ nX ]; 1039*cdf0e10cSrcweir 1040*cdf0e10cSrcweir pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; 1041*cdf0e10cSrcweir cB0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1042*cdf0e10cSrcweir cG0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1043*cdf0e10cSrcweir cR0 = MAP( *pTmp0, *pTmp1, nTmpFX ); 1044*cdf0e10cSrcweir 1045*cdf0e10cSrcweir pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; 1046*cdf0e10cSrcweir cB1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1047*cdf0e10cSrcweir cG1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1048*cdf0e10cSrcweir cR1 = MAP( *pTmp0, *pTmp1, nTmpFX ); 1049*cdf0e10cSrcweir 1050*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 1051*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 1052*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 1053*cdf0e10cSrcweir pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1054*cdf0e10cSrcweir } 1055*cdf0e10cSrcweir } 1056*cdf0e10cSrcweir } 1057*cdf0e10cSrcweir else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ) 1058*cdf0e10cSrcweir { 1059*cdf0e10cSrcweir Scanline pLine0, pLine1, pTmp0, pTmp1; 1060*cdf0e10cSrcweir long nOff; 1061*cdf0e10cSrcweir 1062*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1063*cdf0e10cSrcweir { 1064*cdf0e10cSrcweir nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; 1065*cdf0e10cSrcweir pLine0 = pAcc->GetScanline( nTmpY ); 1066*cdf0e10cSrcweir pLine1 = pAcc->GetScanline( ++nTmpY ); 1067*cdf0e10cSrcweir 1068*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1069*cdf0e10cSrcweir { 1070*cdf0e10cSrcweir nOff = 3L * ( nTmpX = pMapIX[ nX ] ); 1071*cdf0e10cSrcweir nTmpFX = pMapFX[ nX ]; 1072*cdf0e10cSrcweir 1073*cdf0e10cSrcweir pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; 1074*cdf0e10cSrcweir cR0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1075*cdf0e10cSrcweir cG0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1076*cdf0e10cSrcweir cB0 = MAP( *pTmp0, *pTmp1, nTmpFX ); 1077*cdf0e10cSrcweir 1078*cdf0e10cSrcweir pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; 1079*cdf0e10cSrcweir cR1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1080*cdf0e10cSrcweir cG1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; 1081*cdf0e10cSrcweir cB1 = MAP( *pTmp0, *pTmp1, nTmpFX ); 1082*cdf0e10cSrcweir 1083*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 1084*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 1085*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 1086*cdf0e10cSrcweir pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1087*cdf0e10cSrcweir } 1088*cdf0e10cSrcweir } 1089*cdf0e10cSrcweir } 1090*cdf0e10cSrcweir else 1091*cdf0e10cSrcweir { 1092*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1093*cdf0e10cSrcweir { 1094*cdf0e10cSrcweir nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; 1095*cdf0e10cSrcweir 1096*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1097*cdf0e10cSrcweir { 1098*cdf0e10cSrcweir nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; 1099*cdf0e10cSrcweir 1100*cdf0e10cSrcweir aCol0 = pAcc->GetPixel( nTmpY, nTmpX ); 1101*cdf0e10cSrcweir aCol1 = pAcc->GetPixel( nTmpY, ++nTmpX ); 1102*cdf0e10cSrcweir cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); 1103*cdf0e10cSrcweir cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); 1104*cdf0e10cSrcweir cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); 1105*cdf0e10cSrcweir 1106*cdf0e10cSrcweir aCol1 = pAcc->GetPixel( ++nTmpY, nTmpX ); 1107*cdf0e10cSrcweir aCol0 = pAcc->GetPixel( nTmpY--, --nTmpX ); 1108*cdf0e10cSrcweir cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); 1109*cdf0e10cSrcweir cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); 1110*cdf0e10cSrcweir cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); 1111*cdf0e10cSrcweir 1112*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 1113*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 1114*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 1115*cdf0e10cSrcweir pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1116*cdf0e10cSrcweir } 1117*cdf0e10cSrcweir } 1118*cdf0e10cSrcweir } 1119*cdf0e10cSrcweir } 1120*cdf0e10cSrcweir 1121*cdf0e10cSrcweir aOutBmp.ReleaseAccess( pWAcc ); 1122*cdf0e10cSrcweir bRet = sal_True; 1123*cdf0e10cSrcweir } 1124*cdf0e10cSrcweir 1125*cdf0e10cSrcweir aBmp.ReleaseAccess( pAcc ); 1126*cdf0e10cSrcweir } 1127*cdf0e10cSrcweir 1128*cdf0e10cSrcweir if( bRet && rBmpEx.IsTransparent() ) 1129*cdf0e10cSrcweir { 1130*cdf0e10cSrcweir bRet = sal_False; 1131*cdf0e10cSrcweir 1132*cdf0e10cSrcweir if( rBmpEx.IsAlpha() ) 1133*cdf0e10cSrcweir { 1134*cdf0e10cSrcweir DBG_ASSERT( rBmpEx.GetAlpha().GetSizePixel() == rBmpEx.GetSizePixel(), 1135*cdf0e10cSrcweir "GraphicManager::ImplCreateScaled(): alpha mask size inconsistent" ); 1136*cdf0e10cSrcweir 1137*cdf0e10cSrcweir AlphaMask aAlpha( rBmpEx.GetAlpha() ); 1138*cdf0e10cSrcweir AlphaMask aOutAlpha; 1139*cdf0e10cSrcweir 1140*cdf0e10cSrcweir pAcc = aAlpha.AcquireReadAccess(); 1141*cdf0e10cSrcweir 1142*cdf0e10cSrcweir if( pAcc ) 1143*cdf0e10cSrcweir { 1144*cdf0e10cSrcweir aOutAlpha = AlphaMask( Size( nDstW, nDstH ) ); 1145*cdf0e10cSrcweir pWAcc = aOutAlpha.AcquireWriteAccess(); 1146*cdf0e10cSrcweir 1147*cdf0e10cSrcweir if( pWAcc ) 1148*cdf0e10cSrcweir { 1149*cdf0e10cSrcweir if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL && 1150*cdf0e10cSrcweir pWAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 1151*cdf0e10cSrcweir { 1152*cdf0e10cSrcweir Scanline pLine0, pLine1, pLineW; 1153*cdf0e10cSrcweir 1154*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1155*cdf0e10cSrcweir { 1156*cdf0e10cSrcweir nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; 1157*cdf0e10cSrcweir pLine0 = pAcc->GetScanline( nTmpY ); 1158*cdf0e10cSrcweir pLine1 = pAcc->GetScanline( ++nTmpY ); 1159*cdf0e10cSrcweir pLineW = pWAcc->GetScanline( nYDst ); 1160*cdf0e10cSrcweir 1161*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++, nXDst++ ) 1162*cdf0e10cSrcweir { 1163*cdf0e10cSrcweir nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; 1164*cdf0e10cSrcweir 1165*cdf0e10cSrcweir const long nAlpha0 = pLine0[ nTmpX ]; 1166*cdf0e10cSrcweir const long nAlpha2 = pLine1[ nTmpX ]; 1167*cdf0e10cSrcweir const long nAlpha1 = pLine0[ ++nTmpX ]; 1168*cdf0e10cSrcweir const long nAlpha3 = pLine1[ nTmpX ]; 1169*cdf0e10cSrcweir const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); 1170*cdf0e10cSrcweir const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); 1171*cdf0e10cSrcweir 1172*cdf0e10cSrcweir *pLineW++ = MAP( n0, n1, nTmpFY ); 1173*cdf0e10cSrcweir } 1174*cdf0e10cSrcweir } 1175*cdf0e10cSrcweir } 1176*cdf0e10cSrcweir else 1177*cdf0e10cSrcweir { 1178*cdf0e10cSrcweir BitmapColor aAlphaValue( 0 ); 1179*cdf0e10cSrcweir 1180*cdf0e10cSrcweir for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1181*cdf0e10cSrcweir { 1182*cdf0e10cSrcweir nTmpY = pMapIY[ nY ], nTmpFY = pMapFY[ nY ]; 1183*cdf0e10cSrcweir 1184*cdf0e10cSrcweir for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1185*cdf0e10cSrcweir { 1186*cdf0e10cSrcweir nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; 1187*cdf0e10cSrcweir 1188*cdf0e10cSrcweir long nAlpha0 = pAcc->GetPixel( nTmpY, nTmpX ).GetIndex(); 1189*cdf0e10cSrcweir long nAlpha1 = pAcc->GetPixel( nTmpY, ++nTmpX ).GetIndex(); 1190*cdf0e10cSrcweir const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); 1191*cdf0e10cSrcweir 1192*cdf0e10cSrcweir nAlpha1 = pAcc->GetPixel( ++nTmpY, nTmpX ).GetIndex(); 1193*cdf0e10cSrcweir nAlpha0 = pAcc->GetPixel( nTmpY--, --nTmpX ).GetIndex(); 1194*cdf0e10cSrcweir const long n1 = MAP( nAlpha0, nAlpha1, nTmpFX ); 1195*cdf0e10cSrcweir 1196*cdf0e10cSrcweir aAlphaValue.SetIndex( MAP( n0, n1, nTmpFY ) ); 1197*cdf0e10cSrcweir pWAcc->SetPixel( nYDst, nXDst++, aAlphaValue ); 1198*cdf0e10cSrcweir } 1199*cdf0e10cSrcweir } 1200*cdf0e10cSrcweir } 1201*cdf0e10cSrcweir 1202*cdf0e10cSrcweir aOutAlpha.ReleaseAccess( pWAcc ); 1203*cdf0e10cSrcweir bRet = sal_True; 1204*cdf0e10cSrcweir } 1205*cdf0e10cSrcweir 1206*cdf0e10cSrcweir aAlpha.ReleaseAccess( pAcc ); 1207*cdf0e10cSrcweir 1208*cdf0e10cSrcweir if( bRet ) 1209*cdf0e10cSrcweir rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha ); 1210*cdf0e10cSrcweir } 1211*cdf0e10cSrcweir } 1212*cdf0e10cSrcweir else 1213*cdf0e10cSrcweir { 1214*cdf0e10cSrcweir DBG_ASSERT( rBmpEx.GetMask().GetSizePixel() == rBmpEx.GetSizePixel(), 1215*cdf0e10cSrcweir "GraphicManager::ImplCreateScaled(): mask size inconsistent" ); 1216*cdf0e10cSrcweir 1217*cdf0e10cSrcweir Bitmap aMsk( rBmpEx.GetMask() ); 1218*cdf0e10cSrcweir Bitmap aOutMsk; 1219*cdf0e10cSrcweir 1220*cdf0e10cSrcweir pAcc = aMsk.AcquireReadAccess(); 1221*cdf0e10cSrcweir 1222*cdf0e10cSrcweir if( pAcc ) 1223*cdf0e10cSrcweir { 1224*cdf0e10cSrcweir // #i40115# Use the same palette for destination 1225*cdf0e10cSrcweir // bitmap. Otherwise, we'd have to color-map even the 1226*cdf0e10cSrcweir // case below, when both masks are one bit deep. 1227*cdf0e10cSrcweir if( pAcc->HasPalette() ) 1228*cdf0e10cSrcweir aOutMsk = Bitmap( Size( nDstW, nDstH ), 1229*cdf0e10cSrcweir 1, 1230*cdf0e10cSrcweir &pAcc->GetPalette() ); 1231*cdf0e10cSrcweir else 1232*cdf0e10cSrcweir aOutMsk = Bitmap( Size( nDstW, nDstH ), 1 ); 1233*cdf0e10cSrcweir 1234*cdf0e10cSrcweir pWAcc = aOutMsk.AcquireWriteAccess(); 1235*cdf0e10cSrcweir 1236*cdf0e10cSrcweir if( pWAcc ) 1237*cdf0e10cSrcweir { 1238*cdf0e10cSrcweir long* pMapLX = new long[ nDstW ]; 1239*cdf0e10cSrcweir long* pMapLY = new long[ nDstH ]; 1240*cdf0e10cSrcweir 1241*cdf0e10cSrcweir // create new horizontal mapping table 1242*cdf0e10cSrcweir for( nX = 0UL, nTmpX = nStartX; nX < nDstW; nTmpX++ ) 1243*cdf0e10cSrcweir pMapLX[ nX++ ] = FRound( (double) pMapIX[ nTmpX ] + pMapFX[ nTmpX ] / 1048576. ); 1244*cdf0e10cSrcweir 1245*cdf0e10cSrcweir // create new vertical mapping table 1246*cdf0e10cSrcweir for( nY = 0UL, nTmpY = nStartY; nY < nDstH; nTmpY++ ) 1247*cdf0e10cSrcweir pMapLY[ nY++ ] = FRound( (double) pMapIY[ nTmpY ] + pMapFY[ nTmpY ] / 1048576. ); 1248*cdf0e10cSrcweir 1249*cdf0e10cSrcweir // do normal scaling 1250*cdf0e10cSrcweir if( pAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 1251*cdf0e10cSrcweir pWAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL ) 1252*cdf0e10cSrcweir { 1253*cdf0e10cSrcweir // optimized 1254*cdf0e10cSrcweir for( nY = 0; nY < nDstH; nY++ ) 1255*cdf0e10cSrcweir { 1256*cdf0e10cSrcweir Scanline pSrc = pAcc->GetScanline( pMapLY[ nY ] ); 1257*cdf0e10cSrcweir Scanline pDst = pWAcc->GetScanline( nY ); 1258*cdf0e10cSrcweir 1259*cdf0e10cSrcweir for( nX = 0L; nX < nDstW; nX++ ) 1260*cdf0e10cSrcweir { 1261*cdf0e10cSrcweir const long nSrcX = pMapLX[ nX ]; 1262*cdf0e10cSrcweir 1263*cdf0e10cSrcweir if( pSrc[ nSrcX >> 3 ] & ( 1 << ( 7 - ( nSrcX & 7 ) ) ) ) 1264*cdf0e10cSrcweir pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) ); 1265*cdf0e10cSrcweir else 1266*cdf0e10cSrcweir pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) ); 1267*cdf0e10cSrcweir } 1268*cdf0e10cSrcweir } 1269*cdf0e10cSrcweir } 1270*cdf0e10cSrcweir else 1271*cdf0e10cSrcweir { 1272*cdf0e10cSrcweir const BitmapColor aB( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); 1273*cdf0e10cSrcweir const BitmapColor aWB( pWAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); 1274*cdf0e10cSrcweir const BitmapColor aWW( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 1275*cdf0e10cSrcweir 1276*cdf0e10cSrcweir if( pAcc->HasPalette() ) 1277*cdf0e10cSrcweir { 1278*cdf0e10cSrcweir for( nY = 0L; nY < nDstH; nY++ ) 1279*cdf0e10cSrcweir { 1280*cdf0e10cSrcweir for( nX = 0L; nX < nDstW; nX++ ) 1281*cdf0e10cSrcweir { 1282*cdf0e10cSrcweir if( pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( pMapLY[ nY ], pMapLX[ nX ] ) ) == aB ) 1283*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aWB ); 1284*cdf0e10cSrcweir else 1285*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aWW ); 1286*cdf0e10cSrcweir } 1287*cdf0e10cSrcweir } 1288*cdf0e10cSrcweir } 1289*cdf0e10cSrcweir else 1290*cdf0e10cSrcweir { 1291*cdf0e10cSrcweir for( nY = 0L; nY < nDstH; nY++ ) 1292*cdf0e10cSrcweir { 1293*cdf0e10cSrcweir for( nX = 0L; nX < nDstW; nX++ ) 1294*cdf0e10cSrcweir { 1295*cdf0e10cSrcweir if( pAcc->GetPixel( pMapLY[ nY ], pMapLX[ nX ] ) == aB ) 1296*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aWB ); 1297*cdf0e10cSrcweir else 1298*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aWW ); 1299*cdf0e10cSrcweir } 1300*cdf0e10cSrcweir } 1301*cdf0e10cSrcweir } 1302*cdf0e10cSrcweir } 1303*cdf0e10cSrcweir 1304*cdf0e10cSrcweir delete[] pMapLX; 1305*cdf0e10cSrcweir delete[] pMapLY; 1306*cdf0e10cSrcweir aOutMsk.ReleaseAccess( pWAcc ); 1307*cdf0e10cSrcweir bRet = sal_True; 1308*cdf0e10cSrcweir } 1309*cdf0e10cSrcweir 1310*cdf0e10cSrcweir aMsk.ReleaseAccess( pAcc ); 1311*cdf0e10cSrcweir 1312*cdf0e10cSrcweir if( bRet ) 1313*cdf0e10cSrcweir rOutBmpEx = BitmapEx( aOutBmp, aOutMsk ); 1314*cdf0e10cSrcweir } 1315*cdf0e10cSrcweir } 1316*cdf0e10cSrcweir 1317*cdf0e10cSrcweir if( !bRet ) 1318*cdf0e10cSrcweir rOutBmpEx = aOutBmp; 1319*cdf0e10cSrcweir } 1320*cdf0e10cSrcweir else 1321*cdf0e10cSrcweir rOutBmpEx = aOutBmp; 1322*cdf0e10cSrcweir 1323*cdf0e10cSrcweir return bRet; 1324*cdf0e10cSrcweir } 1325*cdf0e10cSrcweir 1326*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1327*cdf0e10cSrcweir 1328*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateRotatedScaled( const BitmapEx& rBmpEx, 1329*cdf0e10cSrcweir sal_uInt16 nRot10, const Size& /*rOutSzPix*/, const Size& rUnrotatedSzPix, 1330*cdf0e10cSrcweir long* pMapIX, long* pMapFX, long* pMapIY, long* pMapFY, 1331*cdf0e10cSrcweir long nStartX, long nEndX, long nStartY, long nEndY, 1332*cdf0e10cSrcweir BitmapEx& rOutBmpEx ) 1333*cdf0e10cSrcweir { 1334*cdf0e10cSrcweir Point aPt; 1335*cdf0e10cSrcweir Bitmap aBmp( rBmpEx.GetBitmap() ); 1336*cdf0e10cSrcweir Bitmap aOutBmp; 1337*cdf0e10cSrcweir BitmapReadAccess* pAcc = aBmp.AcquireReadAccess(); 1338*cdf0e10cSrcweir BitmapWriteAccess* pWAcc; 1339*cdf0e10cSrcweir Polygon aPoly( Rectangle( aPt, rUnrotatedSzPix ) ); aPoly.Rotate( Point(), nRot10 ); 1340*cdf0e10cSrcweir Rectangle aNewBound( aPoly.GetBoundRect() ); 1341*cdf0e10cSrcweir const double fCosAngle = cos( nRot10 * F_PI1800 ), fSinAngle = sin( nRot10 * F_PI1800 ); 1342*cdf0e10cSrcweir double fTmp; 1343*cdf0e10cSrcweir const long nDstW = nEndX - nStartX + 1L; 1344*cdf0e10cSrcweir const long nDstH = nEndY - nStartY + 1L; 1345*cdf0e10cSrcweir const long nUnRotW = rUnrotatedSzPix.Width(); 1346*cdf0e10cSrcweir const long nUnRotH = rUnrotatedSzPix.Height(); 1347*cdf0e10cSrcweir long* pCosX = new long[ nDstW ]; 1348*cdf0e10cSrcweir long* pSinX = new long[ nDstW ]; 1349*cdf0e10cSrcweir long* pCosY = new long[ nDstH ]; 1350*cdf0e10cSrcweir long* pSinY = new long[ nDstH ]; 1351*cdf0e10cSrcweir long nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY, nUnRotX, nUnRotY, nSinY, nCosY; 1352*cdf0e10cSrcweir sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1; 1353*cdf0e10cSrcweir sal_Bool bRet = sal_False; 1354*cdf0e10cSrcweir 1355*cdf0e10cSrcweir // create horizontal mapping table 1356*cdf0e10cSrcweir for( nX = 0L, nTmpX = aNewBound.Left() + nStartX; nX < nDstW; nX++ ) 1357*cdf0e10cSrcweir { 1358*cdf0e10cSrcweir pCosX[ nX ] = FRound( fCosAngle * ( fTmp = nTmpX++ << 8 ) ); 1359*cdf0e10cSrcweir pSinX[ nX ] = FRound( fSinAngle * fTmp ); 1360*cdf0e10cSrcweir } 1361*cdf0e10cSrcweir 1362*cdf0e10cSrcweir // create vertical mapping table 1363*cdf0e10cSrcweir for( nY = 0L, nTmpY = aNewBound.Top() + nStartY; nY < nDstH; nY++ ) 1364*cdf0e10cSrcweir { 1365*cdf0e10cSrcweir pCosY[ nY ] = FRound( fCosAngle * ( fTmp = nTmpY++ << 8 ) ); 1366*cdf0e10cSrcweir pSinY[ nY ] = FRound( fSinAngle * fTmp ); 1367*cdf0e10cSrcweir } 1368*cdf0e10cSrcweir 1369*cdf0e10cSrcweir if( pAcc ) 1370*cdf0e10cSrcweir { 1371*cdf0e10cSrcweir aOutBmp = Bitmap( Size( nDstW, nDstH ), 24 ); 1372*cdf0e10cSrcweir pWAcc = aOutBmp.AcquireWriteAccess(); 1373*cdf0e10cSrcweir 1374*cdf0e10cSrcweir if( pWAcc ) 1375*cdf0e10cSrcweir { 1376*cdf0e10cSrcweir BitmapColor aColRes; 1377*cdf0e10cSrcweir 1378*cdf0e10cSrcweir if( pAcc->HasPalette() ) 1379*cdf0e10cSrcweir { 1380*cdf0e10cSrcweir for( nY = 0; nY < nDstH; nY++ ) 1381*cdf0e10cSrcweir { 1382*cdf0e10cSrcweir nSinY = pSinY[ nY ]; 1383*cdf0e10cSrcweir nCosY = pCosY[ nY ]; 1384*cdf0e10cSrcweir 1385*cdf0e10cSrcweir for( nX = 0; nX < nDstW; nX++ ) 1386*cdf0e10cSrcweir { 1387*cdf0e10cSrcweir nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; 1388*cdf0e10cSrcweir nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; 1389*cdf0e10cSrcweir 1390*cdf0e10cSrcweir if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && 1391*cdf0e10cSrcweir ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) 1392*cdf0e10cSrcweir { 1393*cdf0e10cSrcweir nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; 1394*cdf0e10cSrcweir nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; 1395*cdf0e10cSrcweir 1396*cdf0e10cSrcweir const BitmapColor& rCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, nTmpX ) ); 1397*cdf0e10cSrcweir const BitmapColor& rCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, ++nTmpX ) ); 1398*cdf0e10cSrcweir cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX ); 1399*cdf0e10cSrcweir cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX ); 1400*cdf0e10cSrcweir cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX ); 1401*cdf0e10cSrcweir 1402*cdf0e10cSrcweir const BitmapColor& rCol3 = pAcc->GetPaletteColor( pAcc->GetPixel( ++nTmpY, nTmpX ) ); 1403*cdf0e10cSrcweir const BitmapColor& rCol2 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, --nTmpX ) ); 1404*cdf0e10cSrcweir cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX ); 1405*cdf0e10cSrcweir cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX ); 1406*cdf0e10cSrcweir cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX ); 1407*cdf0e10cSrcweir 1408*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 1409*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 1410*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 1411*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aColRes ); 1412*cdf0e10cSrcweir } 1413*cdf0e10cSrcweir } 1414*cdf0e10cSrcweir } 1415*cdf0e10cSrcweir } 1416*cdf0e10cSrcweir else 1417*cdf0e10cSrcweir { 1418*cdf0e10cSrcweir BitmapColor aCol0, aCol1; 1419*cdf0e10cSrcweir 1420*cdf0e10cSrcweir for( nY = 0; nY < nDstH; nY++ ) 1421*cdf0e10cSrcweir { 1422*cdf0e10cSrcweir nSinY = pSinY[ nY ]; 1423*cdf0e10cSrcweir nCosY = pCosY[ nY ]; 1424*cdf0e10cSrcweir 1425*cdf0e10cSrcweir for( nX = 0; nX < nDstW; nX++ ) 1426*cdf0e10cSrcweir { 1427*cdf0e10cSrcweir nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; 1428*cdf0e10cSrcweir nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; 1429*cdf0e10cSrcweir 1430*cdf0e10cSrcweir if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && 1431*cdf0e10cSrcweir ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) 1432*cdf0e10cSrcweir { 1433*cdf0e10cSrcweir nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; 1434*cdf0e10cSrcweir nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; 1435*cdf0e10cSrcweir 1436*cdf0e10cSrcweir aCol0 = pAcc->GetPixel( nTmpY, nTmpX ); 1437*cdf0e10cSrcweir aCol1 = pAcc->GetPixel( nTmpY, ++nTmpX ); 1438*cdf0e10cSrcweir cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); 1439*cdf0e10cSrcweir cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); 1440*cdf0e10cSrcweir cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); 1441*cdf0e10cSrcweir 1442*cdf0e10cSrcweir aCol1 = pAcc->GetPixel( ++nTmpY, nTmpX ); 1443*cdf0e10cSrcweir aCol0 = pAcc->GetPixel( nTmpY, --nTmpX ); 1444*cdf0e10cSrcweir cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); 1445*cdf0e10cSrcweir cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); 1446*cdf0e10cSrcweir cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); 1447*cdf0e10cSrcweir 1448*cdf0e10cSrcweir aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); 1449*cdf0e10cSrcweir aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); 1450*cdf0e10cSrcweir aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); 1451*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aColRes ); 1452*cdf0e10cSrcweir } 1453*cdf0e10cSrcweir } 1454*cdf0e10cSrcweir } 1455*cdf0e10cSrcweir } 1456*cdf0e10cSrcweir 1457*cdf0e10cSrcweir aOutBmp.ReleaseAccess( pWAcc ); 1458*cdf0e10cSrcweir bRet = sal_True; 1459*cdf0e10cSrcweir } 1460*cdf0e10cSrcweir 1461*cdf0e10cSrcweir aBmp.ReleaseAccess( pAcc ); 1462*cdf0e10cSrcweir } 1463*cdf0e10cSrcweir 1464*cdf0e10cSrcweir // mask processing 1465*cdf0e10cSrcweir if( bRet && ( rBmpEx.IsTransparent() || ( nRot10 != 900 && nRot10 != 1800 && nRot10 != 2700 ) ) ) 1466*cdf0e10cSrcweir { 1467*cdf0e10cSrcweir bRet = sal_False; 1468*cdf0e10cSrcweir 1469*cdf0e10cSrcweir if( rBmpEx.IsAlpha() ) 1470*cdf0e10cSrcweir { 1471*cdf0e10cSrcweir AlphaMask aAlpha( rBmpEx.GetAlpha() ); 1472*cdf0e10cSrcweir AlphaMask aOutAlpha; 1473*cdf0e10cSrcweir 1474*cdf0e10cSrcweir pAcc = aAlpha.AcquireReadAccess(); 1475*cdf0e10cSrcweir 1476*cdf0e10cSrcweir if( pAcc ) 1477*cdf0e10cSrcweir { 1478*cdf0e10cSrcweir aOutAlpha = AlphaMask( Size( nDstW, nDstH ) ); 1479*cdf0e10cSrcweir pWAcc = aOutAlpha.AcquireWriteAccess(); 1480*cdf0e10cSrcweir 1481*cdf0e10cSrcweir if( pWAcc ) 1482*cdf0e10cSrcweir { 1483*cdf0e10cSrcweir if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL && 1484*cdf0e10cSrcweir pWAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 1485*cdf0e10cSrcweir { 1486*cdf0e10cSrcweir Scanline pLine0, pLine1, pLineW; 1487*cdf0e10cSrcweir 1488*cdf0e10cSrcweir for( nY = 0; nY < nDstH; nY++ ) 1489*cdf0e10cSrcweir { 1490*cdf0e10cSrcweir nSinY = pSinY[ nY ], nCosY = pCosY[ nY ]; 1491*cdf0e10cSrcweir pLineW = pWAcc->GetScanline( nY ); 1492*cdf0e10cSrcweir 1493*cdf0e10cSrcweir for( nX = 0; nX < nDstW; nX++ ) 1494*cdf0e10cSrcweir { 1495*cdf0e10cSrcweir nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; 1496*cdf0e10cSrcweir nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; 1497*cdf0e10cSrcweir 1498*cdf0e10cSrcweir if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && 1499*cdf0e10cSrcweir ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) 1500*cdf0e10cSrcweir { 1501*cdf0e10cSrcweir nTmpX = pMapIX[ nUnRotX ], nTmpFX = pMapFX[ nUnRotX ]; 1502*cdf0e10cSrcweir nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; 1503*cdf0e10cSrcweir 1504*cdf0e10cSrcweir pLine0 = pAcc->GetScanline( nTmpY++ ); 1505*cdf0e10cSrcweir pLine1 = pAcc->GetScanline( nTmpY ); 1506*cdf0e10cSrcweir 1507*cdf0e10cSrcweir const long nAlpha0 = pLine0[ nTmpX ]; 1508*cdf0e10cSrcweir const long nAlpha2 = pLine1[ nTmpX++ ]; 1509*cdf0e10cSrcweir const long nAlpha1 = pLine0[ nTmpX ]; 1510*cdf0e10cSrcweir const long nAlpha3 = pLine1[ nTmpX ]; 1511*cdf0e10cSrcweir const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); 1512*cdf0e10cSrcweir const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); 1513*cdf0e10cSrcweir 1514*cdf0e10cSrcweir *pLineW++ = MAP( n0, n1, nTmpFY ); 1515*cdf0e10cSrcweir } 1516*cdf0e10cSrcweir else 1517*cdf0e10cSrcweir *pLineW++ = 255; 1518*cdf0e10cSrcweir } 1519*cdf0e10cSrcweir } 1520*cdf0e10cSrcweir } 1521*cdf0e10cSrcweir else 1522*cdf0e10cSrcweir { 1523*cdf0e10cSrcweir const BitmapColor aTrans( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 1524*cdf0e10cSrcweir BitmapColor aAlphaVal( 0 ); 1525*cdf0e10cSrcweir 1526*cdf0e10cSrcweir for( nY = 0; nY < nDstH; nY++ ) 1527*cdf0e10cSrcweir { 1528*cdf0e10cSrcweir nSinY = pSinY[ nY ], nCosY = pCosY[ nY ]; 1529*cdf0e10cSrcweir 1530*cdf0e10cSrcweir for( nX = 0; nX < nDstW; nX++ ) 1531*cdf0e10cSrcweir { 1532*cdf0e10cSrcweir nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; 1533*cdf0e10cSrcweir nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; 1534*cdf0e10cSrcweir 1535*cdf0e10cSrcweir if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && 1536*cdf0e10cSrcweir ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) 1537*cdf0e10cSrcweir { 1538*cdf0e10cSrcweir nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; 1539*cdf0e10cSrcweir nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; 1540*cdf0e10cSrcweir 1541*cdf0e10cSrcweir const long nAlpha0 = pAcc->GetPixel( nTmpY, nTmpX ).GetIndex(); 1542*cdf0e10cSrcweir const long nAlpha1 = pAcc->GetPixel( nTmpY, ++nTmpX ).GetIndex(); 1543*cdf0e10cSrcweir const long nAlpha3 = pAcc->GetPixel( ++nTmpY, nTmpX ).GetIndex(); 1544*cdf0e10cSrcweir const long nAlpha2 = pAcc->GetPixel( nTmpY, --nTmpX ).GetIndex(); 1545*cdf0e10cSrcweir const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); 1546*cdf0e10cSrcweir const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); 1547*cdf0e10cSrcweir 1548*cdf0e10cSrcweir aAlphaVal.SetIndex( MAP( n0, n1, nTmpFY ) ); 1549*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aAlphaVal ); 1550*cdf0e10cSrcweir } 1551*cdf0e10cSrcweir else 1552*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aTrans ); 1553*cdf0e10cSrcweir } 1554*cdf0e10cSrcweir } 1555*cdf0e10cSrcweir } 1556*cdf0e10cSrcweir 1557*cdf0e10cSrcweir aOutAlpha.ReleaseAccess( pWAcc ); 1558*cdf0e10cSrcweir bRet = sal_True; 1559*cdf0e10cSrcweir } 1560*cdf0e10cSrcweir 1561*cdf0e10cSrcweir aAlpha.ReleaseAccess( pAcc ); 1562*cdf0e10cSrcweir } 1563*cdf0e10cSrcweir 1564*cdf0e10cSrcweir if( bRet ) 1565*cdf0e10cSrcweir rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha ); 1566*cdf0e10cSrcweir } 1567*cdf0e10cSrcweir else 1568*cdf0e10cSrcweir { 1569*cdf0e10cSrcweir Bitmap aOutMsk( Size( nDstW, nDstH ), 1 ); 1570*cdf0e10cSrcweir pWAcc = aOutMsk.AcquireWriteAccess(); 1571*cdf0e10cSrcweir 1572*cdf0e10cSrcweir if( pWAcc ) 1573*cdf0e10cSrcweir { 1574*cdf0e10cSrcweir Bitmap aMsk( rBmpEx.GetMask() ); 1575*cdf0e10cSrcweir const BitmapColor aB( pWAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); 1576*cdf0e10cSrcweir const BitmapColor aW( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 1577*cdf0e10cSrcweir BitmapReadAccess* pMAcc = NULL; 1578*cdf0e10cSrcweir 1579*cdf0e10cSrcweir if( !aMsk || ( ( pMAcc = aMsk.AcquireReadAccess() ) != NULL ) ) 1580*cdf0e10cSrcweir { 1581*cdf0e10cSrcweir long* pMapLX = new long[ nUnRotW ]; 1582*cdf0e10cSrcweir long* pMapLY = new long[ nUnRotH ]; 1583*cdf0e10cSrcweir BitmapColor aTestB; 1584*cdf0e10cSrcweir 1585*cdf0e10cSrcweir if( pMAcc ) 1586*cdf0e10cSrcweir aTestB = pMAcc->GetBestMatchingColor( Color( COL_BLACK ) ); 1587*cdf0e10cSrcweir 1588*cdf0e10cSrcweir // create new horizontal mapping table 1589*cdf0e10cSrcweir for( nX = 0UL; nX < nUnRotW; nX++ ) 1590*cdf0e10cSrcweir pMapLX[ nX ] = FRound( (double) pMapIX[ nX ] + pMapFX[ nX ] / 1048576. ); 1591*cdf0e10cSrcweir 1592*cdf0e10cSrcweir // create new vertical mapping table 1593*cdf0e10cSrcweir for( nY = 0UL; nY < nUnRotH; nY++ ) 1594*cdf0e10cSrcweir pMapLY[ nY ] = FRound( (double) pMapIY[ nY ] + pMapFY[ nY ] / 1048576. ); 1595*cdf0e10cSrcweir 1596*cdf0e10cSrcweir // do mask rotation 1597*cdf0e10cSrcweir for( nY = 0; nY < nDstH; nY++ ) 1598*cdf0e10cSrcweir { 1599*cdf0e10cSrcweir nSinY = pSinY[ nY ]; 1600*cdf0e10cSrcweir nCosY = pCosY[ nY ]; 1601*cdf0e10cSrcweir 1602*cdf0e10cSrcweir for( nX = 0; nX < nDstW; nX++ ) 1603*cdf0e10cSrcweir { 1604*cdf0e10cSrcweir nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; 1605*cdf0e10cSrcweir nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; 1606*cdf0e10cSrcweir 1607*cdf0e10cSrcweir if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && 1608*cdf0e10cSrcweir ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) 1609*cdf0e10cSrcweir { 1610*cdf0e10cSrcweir if( pMAcc ) 1611*cdf0e10cSrcweir { 1612*cdf0e10cSrcweir if( pMAcc->GetPixel( pMapLY[ nUnRotY ], pMapLX[ nUnRotX ] ) == aTestB ) 1613*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aB ); 1614*cdf0e10cSrcweir else 1615*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aW ); 1616*cdf0e10cSrcweir } 1617*cdf0e10cSrcweir else 1618*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aB ); 1619*cdf0e10cSrcweir } 1620*cdf0e10cSrcweir else 1621*cdf0e10cSrcweir pWAcc->SetPixel( nY, nX, aW ); 1622*cdf0e10cSrcweir } 1623*cdf0e10cSrcweir } 1624*cdf0e10cSrcweir 1625*cdf0e10cSrcweir delete[] pMapLX; 1626*cdf0e10cSrcweir delete[] pMapLY; 1627*cdf0e10cSrcweir 1628*cdf0e10cSrcweir if( pMAcc ) 1629*cdf0e10cSrcweir aMsk.ReleaseAccess( pMAcc ); 1630*cdf0e10cSrcweir 1631*cdf0e10cSrcweir bRet = sal_True; 1632*cdf0e10cSrcweir } 1633*cdf0e10cSrcweir 1634*cdf0e10cSrcweir aOutMsk.ReleaseAccess( pWAcc ); 1635*cdf0e10cSrcweir } 1636*cdf0e10cSrcweir 1637*cdf0e10cSrcweir if( bRet ) 1638*cdf0e10cSrcweir rOutBmpEx = BitmapEx( aOutBmp, aOutMsk ); 1639*cdf0e10cSrcweir } 1640*cdf0e10cSrcweir 1641*cdf0e10cSrcweir if( !bRet ) 1642*cdf0e10cSrcweir rOutBmpEx = aOutBmp; 1643*cdf0e10cSrcweir } 1644*cdf0e10cSrcweir else 1645*cdf0e10cSrcweir rOutBmpEx = aOutBmp; 1646*cdf0e10cSrcweir 1647*cdf0e10cSrcweir delete[] pSinX; 1648*cdf0e10cSrcweir delete[] pCosX; 1649*cdf0e10cSrcweir delete[] pSinY; 1650*cdf0e10cSrcweir delete[] pCosY; 1651*cdf0e10cSrcweir 1652*cdf0e10cSrcweir return bRet; 1653*cdf0e10cSrcweir } 1654*cdf0e10cSrcweir 1655*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1656*cdf0e10cSrcweir 1657*cdf0e10cSrcweir void GraphicManager::ImplAdjust( BitmapEx& rBmpEx, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags ) 1658*cdf0e10cSrcweir { 1659*cdf0e10cSrcweir GraphicAttr aAttr( rAttr ); 1660*cdf0e10cSrcweir 1661*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() ) 1662*cdf0e10cSrcweir { 1663*cdf0e10cSrcweir switch( aAttr.GetDrawMode() ) 1664*cdf0e10cSrcweir { 1665*cdf0e10cSrcweir case( GRAPHICDRAWMODE_MONO ): 1666*cdf0e10cSrcweir rBmpEx.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); 1667*cdf0e10cSrcweir break; 1668*cdf0e10cSrcweir 1669*cdf0e10cSrcweir case( GRAPHICDRAWMODE_GREYS ): 1670*cdf0e10cSrcweir rBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS ); 1671*cdf0e10cSrcweir break; 1672*cdf0e10cSrcweir 1673*cdf0e10cSrcweir case( GRAPHICDRAWMODE_WATERMARK ): 1674*cdf0e10cSrcweir { 1675*cdf0e10cSrcweir aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); 1676*cdf0e10cSrcweir aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); 1677*cdf0e10cSrcweir } 1678*cdf0e10cSrcweir break; 1679*cdf0e10cSrcweir 1680*cdf0e10cSrcweir default: 1681*cdf0e10cSrcweir break; 1682*cdf0e10cSrcweir } 1683*cdf0e10cSrcweir } 1684*cdf0e10cSrcweir 1685*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() ) 1686*cdf0e10cSrcweir { 1687*cdf0e10cSrcweir rBmpEx.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), 1688*cdf0e10cSrcweir aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), 1689*cdf0e10cSrcweir aAttr.GetGamma(), aAttr.IsInvert() ); 1690*cdf0e10cSrcweir } 1691*cdf0e10cSrcweir 1692*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() ) 1693*cdf0e10cSrcweir { 1694*cdf0e10cSrcweir rBmpEx.Mirror( aAttr.GetMirrorFlags() ); 1695*cdf0e10cSrcweir } 1696*cdf0e10cSrcweir 1697*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() ) 1698*cdf0e10cSrcweir { 1699*cdf0e10cSrcweir rBmpEx.Rotate( aAttr.GetRotation(), Color( COL_TRANSPARENT ) ); 1700*cdf0e10cSrcweir } 1701*cdf0e10cSrcweir 1702*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() ) 1703*cdf0e10cSrcweir { 1704*cdf0e10cSrcweir AlphaMask aAlpha; 1705*cdf0e10cSrcweir sal_uInt8 cTrans = aAttr.GetTransparency(); 1706*cdf0e10cSrcweir 1707*cdf0e10cSrcweir if( !rBmpEx.IsTransparent() ) 1708*cdf0e10cSrcweir aAlpha = AlphaMask( rBmpEx.GetSizePixel(), &cTrans ); 1709*cdf0e10cSrcweir else if( !rBmpEx.IsAlpha() ) 1710*cdf0e10cSrcweir { 1711*cdf0e10cSrcweir aAlpha = rBmpEx.GetMask(); 1712*cdf0e10cSrcweir aAlpha.Replace( 0, cTrans ); 1713*cdf0e10cSrcweir } 1714*cdf0e10cSrcweir else 1715*cdf0e10cSrcweir { 1716*cdf0e10cSrcweir aAlpha = rBmpEx.GetAlpha(); 1717*cdf0e10cSrcweir BitmapWriteAccess* pA = aAlpha.AcquireWriteAccess(); 1718*cdf0e10cSrcweir 1719*cdf0e10cSrcweir if( pA ) 1720*cdf0e10cSrcweir { 1721*cdf0e10cSrcweir sal_uLong nTrans = cTrans, nNewTrans; 1722*cdf0e10cSrcweir const long nWidth = pA->Width(), nHeight = pA->Height(); 1723*cdf0e10cSrcweir 1724*cdf0e10cSrcweir if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 1725*cdf0e10cSrcweir { 1726*cdf0e10cSrcweir for( long nY = 0; nY < nHeight; nY++ ) 1727*cdf0e10cSrcweir { 1728*cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nY ); 1729*cdf0e10cSrcweir 1730*cdf0e10cSrcweir for( long nX = 0; nX < nWidth; nX++ ) 1731*cdf0e10cSrcweir { 1732*cdf0e10cSrcweir nNewTrans = nTrans + *pAScan; 1733*cdf0e10cSrcweir *pAScan++ = (sal_uInt8) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ); 1734*cdf0e10cSrcweir } 1735*cdf0e10cSrcweir } 1736*cdf0e10cSrcweir } 1737*cdf0e10cSrcweir else 1738*cdf0e10cSrcweir { 1739*cdf0e10cSrcweir BitmapColor aAlphaValue( 0 ); 1740*cdf0e10cSrcweir 1741*cdf0e10cSrcweir for( long nY = 0; nY < nHeight; nY++ ) 1742*cdf0e10cSrcweir { 1743*cdf0e10cSrcweir for( long nX = 0; nX < nWidth; nX++ ) 1744*cdf0e10cSrcweir { 1745*cdf0e10cSrcweir nNewTrans = nTrans + pA->GetPixel( nY, nX ).GetIndex(); 1746*cdf0e10cSrcweir aAlphaValue.SetIndex( (sal_uInt8) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ) ); 1747*cdf0e10cSrcweir pA->SetPixel( nY, nX, aAlphaValue ); 1748*cdf0e10cSrcweir } 1749*cdf0e10cSrcweir } 1750*cdf0e10cSrcweir } 1751*cdf0e10cSrcweir 1752*cdf0e10cSrcweir aAlpha.ReleaseAccess( pA ); 1753*cdf0e10cSrcweir } 1754*cdf0e10cSrcweir } 1755*cdf0e10cSrcweir 1756*cdf0e10cSrcweir rBmpEx = BitmapEx( rBmpEx.GetBitmap(), aAlpha ); 1757*cdf0e10cSrcweir } 1758*cdf0e10cSrcweir } 1759*cdf0e10cSrcweir 1760*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1761*cdf0e10cSrcweir 1762*cdf0e10cSrcweir void GraphicManager::ImplAdjust( GDIMetaFile& rMtf, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags ) 1763*cdf0e10cSrcweir { 1764*cdf0e10cSrcweir GraphicAttr aAttr( rAttr ); 1765*cdf0e10cSrcweir 1766*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() ) 1767*cdf0e10cSrcweir { 1768*cdf0e10cSrcweir switch( aAttr.GetDrawMode() ) 1769*cdf0e10cSrcweir { 1770*cdf0e10cSrcweir case( GRAPHICDRAWMODE_MONO ): 1771*cdf0e10cSrcweir rMtf.Convert( MTF_CONVERSION_1BIT_THRESHOLD ); 1772*cdf0e10cSrcweir break; 1773*cdf0e10cSrcweir 1774*cdf0e10cSrcweir case( GRAPHICDRAWMODE_GREYS ): 1775*cdf0e10cSrcweir rMtf.Convert( MTF_CONVERSION_8BIT_GREYS ); 1776*cdf0e10cSrcweir break; 1777*cdf0e10cSrcweir 1778*cdf0e10cSrcweir case( GRAPHICDRAWMODE_WATERMARK ): 1779*cdf0e10cSrcweir { 1780*cdf0e10cSrcweir aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); 1781*cdf0e10cSrcweir aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); 1782*cdf0e10cSrcweir } 1783*cdf0e10cSrcweir break; 1784*cdf0e10cSrcweir 1785*cdf0e10cSrcweir default: 1786*cdf0e10cSrcweir break; 1787*cdf0e10cSrcweir } 1788*cdf0e10cSrcweir } 1789*cdf0e10cSrcweir 1790*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() ) 1791*cdf0e10cSrcweir { 1792*cdf0e10cSrcweir rMtf.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), 1793*cdf0e10cSrcweir aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), 1794*cdf0e10cSrcweir aAttr.GetGamma(), aAttr.IsInvert() ); 1795*cdf0e10cSrcweir } 1796*cdf0e10cSrcweir 1797*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() ) 1798*cdf0e10cSrcweir { 1799*cdf0e10cSrcweir rMtf.Mirror( aAttr.GetMirrorFlags() ); 1800*cdf0e10cSrcweir } 1801*cdf0e10cSrcweir 1802*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() ) 1803*cdf0e10cSrcweir { 1804*cdf0e10cSrcweir rMtf.Rotate( aAttr.GetRotation() ); 1805*cdf0e10cSrcweir } 1806*cdf0e10cSrcweir 1807*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() ) 1808*cdf0e10cSrcweir { 1809*cdf0e10cSrcweir DBG_ERROR( "Missing implementation: Mtf-Transparency" ); 1810*cdf0e10cSrcweir } 1811*cdf0e10cSrcweir } 1812*cdf0e10cSrcweir 1813*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1814*cdf0e10cSrcweir 1815*cdf0e10cSrcweir void GraphicManager::ImplAdjust( Animation& rAnimation, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags ) 1816*cdf0e10cSrcweir { 1817*cdf0e10cSrcweir GraphicAttr aAttr( rAttr ); 1818*cdf0e10cSrcweir 1819*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() ) 1820*cdf0e10cSrcweir { 1821*cdf0e10cSrcweir switch( aAttr.GetDrawMode() ) 1822*cdf0e10cSrcweir { 1823*cdf0e10cSrcweir case( GRAPHICDRAWMODE_MONO ): 1824*cdf0e10cSrcweir rAnimation.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); 1825*cdf0e10cSrcweir break; 1826*cdf0e10cSrcweir 1827*cdf0e10cSrcweir case( GRAPHICDRAWMODE_GREYS ): 1828*cdf0e10cSrcweir rAnimation.Convert( BMP_CONVERSION_8BIT_GREYS ); 1829*cdf0e10cSrcweir break; 1830*cdf0e10cSrcweir 1831*cdf0e10cSrcweir case( GRAPHICDRAWMODE_WATERMARK ): 1832*cdf0e10cSrcweir { 1833*cdf0e10cSrcweir aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); 1834*cdf0e10cSrcweir aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); 1835*cdf0e10cSrcweir } 1836*cdf0e10cSrcweir break; 1837*cdf0e10cSrcweir 1838*cdf0e10cSrcweir default: 1839*cdf0e10cSrcweir break; 1840*cdf0e10cSrcweir } 1841*cdf0e10cSrcweir } 1842*cdf0e10cSrcweir 1843*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() ) 1844*cdf0e10cSrcweir { 1845*cdf0e10cSrcweir rAnimation.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), 1846*cdf0e10cSrcweir aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), 1847*cdf0e10cSrcweir aAttr.GetGamma(), aAttr.IsInvert() ); 1848*cdf0e10cSrcweir } 1849*cdf0e10cSrcweir 1850*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() ) 1851*cdf0e10cSrcweir { 1852*cdf0e10cSrcweir rAnimation.Mirror( aAttr.GetMirrorFlags() ); 1853*cdf0e10cSrcweir } 1854*cdf0e10cSrcweir 1855*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() ) 1856*cdf0e10cSrcweir { 1857*cdf0e10cSrcweir DBG_ERROR( "Missing implementation: Animation-Rotation" ); 1858*cdf0e10cSrcweir } 1859*cdf0e10cSrcweir 1860*cdf0e10cSrcweir if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() ) 1861*cdf0e10cSrcweir { 1862*cdf0e10cSrcweir DBG_ERROR( "Missing implementation: Animation-Transparency" ); 1863*cdf0e10cSrcweir } 1864*cdf0e10cSrcweir } 1865*cdf0e10cSrcweir 1866*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1867*cdf0e10cSrcweir 1868*cdf0e10cSrcweir void GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, const Size& rSz, 1869*cdf0e10cSrcweir const GDIMetaFile& rMtf, const GraphicAttr& rAttr ) 1870*cdf0e10cSrcweir { 1871*cdf0e10cSrcweir sal_uInt16 nRot10 = rAttr.GetRotation() % 3600; 1872*cdf0e10cSrcweir Point aOutPt( rPt ); 1873*cdf0e10cSrcweir Size aOutSz( rSz ); 1874*cdf0e10cSrcweir 1875*cdf0e10cSrcweir if( nRot10 ) 1876*cdf0e10cSrcweir { 1877*cdf0e10cSrcweir Polygon aPoly( Rectangle( aOutPt, aOutSz ) ); 1878*cdf0e10cSrcweir 1879*cdf0e10cSrcweir aPoly.Rotate( aOutPt, nRot10 ); 1880*cdf0e10cSrcweir const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); 1881*cdf0e10cSrcweir aOutPt = aRotBoundRect.TopLeft(); 1882*cdf0e10cSrcweir aOutSz = aRotBoundRect.GetSize(); 1883*cdf0e10cSrcweir } 1884*cdf0e10cSrcweir 1885*cdf0e10cSrcweir pOut->Push( PUSH_CLIPREGION ); 1886*cdf0e10cSrcweir pOut->IntersectClipRegion( Rectangle( aOutPt, aOutSz ) ); 1887*cdf0e10cSrcweir 1888*cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 1889*cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).Play( pOut, aOutPt, aOutSz ); 1890*cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 1891*cdf0e10cSrcweir 1892*cdf0e10cSrcweir pOut->Pop(); 1893*cdf0e10cSrcweir } 1894*cdf0e10cSrcweir 1895*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1896*cdf0e10cSrcweir 1897*cdf0e10cSrcweir struct ImplTileInfo 1898*cdf0e10cSrcweir { 1899*cdf0e10cSrcweir ImplTileInfo() : aTileTopLeft(), aNextTileTopLeft(), aTileSizePixel(), nTilesEmptyX(0), nTilesEmptyY(0) {} 1900*cdf0e10cSrcweir 1901*cdf0e10cSrcweir Point aTileTopLeft; // top, left position of the rendered tile 1902*cdf0e10cSrcweir Point aNextTileTopLeft; // top, left position for next recursion 1903*cdf0e10cSrcweir // level's tile 1904*cdf0e10cSrcweir Size aTileSizePixel; // size of the generated tile (might 1905*cdf0e10cSrcweir // differ from 1906*cdf0e10cSrcweir // aNextTileTopLeft-aTileTopLeft, because 1907*cdf0e10cSrcweir // this is nExponent*prevTileSize. The 1908*cdf0e10cSrcweir // generated tile is always nExponent 1909*cdf0e10cSrcweir // times the previous tile, such that it 1910*cdf0e10cSrcweir // can be used in the next stage. The 1911*cdf0e10cSrcweir // required area coverage is often 1912*cdf0e10cSrcweir // less. The extraneous area covered is 1913*cdf0e10cSrcweir // later overwritten by the next stage) 1914*cdf0e10cSrcweir int nTilesEmptyX; // number of original tiles empty right of 1915*cdf0e10cSrcweir // this tile. This counts from 1916*cdf0e10cSrcweir // aNextTileTopLeft, i.e. the additional 1917*cdf0e10cSrcweir // area covered by aTileSizePixel is not 1918*cdf0e10cSrcweir // considered here. This is for 1919*cdf0e10cSrcweir // unification purposes, as the iterative 1920*cdf0e10cSrcweir // calculation of the next level's empty 1921*cdf0e10cSrcweir // tiles has to be based on this value. 1922*cdf0e10cSrcweir int nTilesEmptyY; // as above, for Y 1923*cdf0e10cSrcweir }; 1924*cdf0e10cSrcweir 1925*cdf0e10cSrcweir 1926*cdf0e10cSrcweir bool GraphicObject::ImplRenderTempTile( VirtualDevice& rVDev, int nExponent, 1927*cdf0e10cSrcweir int nNumTilesX, int nNumTilesY, 1928*cdf0e10cSrcweir const Size& rTileSizePixel, 1929*cdf0e10cSrcweir const GraphicAttr* pAttr, sal_uLong nFlags ) 1930*cdf0e10cSrcweir { 1931*cdf0e10cSrcweir if( nExponent <= 1 ) 1932*cdf0e10cSrcweir return false; 1933*cdf0e10cSrcweir 1934*cdf0e10cSrcweir // determine MSB factor 1935*cdf0e10cSrcweir int nMSBFactor( 1 ); 1936*cdf0e10cSrcweir while( nNumTilesX / nMSBFactor != 0 || 1937*cdf0e10cSrcweir nNumTilesY / nMSBFactor != 0 ) 1938*cdf0e10cSrcweir { 1939*cdf0e10cSrcweir nMSBFactor *= nExponent; 1940*cdf0e10cSrcweir } 1941*cdf0e10cSrcweir 1942*cdf0e10cSrcweir // one less 1943*cdf0e10cSrcweir nMSBFactor /= nExponent; 1944*cdf0e10cSrcweir 1945*cdf0e10cSrcweir ImplTileInfo aTileInfo; 1946*cdf0e10cSrcweir 1947*cdf0e10cSrcweir // #105229# Switch off mapping (converting to logic and back to 1948*cdf0e10cSrcweir // pixel might cause roundoff errors) 1949*cdf0e10cSrcweir sal_Bool bOldMap( rVDev.IsMapModeEnabled() ); 1950*cdf0e10cSrcweir rVDev.EnableMapMode( sal_False ); 1951*cdf0e10cSrcweir 1952*cdf0e10cSrcweir bool bRet( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor, nNumTilesX, nNumTilesY, 1953*cdf0e10cSrcweir nNumTilesX, nNumTilesY, rTileSizePixel, pAttr, nFlags, aTileInfo ) ); 1954*cdf0e10cSrcweir 1955*cdf0e10cSrcweir rVDev.EnableMapMode( bOldMap ); 1956*cdf0e10cSrcweir 1957*cdf0e10cSrcweir return bRet; 1958*cdf0e10cSrcweir } 1959*cdf0e10cSrcweir 1960*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 1961*cdf0e10cSrcweir 1962*cdf0e10cSrcweir // define for debug drawings 1963*cdf0e10cSrcweir //#define DBG_TEST 1964*cdf0e10cSrcweir 1965*cdf0e10cSrcweir // see header comment. this works similar to base conversion of a 1966*cdf0e10cSrcweir // number, i.e. if the exponent is 10, then the number for every tile 1967*cdf0e10cSrcweir // size is given by the decimal place of the corresponding decimal 1968*cdf0e10cSrcweir // representation. 1969*cdf0e10cSrcweir bool GraphicObject::ImplRenderTileRecursive( VirtualDevice& rVDev, int nExponent, int nMSBFactor, 1970*cdf0e10cSrcweir int nNumOrigTilesX, int nNumOrigTilesY, 1971*cdf0e10cSrcweir int nRemainderTilesX, int nRemainderTilesY, 1972*cdf0e10cSrcweir const Size& rTileSizePixel, const GraphicAttr* pAttr, 1973*cdf0e10cSrcweir sal_uLong nFlags, ImplTileInfo& rTileInfo ) 1974*cdf0e10cSrcweir { 1975*cdf0e10cSrcweir // gets loaded with our tile bitmap 1976*cdf0e10cSrcweir GraphicObject aTmpGraphic; 1977*cdf0e10cSrcweir 1978*cdf0e10cSrcweir // stores a flag that renders the zero'th tile position 1979*cdf0e10cSrcweir // (i.e. (0,0)+rCurrPos) only if we're at the bottom of the 1980*cdf0e10cSrcweir // recursion stack. All other position already have that tile 1981*cdf0e10cSrcweir // rendered, because the lower levels painted their generated tile 1982*cdf0e10cSrcweir // there. 1983*cdf0e10cSrcweir bool bNoFirstTileDraw( false ); 1984*cdf0e10cSrcweir 1985*cdf0e10cSrcweir // what's left when we're done with our tile size 1986*cdf0e10cSrcweir const int nNewRemainderX( nRemainderTilesX % nMSBFactor ); 1987*cdf0e10cSrcweir const int nNewRemainderY( nRemainderTilesY % nMSBFactor ); 1988*cdf0e10cSrcweir 1989*cdf0e10cSrcweir // gets filled out from the recursive call with info of what's 1990*cdf0e10cSrcweir // been generated 1991*cdf0e10cSrcweir ImplTileInfo aTileInfo; 1992*cdf0e10cSrcweir 1993*cdf0e10cSrcweir // current output position while drawing 1994*cdf0e10cSrcweir Point aCurrPos; 1995*cdf0e10cSrcweir int nX, nY; 1996*cdf0e10cSrcweir 1997*cdf0e10cSrcweir // check for recursion's end condition: LSB place reached? 1998*cdf0e10cSrcweir if( nMSBFactor == 1 ) 1999*cdf0e10cSrcweir { 2000*cdf0e10cSrcweir aTmpGraphic = *this; 2001*cdf0e10cSrcweir 2002*cdf0e10cSrcweir // set initial tile size -> orig size 2003*cdf0e10cSrcweir aTileInfo.aTileSizePixel = rTileSizePixel; 2004*cdf0e10cSrcweir aTileInfo.nTilesEmptyX = nNumOrigTilesX; 2005*cdf0e10cSrcweir aTileInfo.nTilesEmptyY = nNumOrigTilesY; 2006*cdf0e10cSrcweir } 2007*cdf0e10cSrcweir else if( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor/nExponent, 2008*cdf0e10cSrcweir nNumOrigTilesX, nNumOrigTilesY, 2009*cdf0e10cSrcweir nNewRemainderX, nNewRemainderY, 2010*cdf0e10cSrcweir rTileSizePixel, pAttr, nFlags, aTileInfo ) ) 2011*cdf0e10cSrcweir { 2012*cdf0e10cSrcweir // extract generated tile -> see comment on the first loop below 2013*cdf0e10cSrcweir BitmapEx aTileBitmap( rVDev.GetBitmap( aTileInfo.aTileTopLeft, aTileInfo.aTileSizePixel ) ); 2014*cdf0e10cSrcweir 2015*cdf0e10cSrcweir aTmpGraphic = GraphicObject( aTileBitmap ); 2016*cdf0e10cSrcweir 2017*cdf0e10cSrcweir // fill stripes left over from upstream levels: 2018*cdf0e10cSrcweir // 2019*cdf0e10cSrcweir // x0000 2020*cdf0e10cSrcweir // 0 2021*cdf0e10cSrcweir // 0 2022*cdf0e10cSrcweir // 0 2023*cdf0e10cSrcweir // 0 2024*cdf0e10cSrcweir // 2025*cdf0e10cSrcweir // where x denotes the place filled by our recursive predecessors 2026*cdf0e10cSrcweir 2027*cdf0e10cSrcweir // check whether we have to fill stripes here. Although not 2028*cdf0e10cSrcweir // obvious, there is one case where we can skip this step: if 2029*cdf0e10cSrcweir // the previous recursion level (the one who filled our 2030*cdf0e10cSrcweir // aTileInfo) had zero area to fill, then there are no white 2031*cdf0e10cSrcweir // stripes left, naturally. This happens if the digit 2032*cdf0e10cSrcweir // associated to that level has a zero, and can be checked via 2033*cdf0e10cSrcweir // aTileTopLeft==aNextTileTopLeft. 2034*cdf0e10cSrcweir if( aTileInfo.aTileTopLeft != aTileInfo.aNextTileTopLeft ) 2035*cdf0e10cSrcweir { 2036*cdf0e10cSrcweir // now fill one row from aTileInfo.aNextTileTopLeft.X() all 2037*cdf0e10cSrcweir // the way to the right 2038*cdf0e10cSrcweir aCurrPos.X() = aTileInfo.aNextTileTopLeft.X(); 2039*cdf0e10cSrcweir aCurrPos.Y() = aTileInfo.aTileTopLeft.Y(); 2040*cdf0e10cSrcweir for( nX=0; nX < aTileInfo.nTilesEmptyX; nX += nMSBFactor ) 2041*cdf0e10cSrcweir { 2042*cdf0e10cSrcweir if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) ) 2043*cdf0e10cSrcweir return false; 2044*cdf0e10cSrcweir 2045*cdf0e10cSrcweir aCurrPos.X() += aTileInfo.aTileSizePixel.Width(); 2046*cdf0e10cSrcweir } 2047*cdf0e10cSrcweir 2048*cdf0e10cSrcweir #ifdef DBG_TEST 2049*cdf0e10cSrcweir // rVDev.SetFillColor( COL_WHITE ); 2050*cdf0e10cSrcweir rVDev.SetFillColor(); 2051*cdf0e10cSrcweir rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) ); 2052*cdf0e10cSrcweir rVDev.DrawEllipse( Rectangle(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y(), 2053*cdf0e10cSrcweir aTileInfo.aNextTileTopLeft.X() - 1 + (aTileInfo.nTilesEmptyX/nMSBFactor)*aTileInfo.aTileSizePixel.Width(), 2054*cdf0e10cSrcweir aTileInfo.aTileTopLeft.Y() + aTileInfo.aTileSizePixel.Height() - 1) ); 2055*cdf0e10cSrcweir #endif 2056*cdf0e10cSrcweir 2057*cdf0e10cSrcweir // now fill one column from aTileInfo.aNextTileTopLeft.Y() all 2058*cdf0e10cSrcweir // the way to the bottom 2059*cdf0e10cSrcweir aCurrPos.X() = aTileInfo.aTileTopLeft.X(); 2060*cdf0e10cSrcweir aCurrPos.Y() = aTileInfo.aNextTileTopLeft.Y(); 2061*cdf0e10cSrcweir for( nY=0; nY < aTileInfo.nTilesEmptyY; nY += nMSBFactor ) 2062*cdf0e10cSrcweir { 2063*cdf0e10cSrcweir if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) ) 2064*cdf0e10cSrcweir return false; 2065*cdf0e10cSrcweir 2066*cdf0e10cSrcweir aCurrPos.Y() += aTileInfo.aTileSizePixel.Height(); 2067*cdf0e10cSrcweir } 2068*cdf0e10cSrcweir 2069*cdf0e10cSrcweir #ifdef DBG_TEST 2070*cdf0e10cSrcweir rVDev.DrawEllipse( Rectangle(aTileInfo.aTileTopLeft.X(), aTileInfo.aNextTileTopLeft.Y(), 2071*cdf0e10cSrcweir aTileInfo.aTileTopLeft.X() + aTileInfo.aTileSizePixel.Width() - 1, 2072*cdf0e10cSrcweir aTileInfo.aNextTileTopLeft.Y() - 1 + (aTileInfo.nTilesEmptyY/nMSBFactor)*aTileInfo.aTileSizePixel.Height()) ); 2073*cdf0e10cSrcweir #endif 2074*cdf0e10cSrcweir } 2075*cdf0e10cSrcweir else 2076*cdf0e10cSrcweir { 2077*cdf0e10cSrcweir // Thought that aTileInfo.aNextTileTopLeft tile has always 2078*cdf0e10cSrcweir // been drawn already, but that's wrong: typically, 2079*cdf0e10cSrcweir // _parts_ of that tile have been drawn, since the 2080*cdf0e10cSrcweir // previous level generated the tile there. But when 2081*cdf0e10cSrcweir // aTileInfo.aNextTileTopLeft!=aTileInfo.aTileTopLeft, the 2082*cdf0e10cSrcweir // difference between these two values is missing in the 2083*cdf0e10cSrcweir // lower right corner of this first tile. So, can do that 2084*cdf0e10cSrcweir // only here. 2085*cdf0e10cSrcweir bNoFirstTileDraw = true; 2086*cdf0e10cSrcweir } 2087*cdf0e10cSrcweir } 2088*cdf0e10cSrcweir else 2089*cdf0e10cSrcweir { 2090*cdf0e10cSrcweir return false; 2091*cdf0e10cSrcweir } 2092*cdf0e10cSrcweir 2093*cdf0e10cSrcweir // calc number of original tiles in our drawing area without 2094*cdf0e10cSrcweir // remainder 2095*cdf0e10cSrcweir nRemainderTilesX -= nNewRemainderX; 2096*cdf0e10cSrcweir nRemainderTilesY -= nNewRemainderY; 2097*cdf0e10cSrcweir 2098*cdf0e10cSrcweir // fill tile info for calling method 2099*cdf0e10cSrcweir rTileInfo.aTileTopLeft = aTileInfo.aNextTileTopLeft; 2100*cdf0e10cSrcweir rTileInfo.aNextTileTopLeft = Point( rTileInfo.aTileTopLeft.X() + rTileSizePixel.Width()*nRemainderTilesX, 2101*cdf0e10cSrcweir rTileInfo.aTileTopLeft.Y() + rTileSizePixel.Height()*nRemainderTilesY ); 2102*cdf0e10cSrcweir rTileInfo.aTileSizePixel = Size( rTileSizePixel.Width()*nMSBFactor*nExponent, 2103*cdf0e10cSrcweir rTileSizePixel.Height()*nMSBFactor*nExponent ); 2104*cdf0e10cSrcweir rTileInfo.nTilesEmptyX = aTileInfo.nTilesEmptyX - nRemainderTilesX; 2105*cdf0e10cSrcweir rTileInfo.nTilesEmptyY = aTileInfo.nTilesEmptyY - nRemainderTilesY; 2106*cdf0e10cSrcweir 2107*cdf0e10cSrcweir // init output position 2108*cdf0e10cSrcweir aCurrPos = aTileInfo.aNextTileTopLeft; 2109*cdf0e10cSrcweir 2110*cdf0e10cSrcweir // fill our drawing area. Fill possibly more, to create the next 2111*cdf0e10cSrcweir // bigger tile size -> see bitmap extraction above. This does no 2112*cdf0e10cSrcweir // harm, since everything right or below our actual area is 2113*cdf0e10cSrcweir // overdrawn by our caller. Just in case we're in the last level, 2114*cdf0e10cSrcweir // we don't draw beyond the right or bottom border. 2115*cdf0e10cSrcweir for( nY=0; nY < aTileInfo.nTilesEmptyY && nY < nExponent*nMSBFactor; nY += nMSBFactor ) 2116*cdf0e10cSrcweir { 2117*cdf0e10cSrcweir aCurrPos.X() = aTileInfo.aNextTileTopLeft.X(); 2118*cdf0e10cSrcweir 2119*cdf0e10cSrcweir for( nX=0; nX < aTileInfo.nTilesEmptyX && nX < nExponent*nMSBFactor; nX += nMSBFactor ) 2120*cdf0e10cSrcweir { 2121*cdf0e10cSrcweir if( bNoFirstTileDraw ) 2122*cdf0e10cSrcweir bNoFirstTileDraw = false; // don't draw first tile position 2123*cdf0e10cSrcweir else if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) ) 2124*cdf0e10cSrcweir return false; 2125*cdf0e10cSrcweir 2126*cdf0e10cSrcweir aCurrPos.X() += aTileInfo.aTileSizePixel.Width(); 2127*cdf0e10cSrcweir } 2128*cdf0e10cSrcweir 2129*cdf0e10cSrcweir aCurrPos.Y() += aTileInfo.aTileSizePixel.Height(); 2130*cdf0e10cSrcweir } 2131*cdf0e10cSrcweir 2132*cdf0e10cSrcweir #ifdef DBG_TEST 2133*cdf0e10cSrcweir // rVDev.SetFillColor( COL_WHITE ); 2134*cdf0e10cSrcweir rVDev.SetFillColor(); 2135*cdf0e10cSrcweir rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) ); 2136*cdf0e10cSrcweir rVDev.DrawRect( Rectangle((rTileInfo.aTileTopLeft.X())*rTileSizePixel.Width(), 2137*cdf0e10cSrcweir (rTileInfo.aTileTopLeft.Y())*rTileSizePixel.Height(), 2138*cdf0e10cSrcweir (rTileInfo.aNextTileTopLeft.X())*rTileSizePixel.Width()-1, 2139*cdf0e10cSrcweir (rTileInfo.aNextTileTopLeft.Y())*rTileSizePixel.Height()-1) ); 2140*cdf0e10cSrcweir #endif 2141*cdf0e10cSrcweir 2142*cdf0e10cSrcweir return true; 2143*cdf0e10cSrcweir } 2144*cdf0e10cSrcweir 2145*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 2146*cdf0e10cSrcweir 2147*cdf0e10cSrcweir bool GraphicObject::ImplDrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSizePixel, 2148*cdf0e10cSrcweir const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D ) 2149*cdf0e10cSrcweir { 2150*cdf0e10cSrcweir // how many tiles to generate per recursion step 2151*cdf0e10cSrcweir enum{ SubdivisionExponent=2 }; 2152*cdf0e10cSrcweir 2153*cdf0e10cSrcweir const MapMode aOutMapMode( pOut->GetMapMode() ); 2154*cdf0e10cSrcweir const MapMode aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() ); 2155*cdf0e10cSrcweir bool bRet( false ); 2156*cdf0e10cSrcweir 2157*cdf0e10cSrcweir // #i42643# Casting to Int64, to avoid integer overflow for 2158*cdf0e10cSrcweir // huge-DPI output devices 2159*cdf0e10cSrcweir if( GetGraphic().GetType() == GRAPHIC_BITMAP && 2160*cdf0e10cSrcweir static_cast<sal_Int64>(rSizePixel.Width()) * rSizePixel.Height() < 2161*cdf0e10cSrcweir static_cast<sal_Int64>(nTileCacheSize1D)*nTileCacheSize1D ) 2162*cdf0e10cSrcweir { 2163*cdf0e10cSrcweir // First combine very small bitmaps into a larger tile 2164*cdf0e10cSrcweir // =================================================== 2165*cdf0e10cSrcweir 2166*cdf0e10cSrcweir VirtualDevice aVDev; 2167*cdf0e10cSrcweir const int nNumTilesInCacheX( (nTileCacheSize1D + rSizePixel.Width()-1) / rSizePixel.Width() ); 2168*cdf0e10cSrcweir const int nNumTilesInCacheY( (nTileCacheSize1D + rSizePixel.Height()-1) / rSizePixel.Height() ); 2169*cdf0e10cSrcweir 2170*cdf0e10cSrcweir aVDev.SetOutputSizePixel( Size( nNumTilesInCacheX*rSizePixel.Width(), 2171*cdf0e10cSrcweir nNumTilesInCacheY*rSizePixel.Height() ) ); 2172*cdf0e10cSrcweir aVDev.SetMapMode( aMapMode ); 2173*cdf0e10cSrcweir 2174*cdf0e10cSrcweir // draw bitmap content 2175*cdf0e10cSrcweir if( ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX, 2176*cdf0e10cSrcweir nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) ) 2177*cdf0e10cSrcweir { 2178*cdf0e10cSrcweir BitmapEx aTileBitmap( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) ); 2179*cdf0e10cSrcweir 2180*cdf0e10cSrcweir // draw alpha content, if any 2181*cdf0e10cSrcweir if( IsTransparent() ) 2182*cdf0e10cSrcweir { 2183*cdf0e10cSrcweir GraphicObject aAlphaGraphic; 2184*cdf0e10cSrcweir 2185*cdf0e10cSrcweir if( GetGraphic().IsAlpha() ) 2186*cdf0e10cSrcweir aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetAlpha().GetBitmap() ); 2187*cdf0e10cSrcweir else 2188*cdf0e10cSrcweir aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetMask() ); 2189*cdf0e10cSrcweir 2190*cdf0e10cSrcweir if( aAlphaGraphic.ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX, 2191*cdf0e10cSrcweir nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) ) 2192*cdf0e10cSrcweir { 2193*cdf0e10cSrcweir // Combine bitmap and alpha/mask 2194*cdf0e10cSrcweir if( GetGraphic().IsAlpha() ) 2195*cdf0e10cSrcweir aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(), 2196*cdf0e10cSrcweir AlphaMask( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) ) ); 2197*cdf0e10cSrcweir else 2198*cdf0e10cSrcweir aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(), 2199*cdf0e10cSrcweir aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ).CreateMask( Color(COL_WHITE) ) ); 2200*cdf0e10cSrcweir } 2201*cdf0e10cSrcweir } 2202*cdf0e10cSrcweir 2203*cdf0e10cSrcweir // paint generated tile 2204*cdf0e10cSrcweir GraphicObject aTmpGraphic( aTileBitmap ); 2205*cdf0e10cSrcweir bRet = aTmpGraphic.ImplDrawTiled( pOut, rArea, 2206*cdf0e10cSrcweir aTileBitmap.GetSizePixel(), 2207*cdf0e10cSrcweir rOffset, pAttr, nFlags, nTileCacheSize1D ); 2208*cdf0e10cSrcweir } 2209*cdf0e10cSrcweir } 2210*cdf0e10cSrcweir else 2211*cdf0e10cSrcweir { 2212*cdf0e10cSrcweir const Size aOutOffset( pOut->LogicToPixel( rOffset, aOutMapMode ) ); 2213*cdf0e10cSrcweir const Rectangle aOutArea( pOut->LogicToPixel( rArea, aOutMapMode ) ); 2214*cdf0e10cSrcweir 2215*cdf0e10cSrcweir // number of invisible (because out-of-area) tiles 2216*cdf0e10cSrcweir int nInvisibleTilesX; 2217*cdf0e10cSrcweir int nInvisibleTilesY; 2218*cdf0e10cSrcweir 2219*cdf0e10cSrcweir // round towards -infty for negative offset 2220*cdf0e10cSrcweir if( aOutOffset.Width() < 0 ) 2221*cdf0e10cSrcweir nInvisibleTilesX = (aOutOffset.Width() - rSizePixel.Width() + 1) / rSizePixel.Width(); 2222*cdf0e10cSrcweir else 2223*cdf0e10cSrcweir nInvisibleTilesX = aOutOffset.Width() / rSizePixel.Width(); 2224*cdf0e10cSrcweir 2225*cdf0e10cSrcweir // round towards -infty for negative offset 2226*cdf0e10cSrcweir if( aOutOffset.Height() < 0 ) 2227*cdf0e10cSrcweir nInvisibleTilesY = (aOutOffset.Height() - rSizePixel.Height() + 1) / rSizePixel.Height(); 2228*cdf0e10cSrcweir else 2229*cdf0e10cSrcweir nInvisibleTilesY = aOutOffset.Height() / rSizePixel.Height(); 2230*cdf0e10cSrcweir 2231*cdf0e10cSrcweir // origin from where to 'virtually' start drawing in pixel 2232*cdf0e10cSrcweir const Point aOutOrigin( pOut->LogicToPixel( Point( rArea.Left() - rOffset.Width(), 2233*cdf0e10cSrcweir rArea.Top() - rOffset.Height() ) ) ); 2234*cdf0e10cSrcweir // position in pixel from where to really start output 2235*cdf0e10cSrcweir const Point aOutStart( aOutOrigin.X() + nInvisibleTilesX*rSizePixel.Width(), 2236*cdf0e10cSrcweir aOutOrigin.Y() + nInvisibleTilesY*rSizePixel.Height() ); 2237*cdf0e10cSrcweir 2238*cdf0e10cSrcweir pOut->Push( PUSH_CLIPREGION ); 2239*cdf0e10cSrcweir pOut->IntersectClipRegion( rArea ); 2240*cdf0e10cSrcweir 2241*cdf0e10cSrcweir // Paint all tiles 2242*cdf0e10cSrcweir // =============== 2243*cdf0e10cSrcweir 2244*cdf0e10cSrcweir bRet = ImplDrawTiled( *pOut, aOutStart, 2245*cdf0e10cSrcweir (aOutArea.GetWidth() + aOutArea.Left() - aOutStart.X() + rSizePixel.Width() - 1) / rSizePixel.Width(), 2246*cdf0e10cSrcweir (aOutArea.GetHeight() + aOutArea.Top() - aOutStart.Y() + rSizePixel.Height() - 1) / rSizePixel.Height(), 2247*cdf0e10cSrcweir rSizePixel, pAttr, nFlags ); 2248*cdf0e10cSrcweir 2249*cdf0e10cSrcweir pOut->Pop(); 2250*cdf0e10cSrcweir } 2251*cdf0e10cSrcweir 2252*cdf0e10cSrcweir return bRet; 2253*cdf0e10cSrcweir } 2254*cdf0e10cSrcweir 2255*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 2256*cdf0e10cSrcweir 2257*cdf0e10cSrcweir bool GraphicObject::ImplDrawTiled( OutputDevice& rOut, const Point& rPosPixel, 2258*cdf0e10cSrcweir int nNumTilesX, int nNumTilesY, 2259*cdf0e10cSrcweir const Size& rTileSizePixel, const GraphicAttr* pAttr, sal_uLong nFlags ) 2260*cdf0e10cSrcweir { 2261*cdf0e10cSrcweir Point aCurrPos( rPosPixel ); 2262*cdf0e10cSrcweir Size aTileSizeLogic( rOut.PixelToLogic( rTileSizePixel ) ); 2263*cdf0e10cSrcweir int nX, nY; 2264*cdf0e10cSrcweir 2265*cdf0e10cSrcweir // #107607# Use logical coordinates for metafile playing, too 2266*cdf0e10cSrcweir bool bDrawInPixel( rOut.GetConnectMetaFile() == NULL && GRAPHIC_BITMAP == GetType() ); 2267*cdf0e10cSrcweir sal_Bool bRet( sal_False ); 2268*cdf0e10cSrcweir 2269*cdf0e10cSrcweir // #105229# Switch off mapping (converting to logic and back to 2270*cdf0e10cSrcweir // pixel might cause roundoff errors) 2271*cdf0e10cSrcweir sal_Bool bOldMap( rOut.IsMapModeEnabled() ); 2272*cdf0e10cSrcweir 2273*cdf0e10cSrcweir if( bDrawInPixel ) 2274*cdf0e10cSrcweir rOut.EnableMapMode( sal_False ); 2275*cdf0e10cSrcweir 2276*cdf0e10cSrcweir for( nY=0; nY < nNumTilesY; ++nY ) 2277*cdf0e10cSrcweir { 2278*cdf0e10cSrcweir aCurrPos.X() = rPosPixel.X(); 2279*cdf0e10cSrcweir 2280*cdf0e10cSrcweir for( nX=0; nX < nNumTilesX; ++nX ) 2281*cdf0e10cSrcweir { 2282*cdf0e10cSrcweir // #105229# work with pixel coordinates here, mapping is disabled! 2283*cdf0e10cSrcweir // #104004# don't disable mapping for metafile recordings 2284*cdf0e10cSrcweir // #108412# don't quit the loop if one draw fails 2285*cdf0e10cSrcweir 2286*cdf0e10cSrcweir // update return value. This method should return true, if 2287*cdf0e10cSrcweir // at least one of the looped Draws succeeded. 2288*cdf0e10cSrcweir bRet |= Draw( &rOut, 2289*cdf0e10cSrcweir bDrawInPixel ? aCurrPos : rOut.PixelToLogic( aCurrPos ), 2290*cdf0e10cSrcweir bDrawInPixel ? rTileSizePixel : aTileSizeLogic, 2291*cdf0e10cSrcweir pAttr, nFlags ); 2292*cdf0e10cSrcweir 2293*cdf0e10cSrcweir aCurrPos.X() += rTileSizePixel.Width(); 2294*cdf0e10cSrcweir } 2295*cdf0e10cSrcweir 2296*cdf0e10cSrcweir aCurrPos.Y() += rTileSizePixel.Height(); 2297*cdf0e10cSrcweir } 2298*cdf0e10cSrcweir 2299*cdf0e10cSrcweir if( bDrawInPixel ) 2300*cdf0e10cSrcweir rOut.EnableMapMode( bOldMap ); 2301*cdf0e10cSrcweir 2302*cdf0e10cSrcweir return bRet; 2303*cdf0e10cSrcweir } 2304*cdf0e10cSrcweir 2305*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 2306*cdf0e10cSrcweir 2307*cdf0e10cSrcweir void GraphicObject::ImplTransformBitmap( BitmapEx& rBmpEx, 2308*cdf0e10cSrcweir const GraphicAttr& rAttr, 2309*cdf0e10cSrcweir const Size& rCropLeftTop, 2310*cdf0e10cSrcweir const Size& rCropRightBottom, 2311*cdf0e10cSrcweir const Rectangle& rCropRect, 2312*cdf0e10cSrcweir const Size& rDstSize, 2313*cdf0e10cSrcweir sal_Bool bEnlarge ) const 2314*cdf0e10cSrcweir { 2315*cdf0e10cSrcweir // #107947# Extracted from svdograf.cxx 2316*cdf0e10cSrcweir 2317*cdf0e10cSrcweir // #104115# Crop the bitmap 2318*cdf0e10cSrcweir if( rAttr.IsCropped() ) 2319*cdf0e10cSrcweir { 2320*cdf0e10cSrcweir rBmpEx.Crop( rCropRect ); 2321*cdf0e10cSrcweir 2322*cdf0e10cSrcweir // #104115# Negative crop sizes mean: enlarge bitmap and pad 2323*cdf0e10cSrcweir if( bEnlarge && ( 2324*cdf0e10cSrcweir rCropLeftTop.Width() < 0 || 2325*cdf0e10cSrcweir rCropLeftTop.Height() < 0 || 2326*cdf0e10cSrcweir rCropRightBottom.Width() < 0 || 2327*cdf0e10cSrcweir rCropRightBottom.Height() < 0 ) ) 2328*cdf0e10cSrcweir { 2329*cdf0e10cSrcweir Size aBmpSize( rBmpEx.GetSizePixel() ); 2330*cdf0e10cSrcweir sal_Int32 nPadLeft( rCropLeftTop.Width() < 0 ? -rCropLeftTop.Width() : 0 ); 2331*cdf0e10cSrcweir sal_Int32 nPadTop( rCropLeftTop.Height() < 0 ? -rCropLeftTop.Height() : 0 ); 2332*cdf0e10cSrcweir sal_Int32 nPadTotalWidth( aBmpSize.Width() + nPadLeft + (rCropRightBottom.Width() < 0 ? -rCropRightBottom.Width() : 0) ); 2333*cdf0e10cSrcweir sal_Int32 nPadTotalHeight( aBmpSize.Height() + nPadTop + (rCropRightBottom.Height() < 0 ? -rCropRightBottom.Height() : 0) ); 2334*cdf0e10cSrcweir 2335*cdf0e10cSrcweir BitmapEx aBmpEx2; 2336*cdf0e10cSrcweir 2337*cdf0e10cSrcweir if( rBmpEx.IsTransparent() ) 2338*cdf0e10cSrcweir { 2339*cdf0e10cSrcweir if( rBmpEx.IsAlpha() ) 2340*cdf0e10cSrcweir aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetAlpha() ); 2341*cdf0e10cSrcweir else 2342*cdf0e10cSrcweir aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetMask() ); 2343*cdf0e10cSrcweir } 2344*cdf0e10cSrcweir else 2345*cdf0e10cSrcweir { 2346*cdf0e10cSrcweir // #104115# Generate mask bitmap and init to zero 2347*cdf0e10cSrcweir Bitmap aMask( aBmpSize, 1 ); 2348*cdf0e10cSrcweir aMask.Erase( Color(0,0,0) ); 2349*cdf0e10cSrcweir 2350*cdf0e10cSrcweir // #104115# Always generate transparent bitmap, we need the border transparent 2351*cdf0e10cSrcweir aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), aMask ); 2352*cdf0e10cSrcweir 2353*cdf0e10cSrcweir // #104115# Add opaque mask to source bitmap, otherwise the destination remains transparent 2354*cdf0e10cSrcweir rBmpEx = aBmpEx2; 2355*cdf0e10cSrcweir } 2356*cdf0e10cSrcweir 2357*cdf0e10cSrcweir aBmpEx2.SetSizePixel( Size(nPadTotalWidth, nPadTotalHeight) ); 2358*cdf0e10cSrcweir aBmpEx2.Erase( Color(0xFF,0,0,0) ); 2359*cdf0e10cSrcweir aBmpEx2.CopyPixel( Rectangle( Point(nPadLeft, nPadTop), aBmpSize ), Rectangle( Point(0, 0), aBmpSize ), &rBmpEx ); 2360*cdf0e10cSrcweir rBmpEx = aBmpEx2; 2361*cdf0e10cSrcweir } 2362*cdf0e10cSrcweir } 2363*cdf0e10cSrcweir 2364*cdf0e10cSrcweir const Size aSizePixel( rBmpEx.GetSizePixel() ); 2365*cdf0e10cSrcweir 2366*cdf0e10cSrcweir if( rAttr.GetRotation() != 0 && !IsAnimated() ) 2367*cdf0e10cSrcweir { 2368*cdf0e10cSrcweir if( aSizePixel.Width() && aSizePixel.Height() && rDstSize.Width() && rDstSize.Height() ) 2369*cdf0e10cSrcweir { 2370*cdf0e10cSrcweir double fSrcWH = (double) aSizePixel.Width() / aSizePixel.Height(); 2371*cdf0e10cSrcweir double fDstWH = (double) rDstSize.Width() / rDstSize.Height(); 2372*cdf0e10cSrcweir double fScaleX = 1.0, fScaleY = 1.0; 2373*cdf0e10cSrcweir 2374*cdf0e10cSrcweir // always choose scaling to shrink bitmap 2375*cdf0e10cSrcweir if( fSrcWH < fDstWH ) 2376*cdf0e10cSrcweir fScaleY = aSizePixel.Width() / ( fDstWH * aSizePixel.Height() ); 2377*cdf0e10cSrcweir else 2378*cdf0e10cSrcweir fScaleX = fDstWH * aSizePixel.Height() / aSizePixel.Width(); 2379*cdf0e10cSrcweir 2380*cdf0e10cSrcweir rBmpEx.Scale( fScaleX, fScaleY ); 2381*cdf0e10cSrcweir } 2382*cdf0e10cSrcweir } 2383*cdf0e10cSrcweir } 2384