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