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