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 <ctype.h> // don't ask. msdev breaks otherwise...
32*cdf0e10cSrcweir #include <canvas/debug.hxx>
33*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
34*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <boost/preprocessor/repetition.hpp>
39*cdf0e10cSrcweir #include <boost/preprocessor/iteration/local.hpp>
40*cdf0e10cSrcweir #include <boost/scoped_array.hpp>
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir #include "dx_canvasbitmap.hxx"
43*cdf0e10cSrcweir #include "dx_impltools.hxx"
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir using namespace ::com::sun::star;
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir namespace dxcanvas
49*cdf0e10cSrcweir {
50*cdf0e10cSrcweir     CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap,
51*cdf0e10cSrcweir                                 const DeviceRef&        rDevice ) :
52*cdf0e10cSrcweir         mpDevice( rDevice ),
53*cdf0e10cSrcweir         mpBitmap( rBitmap )
54*cdf0e10cSrcweir     {
55*cdf0e10cSrcweir         ENSURE_OR_THROW( mpDevice.is() && mpBitmap,
56*cdf0e10cSrcweir                          "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir         maCanvasHelper.setDevice( *mpDevice.get() );
59*cdf0e10cSrcweir 		maCanvasHelper.setTarget( mpBitmap );
60*cdf0e10cSrcweir     }
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir     void SAL_CALL CanvasBitmap::disposing()
63*cdf0e10cSrcweir     {
64*cdf0e10cSrcweir         mpBitmap.reset();
65*cdf0e10cSrcweir         mpDevice.clear();
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir         // forward to parent
68*cdf0e10cSrcweir         CanvasBitmap_Base::disposing();
69*cdf0e10cSrcweir     }
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir     struct AlphaDIB
72*cdf0e10cSrcweir     {
73*cdf0e10cSrcweir         BITMAPINFOHEADER bmiHeader;
74*cdf0e10cSrcweir         RGBQUAD          bmiColors[256];
75*cdf0e10cSrcweir     };
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir     uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle )  throw (uno::RuntimeException)
78*cdf0e10cSrcweir     {
79*cdf0e10cSrcweir         uno::Any aRes;
80*cdf0e10cSrcweir         // 0 ... get BitmapEx
81*cdf0e10cSrcweir         // 1 ... get Pixbuf with bitmap RGB content
82*cdf0e10cSrcweir         // 2 ... get Pixbuf with bitmap alpha mask
83*cdf0e10cSrcweir         switch( nHandle )
84*cdf0e10cSrcweir         {
85*cdf0e10cSrcweir             // sorry, no BitmapEx here...
86*cdf0e10cSrcweir             case 0:
87*cdf0e10cSrcweir                 aRes = ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
88*cdf0e10cSrcweir                 break;
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir             case 1:
91*cdf0e10cSrcweir             {
92*cdf0e10cSrcweir                 if(!mpBitmap->hasAlpha())
93*cdf0e10cSrcweir                 {
94*cdf0e10cSrcweir                     HBITMAP aHBmp;
95*cdf0e10cSrcweir                     mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp );
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir                     uno::Sequence< uno::Any > args(1);
98*cdf0e10cSrcweir                     args[0] = uno::Any( sal_Int64(aHBmp) );
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir                     aRes <<= args;
101*cdf0e10cSrcweir                 }
102*cdf0e10cSrcweir                 else
103*cdf0e10cSrcweir                 {
104*cdf0e10cSrcweir                     // need to copy&convert the bitmap, since dx
105*cdf0e10cSrcweir                     // canvas uses inline alpha channel
106*cdf0e10cSrcweir                     HDC hScreenDC=GetDC(NULL);
107*cdf0e10cSrcweir                     const basegfx::B2IVector aSize(mpBitmap->getSize());
108*cdf0e10cSrcweir                     HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
109*cdf0e10cSrcweir                                                                  aSize.getX(),
110*cdf0e10cSrcweir                                                                  aSize.getY() );
111*cdf0e10cSrcweir                     if( !hBmpBitmap )
112*cdf0e10cSrcweir                         return aRes;
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir                     BITMAPINFOHEADER aBIH;
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir                     aBIH.biSize = sizeof( BITMAPINFOHEADER );
117*cdf0e10cSrcweir                     aBIH.biWidth = aSize.getX();
118*cdf0e10cSrcweir                     aBIH.biHeight = -aSize.getY();
119*cdf0e10cSrcweir                     aBIH.biPlanes = 1;
120*cdf0e10cSrcweir                     aBIH.biBitCount = 32;
121*cdf0e10cSrcweir                     aBIH.biCompression = BI_RGB; // expects pixel in
122*cdf0e10cSrcweir                                                  // bbggrrxx format
123*cdf0e10cSrcweir                                                  // (little endian)
124*cdf0e10cSrcweir                     aBIH.biSizeImage = 0;
125*cdf0e10cSrcweir                     aBIH.biXPelsPerMeter = 0;
126*cdf0e10cSrcweir                     aBIH.biYPelsPerMeter = 0;
127*cdf0e10cSrcweir                     aBIH.biClrUsed = 0;
128*cdf0e10cSrcweir                     aBIH.biClrImportant = 0;
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir                     Gdiplus::BitmapData aBmpData;
131*cdf0e10cSrcweir                     aBmpData.Width		 = aSize.getX();
132*cdf0e10cSrcweir                     aBmpData.Height		 = aSize.getY();
133*cdf0e10cSrcweir                     aBmpData.Stride 	 = 4*aBmpData.Width;
134*cdf0e10cSrcweir                     aBmpData.PixelFormat = PixelFormat32bppARGB;
135*cdf0e10cSrcweir                     aBmpData.Scan0		 = NULL;
136*cdf0e10cSrcweir                     const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
137*cdf0e10cSrcweir                     BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
138*cdf0e10cSrcweir                     if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
139*cdf0e10cSrcweir                                                                  Gdiplus::ImageLockModeRead,
140*cdf0e10cSrcweir                                                                  PixelFormat32bppARGB, // outputs ARGB (big endian)
141*cdf0e10cSrcweir                                                                  &aBmpData ) )
142*cdf0e10cSrcweir                     {
143*cdf0e10cSrcweir                         // failed to lock, bail out
144*cdf0e10cSrcweir                         return aRes;
145*cdf0e10cSrcweir                     }
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir                     // now aBmpData.Scan0 contains our bits - push
148*cdf0e10cSrcweir                     // them into HBITMAP, ignoring alpha
149*cdf0e10cSrcweir                     SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS );
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir                     pGDIPlusBitmap->UnlockBits( &aBmpData );
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir                     uno::Sequence< uno::Any > args(1);
154*cdf0e10cSrcweir                     args[0] = uno::Any( sal_Int64(hBmpBitmap) );
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir                     aRes <<= args;
157*cdf0e10cSrcweir                 }
158*cdf0e10cSrcweir             }
159*cdf0e10cSrcweir             break;
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir             case 2:
162*cdf0e10cSrcweir             {
163*cdf0e10cSrcweir                 if(!mpBitmap->hasAlpha())
164*cdf0e10cSrcweir                 {
165*cdf0e10cSrcweir                     return aRes;
166*cdf0e10cSrcweir                 }
167*cdf0e10cSrcweir                 else
168*cdf0e10cSrcweir                 {
169*cdf0e10cSrcweir                     static AlphaDIB aDIB=
170*cdf0e10cSrcweir                         {
171*cdf0e10cSrcweir                             {0,0,0,1,8,BI_RGB,0,0,0,0,0},
172*cdf0e10cSrcweir                             {
173*cdf0e10cSrcweir                                 // this here fills palette with grey
174*cdf0e10cSrcweir                                 // level colors, starting from 0,0,0
175*cdf0e10cSrcweir                                 // up to 255,255,255
176*cdf0e10cSrcweir #define BOOST_PP_LOCAL_MACRO(n_) \
177*cdf0e10cSrcweir                     BOOST_PP_COMMA_IF(n_) \
178*cdf0e10cSrcweir                     {n_,n_,n_,n_}
179*cdf0e10cSrcweir #define BOOST_PP_LOCAL_LIMITS     (0, 255)
180*cdf0e10cSrcweir #include BOOST_PP_LOCAL_ITERATE()
181*cdf0e10cSrcweir                             }
182*cdf0e10cSrcweir                         };
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir                     // need to copy&convert the bitmap, since dx
185*cdf0e10cSrcweir                     // canvas uses inline alpha channel
186*cdf0e10cSrcweir                     HDC hScreenDC=GetDC(NULL);
187*cdf0e10cSrcweir                     const basegfx::B2IVector aSize(mpBitmap->getSize());
188*cdf0e10cSrcweir                     HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() );
189*cdf0e10cSrcweir                     if( !hBmpBitmap )
190*cdf0e10cSrcweir                         return aRes;
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir                     aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
193*cdf0e10cSrcweir                     aDIB.bmiHeader.biWidth = aSize.getX();
194*cdf0e10cSrcweir                     aDIB.bmiHeader.biHeight = -aSize.getY();
195*cdf0e10cSrcweir                     aDIB.bmiHeader.biPlanes = 1;
196*cdf0e10cSrcweir                     aDIB.bmiHeader.biBitCount = 8;
197*cdf0e10cSrcweir                     aDIB.bmiHeader.biCompression = BI_RGB;
198*cdf0e10cSrcweir                     aDIB.bmiHeader.biSizeImage = 0;
199*cdf0e10cSrcweir                     aDIB.bmiHeader.biXPelsPerMeter = 0;
200*cdf0e10cSrcweir                     aDIB.bmiHeader.biYPelsPerMeter = 0;
201*cdf0e10cSrcweir                     aDIB.bmiHeader.biClrUsed = 0;
202*cdf0e10cSrcweir                     aDIB.bmiHeader.biClrImportant = 0;
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir                     Gdiplus::BitmapData aBmpData;
205*cdf0e10cSrcweir                     aBmpData.Width		 = aSize.getX();
206*cdf0e10cSrcweir                     aBmpData.Height		 = aSize.getY();
207*cdf0e10cSrcweir                     aBmpData.Stride 	 = 4*aBmpData.Width;
208*cdf0e10cSrcweir                     aBmpData.PixelFormat = PixelFormat32bppARGB;
209*cdf0e10cSrcweir                     aBmpData.Scan0		 = NULL;
210*cdf0e10cSrcweir                     const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
211*cdf0e10cSrcweir                     BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
212*cdf0e10cSrcweir                     if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
213*cdf0e10cSrcweir                                                                  Gdiplus::ImageLockModeRead,
214*cdf0e10cSrcweir                                                                  PixelFormat32bppARGB, // outputs ARGB (big endian)
215*cdf0e10cSrcweir                                                                  &aBmpData ) )
216*cdf0e10cSrcweir                     {
217*cdf0e10cSrcweir                         // failed to lock, bail out
218*cdf0e10cSrcweir                         return aRes;
219*cdf0e10cSrcweir                     }
220*cdf0e10cSrcweir 
221*cdf0e10cSrcweir                     // copy only alpha channel to pAlphaBits
222*cdf0e10cSrcweir                     const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3);
223*cdf0e10cSrcweir                     boost::scoped_array<sal_uInt8> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] );
224*cdf0e10cSrcweir                     const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0;
225*cdf0e10cSrcweir                     pInBits+=3;
226*cdf0e10cSrcweir                     sal_uInt8* pOutBits;
227*cdf0e10cSrcweir                     for( sal_Int32 y=0; y<aSize.getY(); ++y )
228*cdf0e10cSrcweir                     {
229*cdf0e10cSrcweir                         pOutBits=pAlphaBits.get()+y*nScanWidth;
230*cdf0e10cSrcweir                         for( sal_Int32 x=0; x<aSize.getX(); ++x )
231*cdf0e10cSrcweir                         {
232*cdf0e10cSrcweir                             *pOutBits++ = 255-*pInBits;
233*cdf0e10cSrcweir                             pInBits += 4;
234*cdf0e10cSrcweir                         }
235*cdf0e10cSrcweir                     }
236*cdf0e10cSrcweir 
237*cdf0e10cSrcweir                     pGDIPlusBitmap->UnlockBits( &aBmpData );
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir                     // set bits to newly create HBITMAP
240*cdf0e10cSrcweir                     SetDIBits( hScreenDC, hBmpBitmap, 0,
241*cdf0e10cSrcweir                                aSize.getY(), pAlphaBits.get(),
242*cdf0e10cSrcweir                                (PBITMAPINFO)&aDIB, DIB_RGB_COLORS );
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir                     uno::Sequence< uno::Any > args(1);
245*cdf0e10cSrcweir                     args[0] = uno::Any( sal_Int64(hBmpBitmap) );
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir                     aRes <<= args;
248*cdf0e10cSrcweir                 }
249*cdf0e10cSrcweir             }
250*cdf0e10cSrcweir             break;
251*cdf0e10cSrcweir         }
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir         return aRes;
254*cdf0e10cSrcweir     }
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap"
257*cdf0e10cSrcweir #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir     ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName(  ) throw (uno::RuntimeException)
260*cdf0e10cSrcweir     {
261*cdf0e10cSrcweir         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
262*cdf0e10cSrcweir     }
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir     sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
265*cdf0e10cSrcweir     {
266*cdf0e10cSrcweir         return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
267*cdf0e10cSrcweir     }
268*cdf0e10cSrcweir 
269*cdf0e10cSrcweir     uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames(  ) throw (uno::RuntimeException)
270*cdf0e10cSrcweir     {
271*cdf0e10cSrcweir         uno::Sequence< ::rtl::OUString > aRet(1);
272*cdf0e10cSrcweir         aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir         return aRet;
275*cdf0e10cSrcweir     }
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir }
278