CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / canvas / source / directx / dx_vcltools.cxx
blobc48931b87eae6213f08110369888c663d46acd5e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
31 #include <vcl/canvastools.hxx>
33 #include <vcl/bitmap.hxx>
34 #include <vcl/bitmapex.hxx>
35 #include <vcl/bmpacc.hxx>
36 #include <tools/diagnose_ex.h>
38 #include "dx_impltools.hxx"
39 #include <basegfx/numeric/ftools.hxx>
41 #include <canvas/debug.hxx>
42 #include <canvas/verbosetrace.hxx>
44 #include <com/sun/star/lang/XServiceInfo.hpp>
45 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
47 #include <boost/scoped_array.hpp>
49 #include "dx_vcltools.hxx"
51 using namespace ::com::sun::star;
53 namespace dxcanvas
55 namespace tools
57 namespace
59 /// Calc number of colors in given BitmapInfoHeader
60 sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
62 if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
64 if( rBIH.biBitCount <= 8 )
66 if( rBIH.biClrUsed )
67 return rBIH.biClrUsed;
68 else
69 return 1L << rBIH.biBitCount;
72 else
74 BITMAPCOREHEADER* pCoreHeader = (BITMAPCOREHEADER*)&rBIH;
76 if( pCoreHeader->bcBitCount <= 8 )
77 return 1L << pCoreHeader->bcBitCount;
80 return 0; // nothing known
83 /// Draw DI bits to given Graphics
84 bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
85 const void* hDIB )
87 bool bRet( false );
88 BitmapSharedPtr pBitmap;
90 const BITMAPINFO* pBI = (BITMAPINFO*)GlobalLock( (HGLOBAL)hDIB );
92 if( pBI )
94 const BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)pBI;
95 const BYTE* pBits = (BYTE*) pBI + *(DWORD*)pBI +
96 calcDIBColorCount( *pBIH ) * sizeof( RGBQUAD );
98 // forward to outsourced GDI+ rendering method
99 // (header clashes)
100 bRet = tools::drawDIBits( rGraphics, *pBI, (void*)pBits );
102 GlobalUnlock( (HGLOBAL)hDIB );
105 return bRet;
108 /** Draw VCL bitmap to given Graphics
110 @param rBmp
111 Reference to bitmap. Might get modified, in such a way
112 that it will hold a DIB after a successful function call.
114 bool drawVCLBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
115 ::Bitmap& rBmp )
117 BitmapSystemData aBmpSysData;
119 if( !rBmp.GetSystemData( aBmpSysData ) ||
120 !aBmpSysData.pDIB )
122 // first of all, ensure that Bitmap contains a DIB, by
123 // aquiring a read access
124 BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
126 // TODO(P2): Acquiring a read access can actually
127 // force a read from VRAM, thus, avoiding this
128 // step somehow will increase performance
129 // here.
130 if( pReadAcc )
132 // try again: now, WinSalBitmap must have
133 // generated a DIB
134 if( rBmp.GetSystemData( aBmpSysData ) &&
135 aBmpSysData.pDIB )
137 return drawDIBits( rGraphics,
138 aBmpSysData.pDIB );
141 rBmp.ReleaseAccess( pReadAcc );
144 else
146 return drawDIBits( rGraphics,
147 aBmpSysData.pDIB );
150 // failed to generate DIBits from vcl bitmap
151 return false;
154 /** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BbitmapEX
156 RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
158 // TODO(P2): Avoid temporary bitmap generation, maybe
159 // even ensure that created DIBs are copied back to
160 // BmpEx (currently, every AcquireReadAccess() will
161 // make the local bitmap copy unique, effectively
162 // duplicating the memory used)
164 ENSURE_OR_THROW( rBmpEx.IsTransparent(),
165 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
166 "BmpEx not transparent" );
168 // convert transparent bitmap to 32bit RGBA
169 // ========================================
171 const ::Size aBmpSize( rBmpEx.GetSizePixel() );
173 RawRGBABitmap aBmpData;
174 aBmpData.mnWidth = aBmpSize.Width();
175 aBmpData.mnHeight = aBmpSize.Height();
176 aBmpData.mpBitmapData.reset( new sal_uInt8[ 4*aBmpData.mnWidth*aBmpData.mnHeight ] );
178 Bitmap aBitmap( rBmpEx.GetBitmap() );
180 ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
181 aBitmap );
183 const sal_Int32 nWidth( aBmpSize.Width() );
184 const sal_Int32 nHeight( aBmpSize.Height() );
186 ENSURE_OR_THROW( pReadAccess.get() != NULL,
187 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
188 "Unable to acquire read acces to bitmap" );
190 if( rBmpEx.IsAlpha() )
192 Bitmap aAlpha( rBmpEx.GetAlpha().GetBitmap() );
194 ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.AcquireReadAccess(),
195 aAlpha );
197 // By convention, the access buffer always has
198 // one of the following formats:
200 // BMP_FORMAT_1BIT_MSB_PAL
201 // BMP_FORMAT_4BIT_MSN_PAL
202 // BMP_FORMAT_8BIT_PAL
203 // BMP_FORMAT_16BIT_TC_LSB_MASK
204 // BMP_FORMAT_24BIT_TC_BGR
205 // BMP_FORMAT_32BIT_TC_MASK
207 // and is always BMP_FORMAT_BOTTOM_UP
209 // This is the way
210 // WinSalBitmap::AcquireBuffer() sets up the
211 // buffer
213 ENSURE_OR_THROW( pAlphaReadAccess.get() != NULL,
214 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
215 "Unable to acquire read acces to alpha" );
217 ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
218 pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
219 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
220 "Unsupported alpha scanline format" );
222 BitmapColor aCol;
223 const sal_Int32 nWidth( aBmpSize.Width() );
224 const sal_Int32 nHeight( aBmpSize.Height() );
225 sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
226 int x, y;
228 for( y=0; y<nHeight; ++y )
230 switch( pReadAccess->GetScanlineFormat() )
232 case BMP_FORMAT_8BIT_PAL:
234 Scanline pScan = pReadAccess->GetScanline( y );
235 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
237 for( x=0; x<nWidth; ++x )
239 aCol = pReadAccess->GetPaletteColor( *pScan++ );
241 *pCurrOutput++ = aCol.GetBlue();
242 *pCurrOutput++ = aCol.GetGreen();
243 *pCurrOutput++ = aCol.GetRed();
245 // out notion of alpha is
246 // different from the rest
247 // of the world's
248 *pCurrOutput++ = 255 - (BYTE)*pAScan++;
251 break;
253 case BMP_FORMAT_24BIT_TC_BGR:
255 Scanline pScan = pReadAccess->GetScanline( y );
256 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
258 for( x=0; x<nWidth; ++x )
260 // store as RGBA
261 *pCurrOutput++ = *pScan++;
262 *pCurrOutput++ = *pScan++;
263 *pCurrOutput++ = *pScan++;
265 // out notion of alpha is
266 // different from the rest
267 // of the world's
268 *pCurrOutput++ = 255 - (BYTE)*pAScan++;
271 break;
273 // TODO(P2): Might be advantageous
274 // to hand-formulate the following
275 // formats, too.
276 case BMP_FORMAT_1BIT_MSB_PAL:
277 // FALLTHROUGH intended
278 case BMP_FORMAT_4BIT_MSN_PAL:
279 // FALLTHROUGH intended
280 case BMP_FORMAT_16BIT_TC_LSB_MASK:
281 // FALLTHROUGH intended
282 case BMP_FORMAT_32BIT_TC_MASK:
284 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
286 // using fallback for those
287 // seldom formats
288 for( x=0; x<nWidth; ++x )
290 // yes. x and y are swapped on Get/SetPixel
291 aCol = pReadAccess->GetColor(y,x);
293 *pCurrOutput++ = aCol.GetBlue();
294 *pCurrOutput++ = aCol.GetGreen();
295 *pCurrOutput++ = aCol.GetRed();
297 // out notion of alpha is
298 // different from the rest
299 // of the world's
300 *pCurrOutput++ = 255 - (BYTE)*pAScan++;
303 break;
305 case BMP_FORMAT_1BIT_LSB_PAL:
306 // FALLTHROUGH intended
307 case BMP_FORMAT_4BIT_LSN_PAL:
308 // FALLTHROUGH intended
309 case BMP_FORMAT_8BIT_TC_MASK:
310 // FALLTHROUGH intended
311 case BMP_FORMAT_24BIT_TC_RGB:
312 // FALLTHROUGH intended
313 case BMP_FORMAT_24BIT_TC_MASK:
314 // FALLTHROUGH intended
315 case BMP_FORMAT_16BIT_TC_MSB_MASK:
316 // FALLTHROUGH intended
317 case BMP_FORMAT_32BIT_TC_ABGR:
318 // FALLTHROUGH intended
319 case BMP_FORMAT_32BIT_TC_ARGB:
320 // FALLTHROUGH intended
321 case BMP_FORMAT_32BIT_TC_BGRA:
322 // FALLTHROUGH intended
323 case BMP_FORMAT_32BIT_TC_RGBA:
324 // FALLTHROUGH intended
325 default:
326 ENSURE_OR_THROW( false,
327 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
328 "Unexpected scanline format - has "
329 "WinSalBitmap::AcquireBuffer() changed?" );
333 else
335 Bitmap aMask( rBmpEx.GetMask() );
337 ScopedBitmapReadAccess pMaskReadAccess( aMask.AcquireReadAccess(),
338 aMask );
340 // By convention, the access buffer always has
341 // one of the following formats:
343 // BMP_FORMAT_1BIT_MSB_PAL
344 // BMP_FORMAT_4BIT_MSN_PAL
345 // BMP_FORMAT_8BIT_PAL
346 // BMP_FORMAT_16BIT_TC_LSB_MASK
347 // BMP_FORMAT_24BIT_TC_BGR
348 // BMP_FORMAT_32BIT_TC_MASK
350 // and is always BMP_FORMAT_BOTTOM_UP
352 // This is the way
353 // WinSalBitmap::AcquireBuffer() sets up the
354 // buffer
356 ENSURE_OR_THROW( pMaskReadAccess.get() != NULL,
357 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
358 "Unable to acquire read acces to mask" );
360 ENSURE_OR_THROW( pMaskReadAccess->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL,
361 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
362 "Unsupported mask scanline format" );
364 BitmapColor aCol;
365 int nCurrBit;
366 const int nMask( 1L );
367 const int nInitialBit(7);
368 sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
369 int x, y;
371 // mapping table, to get from mask index color to
372 // alpha value (which depends on the mask's palette)
373 sal_uInt8 aColorMap[2];
375 const BitmapColor& rCol0( pMaskReadAccess->GetPaletteColor( 0 ) );
376 const BitmapColor& rCol1( pMaskReadAccess->GetPaletteColor( 1 ) );
378 // shortcut for true luminance calculation
379 // (assumes that palette is grey-level). Note the
380 // swapped the indices here, to account for the
381 // fact that VCL's notion of alpha is inverted to
382 // the rest of the world's.
383 aColorMap[0] = rCol1.GetRed();
384 aColorMap[1] = rCol0.GetRed();
386 for( y=0; y<nHeight; ++y )
388 switch( pReadAccess->GetScanlineFormat() )
390 case BMP_FORMAT_8BIT_PAL:
392 Scanline pScan = pReadAccess->GetScanline( y );
393 Scanline pMScan = pMaskReadAccess->GetScanline( y );
395 for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
397 aCol = pReadAccess->GetPaletteColor( *pScan++ );
399 *pCurrOutput++ = aCol.GetBlue();
400 *pCurrOutput++ = aCol.GetGreen();
401 *pCurrOutput++ = aCol.GetRed();
403 *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
404 nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
407 break;
409 case BMP_FORMAT_24BIT_TC_BGR:
411 Scanline pScan = pReadAccess->GetScanline( y );
412 Scanline pMScan = pMaskReadAccess->GetScanline( y );
414 for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
416 // store as RGBA
417 *pCurrOutput++ = *pScan++;
418 *pCurrOutput++ = *pScan++;
419 *pCurrOutput++ = *pScan++;
421 *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
422 nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
425 break;
427 // TODO(P2): Might be advantageous
428 // to hand-formulate the following
429 // formats, too.
430 case BMP_FORMAT_1BIT_MSB_PAL:
431 // FALLTHROUGH intended
432 case BMP_FORMAT_4BIT_MSN_PAL:
433 // FALLTHROUGH intended
434 case BMP_FORMAT_16BIT_TC_LSB_MASK:
435 // FALLTHROUGH intended
436 case BMP_FORMAT_32BIT_TC_MASK:
438 Scanline pMScan = pMaskReadAccess->GetScanline( y );
440 // using fallback for those
441 // seldom formats
442 for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
444 // yes. x and y are swapped on Get/SetPixel
445 aCol = pReadAccess->GetColor(y,x);
447 // store as RGBA
448 *pCurrOutput++ = aCol.GetBlue();
449 *pCurrOutput++ = aCol.GetGreen();
450 *pCurrOutput++ = aCol.GetRed();
452 *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
453 nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
456 break;
458 case BMP_FORMAT_1BIT_LSB_PAL:
459 // FALLTHROUGH intended
460 case BMP_FORMAT_4BIT_LSN_PAL:
461 // FALLTHROUGH intended
462 case BMP_FORMAT_8BIT_TC_MASK:
463 // FALLTHROUGH intended
464 case BMP_FORMAT_24BIT_TC_RGB:
465 // FALLTHROUGH intended
466 case BMP_FORMAT_24BIT_TC_MASK:
467 // FALLTHROUGH intended
468 case BMP_FORMAT_16BIT_TC_MSB_MASK:
469 // FALLTHROUGH intended
470 case BMP_FORMAT_32BIT_TC_ABGR:
471 // FALLTHROUGH intended
472 case BMP_FORMAT_32BIT_TC_ARGB:
473 // FALLTHROUGH intended
474 case BMP_FORMAT_32BIT_TC_BGRA:
475 // FALLTHROUGH intended
476 case BMP_FORMAT_32BIT_TC_RGBA:
477 // FALLTHROUGH intended
478 default:
479 ENSURE_OR_THROW( false,
480 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
481 "Unexpected scanline format - has "
482 "WinSalBitmap::AcquireBuffer() changed?" );
487 return aBmpData;
490 bool drawVCLBitmapEx( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
491 const ::BitmapEx& rBmpEx )
493 if( !rBmpEx.IsTransparent() )
495 Bitmap aBmp( rBmpEx.GetBitmap() );
496 return drawVCLBitmap( rGraphics, aBmp );
498 else
500 return drawRGBABits( rGraphics,
501 bitmapFromVCLBitmapEx( rBmpEx ) );
506 bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
507 const uno::Reference< rendering::XBitmap >& xBitmap )
509 // TODO(F2): add support for floating point bitmap formats
510 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
511 xBitmap, uno::UNO_QUERY );
513 if( !xIntBmp.is() )
514 return false;
516 ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
517 if( !aBmpEx )
518 return false;
520 return drawVCLBitmapEx( rGraphics, aBmpEx );