update dev300-m58
[ooovba.git] / canvas / source / directx / dx_vcltools.cxx
blobc549c5ee84d7aa2cfc91a705aa71ba9508ddeca1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dx_vcltools.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <vcl/canvastools.hxx>
36 #include <vcl/bitmap.hxx>
37 #include <vcl/bitmapex.hxx>
38 #include <vcl/bmpacc.hxx>
39 #include <tools/diagnose_ex.h>
41 #include "dx_impltools.hxx"
42 #include <basegfx/numeric/ftools.hxx>
44 #include <canvas/debug.hxx>
45 #include <canvas/verbosetrace.hxx>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
50 #include <boost/scoped_array.hpp>
52 #include "dx_vcltools.hxx"
54 using namespace ::com::sun::star;
56 namespace dxcanvas
58 namespace tools
60 namespace
62 /// Calc number of colors in given BitmapInfoHeader
63 sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
65 if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
67 if( rBIH.biBitCount <= 8 )
69 if( rBIH.biClrUsed )
70 return rBIH.biClrUsed;
71 else
72 return 1L << rBIH.biBitCount;
75 else
77 BITMAPCOREHEADER* pCoreHeader = (BITMAPCOREHEADER*)&rBIH;
79 if( pCoreHeader->bcBitCount <= 8 )
80 return 1L << pCoreHeader->bcBitCount;
83 return 0; // nothing known
86 /// Draw DI bits to given Graphics
87 bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
88 const void* hDIB )
90 bool bRet( false );
91 BitmapSharedPtr pBitmap;
93 const BITMAPINFO* pBI = (BITMAPINFO*)GlobalLock( (HGLOBAL)hDIB );
95 if( pBI )
97 const BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)pBI;
98 const BYTE* pBits = (BYTE*) pBI + *(DWORD*)pBI +
99 calcDIBColorCount( *pBIH ) * sizeof( RGBQUAD );
101 // forward to outsourced GDI+ rendering method
102 // (header clashes)
103 bRet = tools::drawDIBits( rGraphics, *pBI, (void*)pBits );
105 GlobalUnlock( (HGLOBAL)hDIB );
108 return bRet;
111 /** Draw VCL bitmap to given Graphics
113 @param rBmp
114 Reference to bitmap. Might get modified, in such a way
115 that it will hold a DIB after a successful function call.
117 bool drawVCLBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
118 ::Bitmap& rBmp )
120 BitmapSystemData aBmpSysData;
122 if( !rBmp.GetSystemData( aBmpSysData ) ||
123 !aBmpSysData.pDIB )
125 // first of all, ensure that Bitmap contains a DIB, by
126 // aquiring a read access
127 BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
129 // TODO(P2): Acquiring a read access can actually
130 // force a read from VRAM, thus, avoiding this
131 // step somehow will increase performance
132 // here.
133 if( pReadAcc )
135 // try again: now, WinSalBitmap must have
136 // generated a DIB
137 if( rBmp.GetSystemData( aBmpSysData ) &&
138 aBmpSysData.pDIB )
140 return drawDIBits( rGraphics,
141 aBmpSysData.pDIB );
144 rBmp.ReleaseAccess( pReadAcc );
147 else
149 return drawDIBits( rGraphics,
150 aBmpSysData.pDIB );
153 // failed to generate DIBits from vcl bitmap
154 return false;
157 /** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BbitmapEX
159 RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
161 // TODO(P2): Avoid temporary bitmap generation, maybe
162 // even ensure that created DIBs are copied back to
163 // BmpEx (currently, every AcquireReadAccess() will
164 // make the local bitmap copy unique, effectively
165 // duplicating the memory used)
167 ENSURE_OR_THROW( rBmpEx.IsTransparent(),
168 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
169 "BmpEx not transparent" );
171 // convert transparent bitmap to 32bit RGBA
172 // ========================================
174 const ::Size aBmpSize( rBmpEx.GetSizePixel() );
176 RawRGBABitmap aBmpData;
177 aBmpData.mnWidth = aBmpSize.Width();
178 aBmpData.mnHeight = aBmpSize.Height();
179 aBmpData.mpBitmapData.reset( new sal_uInt8[ 4*aBmpData.mnWidth*aBmpData.mnHeight ] );
181 Bitmap aBitmap( rBmpEx.GetBitmap() );
183 ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
184 aBitmap );
186 const sal_Int32 nWidth( aBmpSize.Width() );
187 const sal_Int32 nHeight( aBmpSize.Height() );
189 ENSURE_OR_THROW( pReadAccess.get() != NULL,
190 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
191 "Unable to acquire read acces to bitmap" );
193 if( rBmpEx.IsAlpha() )
195 Bitmap aAlpha( rBmpEx.GetAlpha().GetBitmap() );
197 ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.AcquireReadAccess(),
198 aAlpha );
200 // By convention, the access buffer always has
201 // one of the following formats:
203 // BMP_FORMAT_1BIT_MSB_PAL
204 // BMP_FORMAT_4BIT_MSN_PAL
205 // BMP_FORMAT_8BIT_PAL
206 // BMP_FORMAT_16BIT_TC_LSB_MASK
207 // BMP_FORMAT_24BIT_TC_BGR
208 // BMP_FORMAT_32BIT_TC_MASK
210 // and is always BMP_FORMAT_BOTTOM_UP
212 // This is the way
213 // WinSalBitmap::AcquireBuffer() sets up the
214 // buffer
216 ENSURE_OR_THROW( pAlphaReadAccess.get() != NULL,
217 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
218 "Unable to acquire read acces to alpha" );
220 ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
221 pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
222 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
223 "Unsupported alpha scanline format" );
225 BitmapColor aCol;
226 const sal_Int32 nWidth( aBmpSize.Width() );
227 const sal_Int32 nHeight( aBmpSize.Height() );
228 sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
229 int x, y;
231 for( y=0; y<nHeight; ++y )
233 switch( pReadAccess->GetScanlineFormat() )
235 case BMP_FORMAT_8BIT_PAL:
237 Scanline pScan = pReadAccess->GetScanline( y );
238 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
240 for( x=0; x<nWidth; ++x )
242 aCol = pReadAccess->GetPaletteColor( *pScan++ );
244 *pCurrOutput++ = aCol.GetBlue();
245 *pCurrOutput++ = aCol.GetGreen();
246 *pCurrOutput++ = aCol.GetRed();
248 // out notion of alpha is
249 // different from the rest
250 // of the world's
251 *pCurrOutput++ = 255 - (BYTE)*pAScan++;
254 break;
256 case BMP_FORMAT_24BIT_TC_BGR:
258 Scanline pScan = pReadAccess->GetScanline( y );
259 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
261 for( x=0; x<nWidth; ++x )
263 // store as RGBA
264 *pCurrOutput++ = *pScan++;
265 *pCurrOutput++ = *pScan++;
266 *pCurrOutput++ = *pScan++;
268 // out notion of alpha is
269 // different from the rest
270 // of the world's
271 *pCurrOutput++ = 255 - (BYTE)*pAScan++;
274 break;
276 // TODO(P2): Might be advantageous
277 // to hand-formulate the following
278 // formats, too.
279 case BMP_FORMAT_1BIT_MSB_PAL:
280 // FALLTHROUGH intended
281 case BMP_FORMAT_4BIT_MSN_PAL:
282 // FALLTHROUGH intended
283 case BMP_FORMAT_16BIT_TC_LSB_MASK:
284 // FALLTHROUGH intended
285 case BMP_FORMAT_32BIT_TC_MASK:
287 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
289 // using fallback for those
290 // seldom formats
291 for( x=0; x<nWidth; ++x )
293 // yes. x and y are swapped on Get/SetPixel
294 aCol = pReadAccess->GetColor(y,x);
296 *pCurrOutput++ = aCol.GetBlue();
297 *pCurrOutput++ = aCol.GetGreen();
298 *pCurrOutput++ = aCol.GetRed();
300 // out notion of alpha is
301 // different from the rest
302 // of the world's
303 *pCurrOutput++ = 255 - (BYTE)*pAScan++;
306 break;
308 case BMP_FORMAT_1BIT_LSB_PAL:
309 // FALLTHROUGH intended
310 case BMP_FORMAT_4BIT_LSN_PAL:
311 // FALLTHROUGH intended
312 case BMP_FORMAT_8BIT_TC_MASK:
313 // FALLTHROUGH intended
314 case BMP_FORMAT_24BIT_TC_RGB:
315 // FALLTHROUGH intended
316 case BMP_FORMAT_24BIT_TC_MASK:
317 // FALLTHROUGH intended
318 case BMP_FORMAT_16BIT_TC_MSB_MASK:
319 // FALLTHROUGH intended
320 case BMP_FORMAT_32BIT_TC_ABGR:
321 // FALLTHROUGH intended
322 case BMP_FORMAT_32BIT_TC_ARGB:
323 // FALLTHROUGH intended
324 case BMP_FORMAT_32BIT_TC_BGRA:
325 // FALLTHROUGH intended
326 case BMP_FORMAT_32BIT_TC_RGBA:
327 // FALLTHROUGH intended
328 default:
329 ENSURE_OR_THROW( false,
330 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
331 "Unexpected scanline format - has "
332 "WinSalBitmap::AcquireBuffer() changed?" );
336 else
338 Bitmap aMask( rBmpEx.GetMask() );
340 ScopedBitmapReadAccess pMaskReadAccess( aMask.AcquireReadAccess(),
341 aMask );
343 // By convention, the access buffer always has
344 // one of the following formats:
346 // BMP_FORMAT_1BIT_MSB_PAL
347 // BMP_FORMAT_4BIT_MSN_PAL
348 // BMP_FORMAT_8BIT_PAL
349 // BMP_FORMAT_16BIT_TC_LSB_MASK
350 // BMP_FORMAT_24BIT_TC_BGR
351 // BMP_FORMAT_32BIT_TC_MASK
353 // and is always BMP_FORMAT_BOTTOM_UP
355 // This is the way
356 // WinSalBitmap::AcquireBuffer() sets up the
357 // buffer
359 ENSURE_OR_THROW( pMaskReadAccess.get() != NULL,
360 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
361 "Unable to acquire read acces to mask" );
363 ENSURE_OR_THROW( pMaskReadAccess->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL,
364 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
365 "Unsupported mask scanline format" );
367 BitmapColor aCol;
368 int nCurrBit;
369 const int nMask( 1L );
370 const int nInitialBit(7);
371 sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
372 int x, y;
374 // mapping table, to get from mask index color to
375 // alpha value (which depends on the mask's palette)
376 sal_uInt8 aColorMap[2];
378 const BitmapColor& rCol0( pMaskReadAccess->GetPaletteColor( 0 ) );
379 const BitmapColor& rCol1( pMaskReadAccess->GetPaletteColor( 1 ) );
381 // shortcut for true luminance calculation
382 // (assumes that palette is grey-level). Note the
383 // swapped the indices here, to account for the
384 // fact that VCL's notion of alpha is inverted to
385 // the rest of the world's.
386 aColorMap[0] = rCol1.GetRed();
387 aColorMap[1] = rCol0.GetRed();
389 for( y=0; y<nHeight; ++y )
391 switch( pReadAccess->GetScanlineFormat() )
393 case BMP_FORMAT_8BIT_PAL:
395 Scanline pScan = pReadAccess->GetScanline( y );
396 Scanline pMScan = pMaskReadAccess->GetScanline( y );
398 for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
400 aCol = pReadAccess->GetPaletteColor( *pScan++ );
402 *pCurrOutput++ = aCol.GetBlue();
403 *pCurrOutput++ = aCol.GetGreen();
404 *pCurrOutput++ = aCol.GetRed();
406 *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
407 nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
410 break;
412 case BMP_FORMAT_24BIT_TC_BGR:
414 Scanline pScan = pReadAccess->GetScanline( y );
415 Scanline pMScan = pMaskReadAccess->GetScanline( y );
417 for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
419 // store as RGBA
420 *pCurrOutput++ = *pScan++;
421 *pCurrOutput++ = *pScan++;
422 *pCurrOutput++ = *pScan++;
424 *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
425 nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
428 break;
430 // TODO(P2): Might be advantageous
431 // to hand-formulate the following
432 // formats, too.
433 case BMP_FORMAT_1BIT_MSB_PAL:
434 // FALLTHROUGH intended
435 case BMP_FORMAT_4BIT_MSN_PAL:
436 // FALLTHROUGH intended
437 case BMP_FORMAT_16BIT_TC_LSB_MASK:
438 // FALLTHROUGH intended
439 case BMP_FORMAT_32BIT_TC_MASK:
441 Scanline pMScan = pMaskReadAccess->GetScanline( y );
443 // using fallback for those
444 // seldom formats
445 for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
447 // yes. x and y are swapped on Get/SetPixel
448 aCol = pReadAccess->GetColor(y,x);
450 // store as RGBA
451 *pCurrOutput++ = aCol.GetBlue();
452 *pCurrOutput++ = aCol.GetGreen();
453 *pCurrOutput++ = aCol.GetRed();
455 *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
456 nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
459 break;
461 case BMP_FORMAT_1BIT_LSB_PAL:
462 // FALLTHROUGH intended
463 case BMP_FORMAT_4BIT_LSN_PAL:
464 // FALLTHROUGH intended
465 case BMP_FORMAT_8BIT_TC_MASK:
466 // FALLTHROUGH intended
467 case BMP_FORMAT_24BIT_TC_RGB:
468 // FALLTHROUGH intended
469 case BMP_FORMAT_24BIT_TC_MASK:
470 // FALLTHROUGH intended
471 case BMP_FORMAT_16BIT_TC_MSB_MASK:
472 // FALLTHROUGH intended
473 case BMP_FORMAT_32BIT_TC_ABGR:
474 // FALLTHROUGH intended
475 case BMP_FORMAT_32BIT_TC_ARGB:
476 // FALLTHROUGH intended
477 case BMP_FORMAT_32BIT_TC_BGRA:
478 // FALLTHROUGH intended
479 case BMP_FORMAT_32BIT_TC_RGBA:
480 // FALLTHROUGH intended
481 default:
482 ENSURE_OR_THROW( false,
483 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
484 "Unexpected scanline format - has "
485 "WinSalBitmap::AcquireBuffer() changed?" );
490 return aBmpData;
493 bool drawVCLBitmapEx( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
494 const ::BitmapEx& rBmpEx )
496 if( !rBmpEx.IsTransparent() )
498 Bitmap aBmp( rBmpEx.GetBitmap() );
499 return drawVCLBitmap( rGraphics, aBmp );
501 else
503 return drawRGBABits( rGraphics,
504 bitmapFromVCLBitmapEx( rBmpEx ) );
509 bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
510 const uno::Reference< rendering::XBitmap >& xBitmap )
512 // TODO(F2): add support for floating point bitmap formats
513 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
514 xBitmap, uno::UNO_QUERY );
516 if( !xIntBmp.is() )
517 return false;
519 ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
520 if( !aBmpEx )
521 return false;
523 return drawVCLBitmapEx( rGraphics, aBmpEx );