fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / drawinglayer / source / processor2d / vclhelperbufferdevice.cxx
blobf87afc62ff2c3129179fc432dfd32b022ded6da6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vclhelperbufferdevice.hxx>
21 #include <basegfx/range/b2drange.hxx>
22 #include <vcl/bitmapex.hxx>
23 #include <basegfx/matrix/b2dhommatrix.hxx>
24 #include <tools/stream.hxx>
25 #include <vcl/timer.hxx>
26 #include <comphelper/broadcasthelper.hxx>
27 #include <vcl/lazydelete.hxx>
29 //////////////////////////////////////////////////////////////////////////////
30 // buffered VDev usage
32 namespace
34 typedef ::std::vector< VirtualDevice* > aBuffers;
36 class VDevBuffer : public Timer, protected comphelper::OBaseMutex
38 private:
39 // available buffers
40 aBuffers maFreeBuffers;
42 // allocated/used buffers (remembered to allow deleteing them in destructor)
43 aBuffers maUsedBuffers;
45 public:
46 VDevBuffer();
47 virtual ~VDevBuffer();
49 VirtualDevice* alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono);
50 void free(VirtualDevice& rDevice);
52 // Timer virtuals
53 virtual void Timeout();
56 VDevBuffer::VDevBuffer()
57 : Timer(),
58 maFreeBuffers(),
59 maUsedBuffers()
61 SetTimeout(10L * 1000L); // ten seconds
64 VDevBuffer::~VDevBuffer()
66 ::osl::MutexGuard aGuard(m_aMutex);
67 Stop();
69 while(!maFreeBuffers.empty())
71 delete *(maFreeBuffers.end() - 1);
72 maFreeBuffers.pop_back();
75 while(!maUsedBuffers.empty())
77 delete *(maUsedBuffers.end() - 1);
78 maUsedBuffers.pop_back();
82 VirtualDevice* VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono)
84 ::osl::MutexGuard aGuard(m_aMutex);
85 VirtualDevice* pRetval = 0;
87 if(!maFreeBuffers.empty())
89 bool bOkay(false);
90 aBuffers::iterator aFound(maFreeBuffers.end());
92 for(aBuffers::iterator a(maFreeBuffers.begin()); a != maFreeBuffers.end(); ++a)
94 OSL_ENSURE(*a, "Empty pointer in VDevBuffer (!)");
96 if((bMono && 1 == (*a)->GetBitCount()) || (!bMono && (*a)->GetBitCount() > 1))
98 // candidate is valid due to bit depth
99 if(aFound != maFreeBuffers.end())
101 // already found
102 if(bOkay)
104 // found is valid
105 const bool bCandidateOkay((*a)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*a)->GetOutputHeightPixel() >= rSizePixel.getHeight());
107 if(bCandidateOkay)
109 // found and candidate are valid
110 const sal_uLong aSquare((*aFound)->GetOutputWidthPixel() * (*aFound)->GetOutputHeightPixel());
111 const sal_uLong aCandidateSquare((*a)->GetOutputWidthPixel() * (*a)->GetOutputHeightPixel());
113 if(aCandidateSquare < aSquare)
115 // candidate is valid and smaller, use it
116 aFound = a;
119 else
121 // found is valid, candidate is not. Keep found
124 else
126 // found is invalid, use candidate
127 aFound = a;
128 bOkay = (*aFound)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*aFound)->GetOutputHeightPixel() >= rSizePixel.getHeight();
131 else
133 // none yet, use candidate
134 aFound = a;
135 bOkay = (*aFound)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*aFound)->GetOutputHeightPixel() >= rSizePixel.getHeight();
140 if(aFound != maFreeBuffers.end())
142 pRetval = *aFound;
143 maFreeBuffers.erase(aFound);
145 if(bOkay)
147 if(bClear)
149 pRetval->Erase(Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight()));
152 else
154 pRetval->SetOutputSizePixel(rSizePixel, bClear);
159 // no success yet, create new buffer
160 if(!pRetval)
162 pRetval = (bMono) ? new VirtualDevice(rOutDev, 1) : new VirtualDevice(rOutDev);
163 pRetval->SetOutputSizePixel(rSizePixel, bClear);
165 else
167 // reused, reset some values
168 pRetval->SetMapMode();
171 // remember allocated buffer
172 maUsedBuffers.push_back(pRetval);
174 return pRetval;
177 void VDevBuffer::free(VirtualDevice& rDevice)
179 ::osl::MutexGuard aGuard(m_aMutex);
180 const aBuffers::iterator aUsedFound(::std::find(maUsedBuffers.begin(), maUsedBuffers.end(), &rDevice));
181 OSL_ENSURE(aUsedFound != maUsedBuffers.end(), "OOps, non-registered buffer freed (!)");
183 maUsedBuffers.erase(aUsedFound);
184 maFreeBuffers.push_back(&rDevice);
185 Start();
188 void VDevBuffer::Timeout()
190 ::osl::MutexGuard aGuard(m_aMutex);
192 while(!maFreeBuffers.empty())
194 delete *(maFreeBuffers.end() - 1);
195 maFreeBuffers.pop_back();
200 //////////////////////////////////////////////////////////////////////////////
201 // support for rendering Bitmap and BitmapEx contents
203 namespace drawinglayer
205 // static global VDev buffer for the VclProcessor2D's (VclMetafileProcessor2D and VclPixelProcessor2D)
206 VDevBuffer& getVDevBuffer()
208 // secure global instance with Vcl's safe desroyer of external (seen by
209 // library base) stuff, the remembered VDevs need to be deleted before
210 // Vcl's deinit
211 static vcl::DeleteOnDeinit< VDevBuffer > aVDevBuffer(new VDevBuffer());
212 return *aVDevBuffer.get();
215 impBufferDevice::impBufferDevice(
216 OutputDevice& rOutDev,
217 const basegfx::B2DRange& rRange,
218 bool bAddOffsetToMapping)
219 : mrOutDev(rOutDev),
220 mpContent(0),
221 mpMask(0),
222 mpAlpha(0)
224 basegfx::B2DRange aRangePixel(rRange);
225 aRangePixel.transform(mrOutDev.GetViewTransformation());
226 const Rectangle aRectPixel(
227 (sal_Int32)floor(aRangePixel.getMinX()), (sal_Int32)floor(aRangePixel.getMinY()),
228 (sal_Int32)ceil(aRangePixel.getMaxX()), (sal_Int32)ceil(aRangePixel.getMaxY()));
229 const Point aEmptyPoint;
230 maDestPixel = Rectangle(aEmptyPoint, mrOutDev.GetOutputSizePixel());
231 maDestPixel.Intersection(aRectPixel);
233 if(isVisible())
235 mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, false);
237 // #i93485# assert when copying from window to VDev is used
238 OSL_ENSURE(mrOutDev.GetOutDevType() != OUTDEV_WINDOW,
239 "impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)");
241 const bool bWasEnabledSrc(mrOutDev.IsMapModeEnabled());
242 mrOutDev.EnableMapMode(false);
243 mpContent->DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), mrOutDev);
244 mrOutDev.EnableMapMode(bWasEnabledSrc);
246 MapMode aNewMapMode(mrOutDev.GetMapMode());
248 if(bAddOffsetToMapping)
250 const Point aLogicTopLeft(mrOutDev.PixelToLogic(maDestPixel.TopLeft()));
251 aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y()));
254 mpContent->SetMapMode(aNewMapMode);
256 // copy AA flag for new target
257 mpContent->SetAntialiasing(mrOutDev.GetAntialiasing());
261 impBufferDevice::~impBufferDevice()
263 if(mpContent)
265 getVDevBuffer().free(*mpContent);
268 if(mpMask)
270 getVDevBuffer().free(*mpMask);
273 if(mpAlpha)
275 getVDevBuffer().free(*mpAlpha);
279 void impBufferDevice::paint(double fTrans)
281 if(isVisible())
283 const Point aEmptyPoint;
284 const Size aSizePixel(maDestPixel.GetSize());
285 const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled());
286 static bool bDoSaveForVisualControl(false);
288 mrOutDev.EnableMapMode(false);
289 mpContent->EnableMapMode(false);
290 Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel));
292 if(bDoSaveForVisualControl)
294 SvFileStream aNew((const String&)String( "c:\\content.bmp" ), STREAM_WRITE|STREAM_TRUNC);
295 aNew << aContent;
298 if(mpAlpha)
300 mpAlpha->EnableMapMode(false);
301 const AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel));
303 if(bDoSaveForVisualControl)
305 SvFileStream aNew((const String&)String( "c:\\transparence.bmp" ), STREAM_WRITE|STREAM_TRUNC);
306 aNew << aAlphaMask.GetBitmap();
309 mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
311 else if(mpMask)
313 mpMask->EnableMapMode(false);
314 const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel));
316 if(bDoSaveForVisualControl)
318 SvFileStream aNew((const String&)String( "c:\\mask.bmp" ), STREAM_WRITE|STREAM_TRUNC);
319 aNew << aMask;
322 mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask));
324 else if(0.0 != fTrans)
326 sal_uInt8 nMaskValue((sal_uInt8)basegfx::fround(fTrans * 255.0));
327 const AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
328 mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
330 else
332 mrOutDev.DrawBitmap(maDestPixel.TopLeft(), aContent);
335 mrOutDev.EnableMapMode(bWasEnabledDst);
339 VirtualDevice& impBufferDevice::getContent()
341 OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
342 return *mpContent;
345 VirtualDevice& impBufferDevice::getMask()
347 OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
348 if(!mpMask)
350 mpMask = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, true);
351 mpMask->SetMapMode(mpContent->GetMapMode());
353 // do NOT copy AA flag for mask!
356 return *mpMask;
359 VirtualDevice& impBufferDevice::getTransparence()
361 OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
362 if(!mpAlpha)
364 mpAlpha = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false);
365 mpAlpha->SetMapMode(mpContent->GetMapMode());
367 // copy AA flag for new target; masking needs to be smooth
368 mpAlpha->SetAntialiasing(mpContent->GetAntialiasing());
371 return *mpAlpha;
373 } // end of namespace drawinglayer
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */