Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <canvas/debug.hxx>
22 : #include <tools/diagnose_ex.h>
23 :
24 : #include <com/sun/star/util/Endianness.hpp>
25 :
26 : #include <rtl/logfile.hxx>
27 : #include <rtl/math.hxx>
28 :
29 : #include <tools/poly.hxx>
30 : #include <vcl/window.hxx>
31 : #include <vcl/bitmapex.hxx>
32 : #include <vcl/bmpacc.hxx>
33 : #include <vcl/canvastools.hxx>
34 :
35 : #include <basegfx/matrix/b2dhommatrix.hxx>
36 : #include <basegfx/point/b2dpoint.hxx>
37 : #include <basegfx/tools/canvastools.hxx>
38 : #include <basegfx/numeric/ftools.hxx>
39 :
40 : #include <canvas/canvastools.hxx>
41 :
42 : #include "canvasbitmap.hxx"
43 : #include "canvasbitmaphelper.hxx"
44 :
45 :
46 : using namespace ::com::sun::star;
47 :
48 : namespace vclcanvas
49 : {
50 0 : CanvasBitmapHelper::CanvasBitmapHelper() :
51 : mpBackBuffer(),
52 0 : mpOutDevReference()
53 : {
54 0 : }
55 :
56 0 : void CanvasBitmapHelper::setBitmap( const BitmapEx& rBitmap )
57 : {
58 0 : ENSURE_OR_THROW( mpOutDev,
59 : "Invalid reference device" );
60 :
61 : mpBackBuffer.reset( new BitmapBackBuffer( rBitmap,
62 0 : mpOutDev->getOutDev() ) );
63 :
64 : // tell canvas helper about the new target OutDev (don't
65 : // protect state, it's our own VirDev, anyways)
66 0 : setOutDev( mpBackBuffer, false );
67 0 : }
68 :
69 0 : void CanvasBitmapHelper::init( const BitmapEx& rBitmap,
70 : rendering::XGraphicDevice& rDevice,
71 : const OutDevProviderSharedPtr& rOutDevReference )
72 : {
73 0 : mpOutDevReference = rOutDevReference;
74 0 : mpBackBuffer.reset( new BitmapBackBuffer( rBitmap, rOutDevReference->getOutDev() ));
75 :
76 : // forward new settings to base class (ref device, output
77 : // surface, no protection (own backbuffer), alpha depends on
78 : // whether BmpEx is transparent or not)
79 : CanvasHelper::init( rDevice,
80 : mpBackBuffer,
81 : false,
82 0 : rBitmap.IsTransparent() );
83 0 : }
84 :
85 0 : void CanvasBitmapHelper::disposing()
86 : {
87 0 : mpBackBuffer.reset();
88 0 : mpOutDevReference.reset();
89 :
90 : // forward to base class
91 0 : CanvasHelper::disposing();
92 0 : }
93 :
94 0 : geometry::IntegerSize2D CanvasBitmapHelper::getSize()
95 : {
96 0 : if( !mpBackBuffer )
97 0 : return geometry::IntegerSize2D();
98 :
99 0 : return ::vcl::unotools::integerSize2DFromSize( mpBackBuffer->getBitmapSizePixel() );
100 : }
101 :
102 0 : void CanvasBitmapHelper::clear()
103 : {
104 : // are we disposed?
105 0 : if( mpBackBuffer )
106 0 : mpBackBuffer->clear(); // alpha vdev needs special treatment
107 0 : }
108 :
109 0 : uno::Reference< rendering::XBitmap > CanvasBitmapHelper::getScaledBitmap( const geometry::RealSize2D& newSize,
110 : sal_Bool beFast )
111 : {
112 0 : ENSURE_OR_THROW( mpDevice,
113 : "disposed CanvasHelper" );
114 :
115 : RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getScaledBitmap()" );
116 :
117 0 : if( !mpBackBuffer || mpDevice )
118 0 : return uno::Reference< rendering::XBitmap >(); // we're disposed
119 :
120 0 : BitmapEx aRes( mpBackBuffer->getBitmapReference() );
121 :
122 : aRes.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize),
123 0 : beFast ? BMP_SCALE_FAST : BMP_SCALE_DEFAULT );
124 :
125 : return uno::Reference< rendering::XBitmap >(
126 0 : new CanvasBitmap( aRes, *mpDevice, mpOutDevReference ) );
127 : }
128 :
129 0 : uno::Sequence< sal_Int8 > CanvasBitmapHelper::getData( rendering::IntegerBitmapLayout& rLayout,
130 : const geometry::IntegerRectangle2D& rect )
131 : {
132 : RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getData()" );
133 :
134 0 : if( !mpBackBuffer )
135 0 : return uno::Sequence< sal_Int8 >(); // we're disposed
136 :
137 0 : rLayout = getMemoryLayout();
138 0 : Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
139 0 : Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
140 :
141 0 : Bitmap::ScopedReadAccess pReadAccess( aBitmap );
142 0 : Bitmap::ScopedReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ?
143 : (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(),
144 0 : aAlpha );
145 :
146 0 : ENSURE_OR_THROW( pReadAccess.get() != NULL,
147 : "Could not acquire read access to bitmap" );
148 :
149 : // TODO(F1): Support more formats.
150 0 : const Size aBmpSize( aBitmap.GetSizePixel() );
151 :
152 0 : rLayout.ScanLines = aBmpSize.Height();
153 0 : rLayout.ScanLineBytes = aBmpSize.Width()*4;
154 0 : rLayout.ScanLineStride = rLayout.ScanLineBytes;
155 :
156 : // for the time being, always return as BGRA
157 0 : uno::Sequence< sal_Int8 > aRes( 4*aBmpSize.Width()*aBmpSize.Height() );
158 0 : sal_Int8* pRes = aRes.getArray();
159 :
160 0 : int nCurrPos(0);
161 0 : for( int y=rect.Y1;
162 0 : y<aBmpSize.Height() && y<rect.Y2;
163 : ++y )
164 : {
165 0 : if( pAlphaReadAccess.get() != NULL )
166 : {
167 0 : for( int x=rect.X1;
168 0 : x<aBmpSize.Width() && x<rect.X2;
169 : ++x )
170 : {
171 0 : pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
172 0 : pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
173 0 : pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
174 0 : pRes[ nCurrPos++ ] = pAlphaReadAccess->GetPixel( y, x ).GetIndex();
175 : }
176 : }
177 : else
178 : {
179 0 : for( int x=rect.X1;
180 0 : x<aBmpSize.Width() && x<rect.X2;
181 : ++x )
182 : {
183 0 : pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
184 0 : pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
185 0 : pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
186 0 : pRes[ nCurrPos++ ] = sal_uInt8(255);
187 : }
188 : }
189 : }
190 :
191 0 : return aRes;
192 : }
193 :
194 0 : void CanvasBitmapHelper::setData( const uno::Sequence< sal_Int8 >& data,
195 : const rendering::IntegerBitmapLayout& rLayout,
196 : const geometry::IntegerRectangle2D& rect )
197 : {
198 : RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setData()" );
199 :
200 0 : if( !mpBackBuffer )
201 0 : return; // we're disposed
202 :
203 0 : const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
204 0 : ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
205 : aRefLayout.ColorSpace != rLayout.ColorSpace ||
206 : aRefLayout.Palette != rLayout.Palette ||
207 : aRefLayout.IsMsbFirst != rLayout.IsMsbFirst,
208 : "Mismatching memory layout" );
209 :
210 : // retrieve local copies from the BitmapEx, which are later
211 : // stored back. Unfortunately, the BitmapEx does not permit
212 : // in-place modifications, as they are necessary here.
213 0 : Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
214 0 : Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
215 :
216 0 : bool bCopyBack( false ); // only copy something back, if we
217 : // actually changed a pixel
218 :
219 : {
220 0 : Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
221 0 : Bitmap::ScopedWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ?
222 : (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(),
223 0 : aAlpha );
224 :
225 0 : if( pAlphaWriteAccess.get() )
226 : {
227 : DBG_ASSERT( pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
228 : pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
229 : "non-8bit alpha not supported!" );
230 : }
231 :
232 0 : ENSURE_OR_THROW( pWriteAccess.get() != NULL,
233 : "Could not acquire write access to bitmap" );
234 :
235 : // TODO(F1): Support more formats.
236 0 : const Size aBmpSize( aBitmap.GetSizePixel() );
237 :
238 : // for the time being, always read as BGRA
239 0 : int x, y, nCurrPos(0);
240 0 : for( y=rect.Y1;
241 0 : y<aBmpSize.Height() && y<rect.Y2;
242 : ++y )
243 : {
244 0 : if( pAlphaWriteAccess.get() != NULL )
245 : {
246 0 : switch( pWriteAccess->GetScanlineFormat() )
247 : {
248 : case BMP_FORMAT_8BIT_PAL:
249 : {
250 0 : Scanline pScan = pWriteAccess->GetScanline( y );
251 0 : Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
252 :
253 0 : for( x=rect.X1;
254 0 : x<aBmpSize.Width() && x<rect.X2;
255 : ++x )
256 : {
257 0 : *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex(
258 0 : BitmapColor( data[ nCurrPos ],
259 0 : data[ nCurrPos+1 ],
260 0 : data[ nCurrPos+2 ] ) );
261 :
262 0 : nCurrPos += 3;
263 :
264 : // cast to unsigned byte, for correct subtraction result
265 : *pAScan++ = static_cast<sal_uInt8>(255 -
266 0 : static_cast<sal_uInt8>(data[ nCurrPos++ ]));
267 : }
268 : }
269 0 : break;
270 :
271 : case BMP_FORMAT_24BIT_TC_BGR:
272 : {
273 0 : Scanline pScan = pWriteAccess->GetScanline( y );
274 0 : Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
275 :
276 0 : for( x=rect.X1;
277 0 : x<aBmpSize.Width() && x<rect.X2;
278 : ++x )
279 : {
280 0 : *pScan++ = data[ nCurrPos+2 ];
281 0 : *pScan++ = data[ nCurrPos+1 ];
282 0 : *pScan++ = data[ nCurrPos ];
283 :
284 0 : nCurrPos += 3;
285 :
286 : // cast to unsigned byte, for correct subtraction result
287 : *pAScan++ = static_cast<sal_uInt8>(255 -
288 0 : static_cast<sal_uInt8>(data[ nCurrPos++ ]));
289 : }
290 : }
291 0 : break;
292 :
293 : case BMP_FORMAT_24BIT_TC_RGB:
294 : {
295 0 : Scanline pScan = pWriteAccess->GetScanline( y );
296 0 : Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
297 :
298 0 : for( x=rect.X1;
299 0 : x<aBmpSize.Width() && x<rect.X2;
300 : ++x )
301 : {
302 0 : *pScan++ = data[ nCurrPos ];
303 0 : *pScan++ = data[ nCurrPos+1 ];
304 0 : *pScan++ = data[ nCurrPos+2 ];
305 :
306 0 : nCurrPos += 3;
307 :
308 : // cast to unsigned byte, for correct subtraction result
309 : *pAScan++ = static_cast<sal_uInt8>(255 -
310 0 : static_cast<sal_uInt8>(data[ nCurrPos++ ]));
311 : }
312 : }
313 0 : break;
314 :
315 : default:
316 : {
317 0 : for( x=rect.X1;
318 0 : x<aBmpSize.Width() && x<rect.X2;
319 : ++x )
320 : {
321 0 : pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ],
322 0 : data[ nCurrPos+1 ],
323 0 : data[ nCurrPos+2 ] ) );
324 0 : nCurrPos += 3;
325 :
326 : // cast to unsigned byte, for correct subtraction result
327 : pAlphaWriteAccess->SetPixel( y, x,
328 : BitmapColor(
329 : static_cast<sal_uInt8>(255 -
330 0 : static_cast<sal_uInt8>(data[ nCurrPos++ ])) ) );
331 : }
332 : }
333 0 : break;
334 : }
335 : }
336 : else
337 : {
338 : // TODO(Q3): This is copy'n'pasted from
339 : // canvashelper.cxx, unify!
340 0 : switch( pWriteAccess->GetScanlineFormat() )
341 : {
342 : case BMP_FORMAT_8BIT_PAL:
343 : {
344 0 : Scanline pScan = pWriteAccess->GetScanline( y );
345 :
346 0 : for( x=rect.X1;
347 0 : x<aBmpSize.Width() && x<rect.X2;
348 : ++x )
349 : {
350 0 : *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex(
351 0 : BitmapColor( data[ nCurrPos ],
352 0 : data[ nCurrPos+1 ],
353 0 : data[ nCurrPos+2 ] ) );
354 :
355 0 : nCurrPos += 4; // skip three colors, _plus_ alpha
356 : }
357 : }
358 0 : break;
359 :
360 : case BMP_FORMAT_24BIT_TC_BGR:
361 : {
362 0 : Scanline pScan = pWriteAccess->GetScanline( y );
363 :
364 0 : for( x=rect.X1;
365 0 : x<aBmpSize.Width() && x<rect.X2;
366 : ++x )
367 : {
368 0 : *pScan++ = data[ nCurrPos+2 ];
369 0 : *pScan++ = data[ nCurrPos+1 ];
370 0 : *pScan++ = data[ nCurrPos ];
371 :
372 0 : nCurrPos += 4; // skip three colors, _plus_ alpha
373 : }
374 : }
375 0 : break;
376 :
377 : case BMP_FORMAT_24BIT_TC_RGB:
378 : {
379 0 : Scanline pScan = pWriteAccess->GetScanline( y );
380 :
381 0 : for( x=rect.X1;
382 0 : x<aBmpSize.Width() && x<rect.X2;
383 : ++x )
384 : {
385 0 : *pScan++ = data[ nCurrPos ];
386 0 : *pScan++ = data[ nCurrPos+1 ];
387 0 : *pScan++ = data[ nCurrPos+2 ];
388 :
389 0 : nCurrPos += 4; // skip three colors, _plus_ alpha
390 : }
391 : }
392 0 : break;
393 :
394 : default:
395 : {
396 0 : for( x=rect.X1;
397 0 : x<aBmpSize.Width() && x<rect.X2;
398 : ++x )
399 : {
400 0 : pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ],
401 0 : data[ nCurrPos+1 ],
402 0 : data[ nCurrPos+2 ] ) );
403 0 : nCurrPos += 4; // skip three colors, _plus_ alpha
404 : }
405 : }
406 0 : break;
407 : }
408 : }
409 :
410 0 : bCopyBack = true;
411 0 : }
412 : }
413 :
414 : // copy back only here, since the BitmapAccessors must be
415 : // destroyed beforehand
416 0 : if( bCopyBack )
417 : {
418 0 : if( aAlpha.IsEmpty() )
419 0 : setBitmap( BitmapEx( aBitmap ) );
420 : else
421 : setBitmap( BitmapEx( aBitmap,
422 0 : AlphaMask( aAlpha ) ) );
423 0 : }
424 : }
425 :
426 0 : void CanvasBitmapHelper::setPixel( const uno::Sequence< sal_Int8 >& color,
427 : const rendering::IntegerBitmapLayout& rLayout,
428 : const geometry::IntegerPoint2D& pos )
429 : {
430 : RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setPixel()" );
431 :
432 0 : if( !mpBackBuffer )
433 0 : return; // we're disposed
434 :
435 0 : const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() );
436 :
437 0 : ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
438 : "X coordinate out of bounds" );
439 0 : ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
440 : "Y coordinate out of bounds" );
441 0 : ENSURE_ARG_OR_THROW( color.getLength() > 3,
442 : "not enough color components" );
443 :
444 0 : const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
445 0 : ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
446 : aRefLayout.ColorSpace != rLayout.ColorSpace ||
447 : aRefLayout.Palette != rLayout.Palette ||
448 : aRefLayout.IsMsbFirst != rLayout.IsMsbFirst,
449 : "Mismatching memory layout" );
450 :
451 : // retrieve local copies from the BitmapEx, which are later
452 : // stored back. Unfortunately, the BitmapEx does not permit
453 : // in-place modifications, as they are necessary here.
454 0 : Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
455 0 : Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
456 :
457 0 : bool bCopyBack( false ); // only copy something back, if we
458 : // actually changed a pixel
459 :
460 : {
461 0 : Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
462 0 : Bitmap::ScopedWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ?
463 : (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(),
464 0 : aAlpha );
465 :
466 0 : ENSURE_OR_THROW( pWriteAccess.get() != NULL,
467 : "Could not acquire write access to bitmap" );
468 :
469 0 : pWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( color[ 0 ],
470 0 : color[ 1 ],
471 0 : color[ 2 ] ) );
472 :
473 0 : if( pAlphaWriteAccess.get() != NULL )
474 0 : pAlphaWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( 255 - color[ 3 ] ) );
475 :
476 0 : bCopyBack = true;
477 : }
478 :
479 : // copy back only here, since the BitmapAccessors must be
480 : // destroyed beforehand
481 0 : if( bCopyBack )
482 : {
483 0 : if( aAlpha.IsEmpty() )
484 0 : setBitmap( BitmapEx( aBitmap ) );
485 : else
486 : setBitmap( BitmapEx( aBitmap,
487 0 : AlphaMask( aAlpha ) ) );
488 0 : }
489 : }
490 :
491 0 : uno::Sequence< sal_Int8 > CanvasBitmapHelper::getPixel( rendering::IntegerBitmapLayout& rLayout,
492 : const geometry::IntegerPoint2D& pos )
493 : {
494 : RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getPixel()" );
495 :
496 0 : if( !mpBackBuffer )
497 0 : return uno::Sequence< sal_Int8 >(); // we're disposed
498 :
499 0 : rLayout = getMemoryLayout();
500 0 : rLayout.ScanLines = 1;
501 0 : rLayout.ScanLineBytes = 4;
502 0 : rLayout.ScanLineStride = rLayout.ScanLineBytes;
503 :
504 0 : const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() );
505 :
506 0 : ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
507 : "X coordinate out of bounds" );
508 0 : ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
509 : "Y coordinate out of bounds" );
510 :
511 0 : Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
512 0 : Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
513 :
514 0 : Bitmap::ScopedReadAccess pReadAccess( aBitmap );
515 0 : Bitmap::ScopedReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ?
516 : (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(),
517 0 : aAlpha );
518 0 : ENSURE_OR_THROW( pReadAccess.get() != NULL,
519 : "Could not acquire read access to bitmap" );
520 :
521 0 : uno::Sequence< sal_Int8 > aRes( 4 );
522 0 : sal_Int8* pRes = aRes.getArray();
523 :
524 0 : const BitmapColor aColor( pReadAccess->GetColor( pos.Y, pos.X ) );
525 0 : pRes[ 0 ] = aColor.GetRed();
526 0 : pRes[ 1 ] = aColor.GetGreen();
527 0 : pRes[ 2 ] = aColor.GetBlue();
528 :
529 0 : if( pAlphaReadAccess.get() != NULL )
530 0 : pRes[ 3 ] = pAlphaReadAccess->GetPixel( pos.Y, pos.X ).GetIndex();
531 : else
532 0 : pRes[ 3 ] = sal_uInt8(255);
533 :
534 0 : return aRes;
535 : }
536 :
537 0 : rendering::IntegerBitmapLayout CanvasBitmapHelper::getMemoryLayout()
538 : {
539 0 : if( !mpOutDev.get() )
540 0 : return rendering::IntegerBitmapLayout(); // we're disposed
541 :
542 0 : rendering::IntegerBitmapLayout xBitmapLayout( ::canvas::tools::getStdMemoryLayout(getSize()) );
543 0 : if ( !hasAlpha() )
544 0 : xBitmapLayout.ColorSpace = canvas::tools::getStdColorSpaceWithoutAlpha();
545 :
546 0 : return xBitmapLayout;
547 : }
548 :
549 0 : BitmapEx CanvasBitmapHelper::getBitmap() const
550 : {
551 0 : if( !mpBackBuffer )
552 0 : return BitmapEx(); // we're disposed
553 : else
554 0 : return mpBackBuffer->getBitmapReference();
555 : }
556 :
557 0 : }
558 :
559 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|