1464702f4SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3464702f4SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4464702f4SAndrew Rist * or more contributor license agreements. See the NOTICE file 5464702f4SAndrew Rist * distributed with this work for additional information 6464702f4SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7464702f4SAndrew Rist * to you under the Apache License, Version 2.0 (the 8464702f4SAndrew Rist * "License"); you may not use this file except in compliance 9464702f4SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11464702f4SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13464702f4SAndrew Rist * Unless required by applicable law or agreed to in writing, 14464702f4SAndrew Rist * software distributed under the License is distributed on an 15464702f4SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16464702f4SAndrew Rist * KIND, either express or implied. See the License for the 17464702f4SAndrew Rist * specific language governing permissions and limitations 18464702f4SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20464702f4SAndrew Rist *************************************************************/ 21464702f4SAndrew Rist 22464702f4SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <vclhelperbufferdevice.hxx> 28cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx> 29cdf0e10cSrcweir #include <vcl/bitmapex.hxx> 30cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 31cdf0e10cSrcweir #include <tools/stream.hxx> 32*ce37d08fSArmin Le Grand #include <vcl/timer.hxx> 33*ce37d08fSArmin Le Grand #include <comphelper/broadcasthelper.hxx> 34*ce37d08fSArmin Le Grand 35*ce37d08fSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 36*ce37d08fSArmin Le Grand // buffered VDev usage 37*ce37d08fSArmin Le Grand 38*ce37d08fSArmin Le Grand namespace 39*ce37d08fSArmin Le Grand { 40*ce37d08fSArmin Le Grand typedef ::std::vector< VirtualDevice* > aBuffers; 41*ce37d08fSArmin Le Grand 42*ce37d08fSArmin Le Grand class VDevBuffer : public Timer, protected comphelper::OBaseMutex 43*ce37d08fSArmin Le Grand { 44*ce37d08fSArmin Le Grand private: 45*ce37d08fSArmin Le Grand aBuffers maBuffers; 46*ce37d08fSArmin Le Grand 47*ce37d08fSArmin Le Grand public: 48*ce37d08fSArmin Le Grand VDevBuffer(); 49*ce37d08fSArmin Le Grand virtual ~VDevBuffer(); 50*ce37d08fSArmin Le Grand 51*ce37d08fSArmin Le Grand VirtualDevice* alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono); 52*ce37d08fSArmin Le Grand void free(VirtualDevice& rDevice); 53*ce37d08fSArmin Le Grand 54*ce37d08fSArmin Le Grand // Timer virtuals 55*ce37d08fSArmin Le Grand virtual void Timeout(); 56*ce37d08fSArmin Le Grand }; 57*ce37d08fSArmin Le Grand 58*ce37d08fSArmin Le Grand VDevBuffer::VDevBuffer() 59*ce37d08fSArmin Le Grand : Timer(), 60*ce37d08fSArmin Le Grand maBuffers() 61*ce37d08fSArmin Le Grand { 62*ce37d08fSArmin Le Grand SetTimeout(10L * 1000L); // ten seconds 63*ce37d08fSArmin Le Grand } 64*ce37d08fSArmin Le Grand 65*ce37d08fSArmin Le Grand VDevBuffer::~VDevBuffer() 66*ce37d08fSArmin Le Grand { 67*ce37d08fSArmin Le Grand ::osl::MutexGuard aGuard(m_aMutex); 68*ce37d08fSArmin Le Grand Stop(); 69*ce37d08fSArmin Le Grand 70*ce37d08fSArmin Le Grand while(!maBuffers.empty()) 71*ce37d08fSArmin Le Grand { 72*ce37d08fSArmin Le Grand delete *(maBuffers.end() - 1); 73*ce37d08fSArmin Le Grand maBuffers.pop_back(); 74*ce37d08fSArmin Le Grand } 75*ce37d08fSArmin Le Grand } 76*ce37d08fSArmin Le Grand 77*ce37d08fSArmin Le Grand VirtualDevice* VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono) 78*ce37d08fSArmin Le Grand { 79*ce37d08fSArmin Le Grand ::osl::MutexGuard aGuard(m_aMutex); 80*ce37d08fSArmin Le Grand VirtualDevice* pRetval = 0; 81*ce37d08fSArmin Le Grand 82*ce37d08fSArmin Le Grand if(!maBuffers.empty()) 83*ce37d08fSArmin Le Grand { 84*ce37d08fSArmin Le Grand bool bOkay(false); 85*ce37d08fSArmin Le Grand aBuffers::iterator aFound(maBuffers.end()); 86*ce37d08fSArmin Le Grand 87*ce37d08fSArmin Le Grand for(aBuffers::iterator a(maBuffers.begin()); a != maBuffers.end(); a++) 88*ce37d08fSArmin Le Grand { 89*ce37d08fSArmin Le Grand OSL_ENSURE(*a, "Empty pointer in VDevBuffer (!)"); 90*ce37d08fSArmin Le Grand 91*ce37d08fSArmin Le Grand if((bMono && 1 == (*a)->GetBitCount()) || (!bMono && (*a)->GetBitCount() > 1)) 92*ce37d08fSArmin Le Grand { 93*ce37d08fSArmin Le Grand // candidate is valid due to bit depth 94*ce37d08fSArmin Le Grand if(aFound != maBuffers.end()) 95*ce37d08fSArmin Le Grand { 96*ce37d08fSArmin Le Grand // already found 97*ce37d08fSArmin Le Grand if(bOkay) 98*ce37d08fSArmin Le Grand { 99*ce37d08fSArmin Le Grand // found is valid 100*ce37d08fSArmin Le Grand const bool bCandidateOkay((*a)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*a)->GetOutputHeightPixel() >= rSizePixel.getHeight()); 101*ce37d08fSArmin Le Grand 102*ce37d08fSArmin Le Grand if(bCandidateOkay) 103*ce37d08fSArmin Le Grand { 104*ce37d08fSArmin Le Grand // found and candidate are valid 105*ce37d08fSArmin Le Grand const sal_uLong aSquare((*aFound)->GetOutputWidthPixel() * (*aFound)->GetOutputHeightPixel()); 106*ce37d08fSArmin Le Grand const sal_uLong aCandidateSquare((*a)->GetOutputWidthPixel() * (*a)->GetOutputHeightPixel()); 107*ce37d08fSArmin Le Grand 108*ce37d08fSArmin Le Grand if(aCandidateSquare < aSquare) 109*ce37d08fSArmin Le Grand { 110*ce37d08fSArmin Le Grand // candidate is valid and smaller, use it 111*ce37d08fSArmin Le Grand aFound = a; 112*ce37d08fSArmin Le Grand } 113*ce37d08fSArmin Le Grand } 114*ce37d08fSArmin Le Grand else 115*ce37d08fSArmin Le Grand { 116*ce37d08fSArmin Le Grand // found is valid, candidate is not. Keep found 117*ce37d08fSArmin Le Grand } 118*ce37d08fSArmin Le Grand } 119*ce37d08fSArmin Le Grand else 120*ce37d08fSArmin Le Grand { 121*ce37d08fSArmin Le Grand // found is invalid, use candidate 122*ce37d08fSArmin Le Grand aFound = a; 123*ce37d08fSArmin Le Grand bOkay = (*aFound)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*aFound)->GetOutputHeightPixel() >= rSizePixel.getHeight(); 124*ce37d08fSArmin Le Grand } 125*ce37d08fSArmin Le Grand } 126*ce37d08fSArmin Le Grand else 127*ce37d08fSArmin Le Grand { 128*ce37d08fSArmin Le Grand // none yet, use candidate 129*ce37d08fSArmin Le Grand aFound = a; 130*ce37d08fSArmin Le Grand bOkay = (*aFound)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*aFound)->GetOutputHeightPixel() >= rSizePixel.getHeight(); 131*ce37d08fSArmin Le Grand } 132*ce37d08fSArmin Le Grand } 133*ce37d08fSArmin Le Grand } 134*ce37d08fSArmin Le Grand 135*ce37d08fSArmin Le Grand if(aFound != maBuffers.end()) 136*ce37d08fSArmin Le Grand { 137*ce37d08fSArmin Le Grand pRetval = *aFound; 138*ce37d08fSArmin Le Grand maBuffers.erase(aFound); 139*ce37d08fSArmin Le Grand 140*ce37d08fSArmin Le Grand if(bOkay) 141*ce37d08fSArmin Le Grand { 142*ce37d08fSArmin Le Grand if(bClear) 143*ce37d08fSArmin Le Grand { 144*ce37d08fSArmin Le Grand pRetval->Erase(Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight())); 145*ce37d08fSArmin Le Grand } 146*ce37d08fSArmin Le Grand } 147*ce37d08fSArmin Le Grand else 148*ce37d08fSArmin Le Grand { 149*ce37d08fSArmin Le Grand pRetval->SetOutputSizePixel(rSizePixel, bClear); 150*ce37d08fSArmin Le Grand } 151*ce37d08fSArmin Le Grand } 152*ce37d08fSArmin Le Grand } 153*ce37d08fSArmin Le Grand 154*ce37d08fSArmin Le Grand // no success yet, create new buffer 155*ce37d08fSArmin Le Grand if(!pRetval) 156*ce37d08fSArmin Le Grand { 157*ce37d08fSArmin Le Grand pRetval = (bMono) ? new VirtualDevice(rOutDev, 1) : new VirtualDevice(rOutDev); 158*ce37d08fSArmin Le Grand pRetval->SetOutputSizePixel(rSizePixel, bClear); 159*ce37d08fSArmin Le Grand } 160*ce37d08fSArmin Le Grand else 161*ce37d08fSArmin Le Grand { 162*ce37d08fSArmin Le Grand // reused, reset some values 163*ce37d08fSArmin Le Grand pRetval->SetMapMode(); 164*ce37d08fSArmin Le Grand } 165*ce37d08fSArmin Le Grand 166*ce37d08fSArmin Le Grand return pRetval; 167*ce37d08fSArmin Le Grand } 168*ce37d08fSArmin Le Grand 169*ce37d08fSArmin Le Grand void VDevBuffer::free(VirtualDevice& rDevice) 170*ce37d08fSArmin Le Grand { 171*ce37d08fSArmin Le Grand ::osl::MutexGuard aGuard(m_aMutex); 172*ce37d08fSArmin Le Grand maBuffers.push_back(&rDevice); 173*ce37d08fSArmin Le Grand Start(); 174*ce37d08fSArmin Le Grand } 175*ce37d08fSArmin Le Grand 176*ce37d08fSArmin Le Grand void VDevBuffer::Timeout() 177*ce37d08fSArmin Le Grand { 178*ce37d08fSArmin Le Grand ::osl::MutexGuard aGuard(m_aMutex); 179*ce37d08fSArmin Le Grand 180*ce37d08fSArmin Le Grand while(!maBuffers.empty()) 181*ce37d08fSArmin Le Grand { 182*ce37d08fSArmin Le Grand delete *(maBuffers.end() - 1); 183*ce37d08fSArmin Le Grand maBuffers.pop_back(); 184*ce37d08fSArmin Le Grand } 185*ce37d08fSArmin Le Grand } 186*ce37d08fSArmin Le Grand } 187cdf0e10cSrcweir 188cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 189cdf0e10cSrcweir // support for rendering Bitmap and BitmapEx contents 190cdf0e10cSrcweir 191cdf0e10cSrcweir namespace drawinglayer 192cdf0e10cSrcweir { 193*ce37d08fSArmin Le Grand // static global VDev buffer for the VclProcessor2D's (VclMetafileProcessor2D and VclPixelProcessor2D) 194*ce37d08fSArmin Le Grand static VDevBuffer aVDevBuffer; 195*ce37d08fSArmin Le Grand 196cdf0e10cSrcweir impBufferDevice::impBufferDevice( 197cdf0e10cSrcweir OutputDevice& rOutDev, 198cdf0e10cSrcweir const basegfx::B2DRange& rRange, 199cdf0e10cSrcweir bool bAddOffsetToMapping) 200cdf0e10cSrcweir : mrOutDev(rOutDev), 201*ce37d08fSArmin Le Grand mpContent(0), 202*ce37d08fSArmin Le Grand mpMask(0), 203*ce37d08fSArmin Le Grand mpAlpha(0) 204cdf0e10cSrcweir { 205cdf0e10cSrcweir basegfx::B2DRange aRangePixel(rRange); 206*ce37d08fSArmin Le Grand aRangePixel.transform(mrOutDev.GetViewTransformation()); 207cdf0e10cSrcweir const Rectangle aRectPixel( 208cdf0e10cSrcweir (sal_Int32)floor(aRangePixel.getMinX()), (sal_Int32)floor(aRangePixel.getMinY()), 209cdf0e10cSrcweir (sal_Int32)ceil(aRangePixel.getMaxX()), (sal_Int32)ceil(aRangePixel.getMaxY())); 210cdf0e10cSrcweir const Point aEmptyPoint; 211*ce37d08fSArmin Le Grand maDestPixel = Rectangle(aEmptyPoint, mrOutDev.GetOutputSizePixel()); 212cdf0e10cSrcweir maDestPixel.Intersection(aRectPixel); 213cdf0e10cSrcweir 214cdf0e10cSrcweir if(isVisible()) 215cdf0e10cSrcweir { 216*ce37d08fSArmin Le Grand mpContent = aVDevBuffer.alloc(mrOutDev, maDestPixel.GetSize(), false, false); 217cdf0e10cSrcweir 218cdf0e10cSrcweir // #i93485# assert when copying from window to VDev is used 219*ce37d08fSArmin Le Grand OSL_ENSURE(mrOutDev.GetOutDevType() != OUTDEV_WINDOW, 220cdf0e10cSrcweir "impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)"); 221cdf0e10cSrcweir 222*ce37d08fSArmin Le Grand const bool bWasEnabledSrc(mrOutDev.IsMapModeEnabled()); 223*ce37d08fSArmin Le Grand mrOutDev.EnableMapMode(false); 224*ce37d08fSArmin Le Grand mpContent->DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), mrOutDev); 225*ce37d08fSArmin Le Grand mrOutDev.EnableMapMode(bWasEnabledSrc); 226cdf0e10cSrcweir 227*ce37d08fSArmin Le Grand MapMode aNewMapMode(mrOutDev.GetMapMode()); 228cdf0e10cSrcweir 229cdf0e10cSrcweir if(bAddOffsetToMapping) 230cdf0e10cSrcweir { 231*ce37d08fSArmin Le Grand const Point aLogicTopLeft(mrOutDev.PixelToLogic(maDestPixel.TopLeft())); 232cdf0e10cSrcweir aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y())); 233cdf0e10cSrcweir } 234cdf0e10cSrcweir 235*ce37d08fSArmin Le Grand mpContent->SetMapMode(aNewMapMode); 236cdf0e10cSrcweir 237cdf0e10cSrcweir // copy AA flag for new target 238*ce37d08fSArmin Le Grand mpContent->SetAntialiasing(mrOutDev.GetAntialiasing()); 239cdf0e10cSrcweir } 240cdf0e10cSrcweir } 241cdf0e10cSrcweir 242cdf0e10cSrcweir impBufferDevice::~impBufferDevice() 243cdf0e10cSrcweir { 244*ce37d08fSArmin Le Grand if(mpContent) 245*ce37d08fSArmin Le Grand { 246*ce37d08fSArmin Le Grand aVDevBuffer.free(*mpContent); 247*ce37d08fSArmin Le Grand } 248*ce37d08fSArmin Le Grand 249*ce37d08fSArmin Le Grand if(mpMask) 250*ce37d08fSArmin Le Grand { 251*ce37d08fSArmin Le Grand aVDevBuffer.free(*mpMask); 252*ce37d08fSArmin Le Grand } 253*ce37d08fSArmin Le Grand 254*ce37d08fSArmin Le Grand if(mpAlpha) 255*ce37d08fSArmin Le Grand { 256*ce37d08fSArmin Le Grand aVDevBuffer.free(*mpAlpha); 257*ce37d08fSArmin Le Grand } 258cdf0e10cSrcweir } 259cdf0e10cSrcweir 260cdf0e10cSrcweir void impBufferDevice::paint(double fTrans) 261cdf0e10cSrcweir { 262*ce37d08fSArmin Le Grand if(isVisible()) 263*ce37d08fSArmin Le Grand { 264cdf0e10cSrcweir const Point aEmptyPoint; 265*ce37d08fSArmin Le Grand const Size aSizePixel(maDestPixel.GetSize()); 266cdf0e10cSrcweir const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled()); 267cdf0e10cSrcweir static bool bDoSaveForVisualControl(false); 268cdf0e10cSrcweir 269cdf0e10cSrcweir mrOutDev.EnableMapMode(false); 270*ce37d08fSArmin Le Grand mpContent->EnableMapMode(false); 271*ce37d08fSArmin Le Grand Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); 272cdf0e10cSrcweir 273cdf0e10cSrcweir if(bDoSaveForVisualControl) 274cdf0e10cSrcweir { 275cdf0e10cSrcweir SvFileStream aNew((const String&)String(ByteString( "c:\\content.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC); 276cdf0e10cSrcweir aNew << aContent; 277cdf0e10cSrcweir } 278cdf0e10cSrcweir 279cdf0e10cSrcweir if(mpAlpha) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir mpAlpha->EnableMapMode(false); 282cdf0e10cSrcweir const AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel)); 283cdf0e10cSrcweir 284cdf0e10cSrcweir if(bDoSaveForVisualControl) 285cdf0e10cSrcweir { 286cdf0e10cSrcweir SvFileStream aNew((const String&)String(ByteString( "c:\\transparence.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC); 287cdf0e10cSrcweir aNew << aAlphaMask.GetBitmap(); 288cdf0e10cSrcweir } 289cdf0e10cSrcweir 290cdf0e10cSrcweir mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask)); 291cdf0e10cSrcweir } 292cdf0e10cSrcweir else if(mpMask) 293cdf0e10cSrcweir { 294cdf0e10cSrcweir mpMask->EnableMapMode(false); 295cdf0e10cSrcweir const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel)); 296cdf0e10cSrcweir 297cdf0e10cSrcweir if(bDoSaveForVisualControl) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir SvFileStream aNew((const String&)String(ByteString( "c:\\mask.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC); 300cdf0e10cSrcweir aNew << aMask; 301cdf0e10cSrcweir } 302cdf0e10cSrcweir 303cdf0e10cSrcweir mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask)); 304cdf0e10cSrcweir } 305cdf0e10cSrcweir else if(0.0 != fTrans) 306cdf0e10cSrcweir { 307cdf0e10cSrcweir sal_uInt8 nMaskValue((sal_uInt8)basegfx::fround(fTrans * 255.0)); 308cdf0e10cSrcweir const AlphaMask aAlphaMask(aSizePixel, &nMaskValue); 309cdf0e10cSrcweir mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask)); 310cdf0e10cSrcweir } 311cdf0e10cSrcweir else 312cdf0e10cSrcweir { 313cdf0e10cSrcweir mrOutDev.DrawBitmap(maDestPixel.TopLeft(), aContent); 314cdf0e10cSrcweir } 315cdf0e10cSrcweir 316cdf0e10cSrcweir mrOutDev.EnableMapMode(bWasEnabledDst); 317cdf0e10cSrcweir } 318*ce37d08fSArmin Le Grand } 319*ce37d08fSArmin Le Grand 320*ce37d08fSArmin Le Grand VirtualDevice& impBufferDevice::getContent() 321*ce37d08fSArmin Le Grand { 322*ce37d08fSArmin Le Grand OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)"); 323*ce37d08fSArmin Le Grand return *mpContent; 324*ce37d08fSArmin Le Grand } 325cdf0e10cSrcweir 326cdf0e10cSrcweir VirtualDevice& impBufferDevice::getMask() 327cdf0e10cSrcweir { 328*ce37d08fSArmin Le Grand OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)"); 329cdf0e10cSrcweir if(!mpMask) 330cdf0e10cSrcweir { 331*ce37d08fSArmin Le Grand mpMask = aVDevBuffer.alloc(mrOutDev, maDestPixel.GetSize(), true, true); 332*ce37d08fSArmin Le Grand mpMask->SetMapMode(mpContent->GetMapMode()); 333cdf0e10cSrcweir 334cdf0e10cSrcweir // do NOT copy AA flag for mask! 335cdf0e10cSrcweir } 336cdf0e10cSrcweir 337cdf0e10cSrcweir return *mpMask; 338cdf0e10cSrcweir } 339cdf0e10cSrcweir 340cdf0e10cSrcweir VirtualDevice& impBufferDevice::getTransparence() 341cdf0e10cSrcweir { 342*ce37d08fSArmin Le Grand OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)"); 343cdf0e10cSrcweir if(!mpAlpha) 344cdf0e10cSrcweir { 345*ce37d08fSArmin Le Grand mpAlpha = aVDevBuffer.alloc(mrOutDev, maDestPixel.GetSize(), true, false); 346*ce37d08fSArmin Le Grand mpAlpha->SetMapMode(mpContent->GetMapMode()); 347cdf0e10cSrcweir 348cdf0e10cSrcweir // copy AA flag for new target; masking needs to be smooth 349*ce37d08fSArmin Le Grand mpAlpha->SetAntialiasing(mpContent->GetAntialiasing()); 350cdf0e10cSrcweir } 351cdf0e10cSrcweir 352cdf0e10cSrcweir return *mpAlpha; 353cdf0e10cSrcweir } 354cdf0e10cSrcweir } // end of namespace drawinglayer 355cdf0e10cSrcweir 356cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 357cdf0e10cSrcweir // eof 358