vclhelperbufferdevice.cxx (464702f4) vclhelperbufferdevice.cxx (ce37d08f)
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance

--- 15 unchanged lines hidden (view full) ---

24// MARKER(update_precomp.py): autogen include statement, do not remove
25#include "precompiled_drawinglayer.hxx"
26
27#include <vclhelperbufferdevice.hxx>
28#include <basegfx/range/b2drange.hxx>
29#include <vcl/bitmapex.hxx>
30#include <basegfx/matrix/b2dhommatrix.hxx>
31#include <tools/stream.hxx>
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance

--- 15 unchanged lines hidden (view full) ---

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