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 <ctype.h> // don't ask. msdev breaks otherwise...
32 #include <canvas/debug.hxx>
33 #include <canvas/canvastools.hxx>
34 #include <tools/diagnose_ex.h>
36 #include <vcl/bitmapex.hxx>
38 #include <boost/preprocessor/repetition.hpp>
39 #include <boost/preprocessor/iteration/local.hpp>
40 #include <boost/scoped_array.hpp>
42 #include "dx_canvasbitmap.hxx"
43 #include "dx_impltools.hxx"
46 using namespace ::com::sun::star
;
50 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr
& rBitmap
,
51 const DeviceRef
& rDevice
) :
55 ENSURE_OR_THROW( mpDevice
.is() && mpBitmap
,
56 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
58 maCanvasHelper
.setDevice( *mpDevice
.get() );
59 maCanvasHelper
.setTarget( mpBitmap
);
62 void SAL_CALL
CanvasBitmap::disposing()
68 CanvasBitmap_Base::disposing();
73 BITMAPINFOHEADER bmiHeader
;
74 RGBQUAD bmiColors
[256];
77 uno::Any SAL_CALL
CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle
) throw (uno::RuntimeException
)
81 // 1 ... get Pixbuf with bitmap RGB content
82 // 2 ... get Pixbuf with bitmap alpha mask
85 // sorry, no BitmapEx here...
87 aRes
= ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64
>( (BitmapEx
*) NULL
) );
92 if(!mpBitmap
->hasAlpha())
95 mpBitmap
->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp
);
97 uno::Sequence
< uno::Any
> args(1);
98 args
[0] = uno::Any( sal_Int64(aHBmp
) );
104 // need to copy&convert the bitmap, since dx
105 // canvas uses inline alpha channel
106 HDC hScreenDC
=GetDC(NULL
);
107 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
108 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
,
114 BITMAPINFOHEADER aBIH
;
116 aBIH
.biSize
= sizeof( BITMAPINFOHEADER
);
117 aBIH
.biWidth
= aSize
.getX();
118 aBIH
.biHeight
= -aSize
.getY();
120 aBIH
.biBitCount
= 32;
121 aBIH
.biCompression
= BI_RGB
; // expects pixel in
124 aBIH
.biSizeImage
= 0;
125 aBIH
.biXPelsPerMeter
= 0;
126 aBIH
.biYPelsPerMeter
= 0;
128 aBIH
.biClrImportant
= 0;
130 Gdiplus::BitmapData aBmpData
;
131 aBmpData
.Width
= aSize
.getX();
132 aBmpData
.Height
= aSize
.getY();
133 aBmpData
.Stride
= 4*aBmpData
.Width
;
134 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
135 aBmpData
.Scan0
= NULL
;
136 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
137 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
138 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
139 Gdiplus::ImageLockModeRead
,
140 PixelFormat32bppARGB
, // outputs ARGB (big endian)
143 // failed to lock, bail out
147 // now aBmpData.Scan0 contains our bits - push
148 // them into HBITMAP, ignoring alpha
149 SetDIBits( hScreenDC
, hBmpBitmap
, 0, aSize
.getY(), aBmpData
.Scan0
, (PBITMAPINFO
)&aBIH
, DIB_RGB_COLORS
);
151 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
153 uno::Sequence
< uno::Any
> args(1);
154 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
163 if(!mpBitmap
->hasAlpha())
169 static AlphaDIB aDIB
=
171 {0,0,0,1,8,BI_RGB
,0,0,0,0,0},
173 // this here fills palette with grey
174 // level colors, starting from 0,0,0
176 #define BOOST_PP_LOCAL_MACRO(n_) \
177 BOOST_PP_COMMA_IF(n_) \
179 #define BOOST_PP_LOCAL_LIMITS (0, 255)
180 #include BOOST_PP_LOCAL_ITERATE()
184 // need to copy&convert the bitmap, since dx
185 // canvas uses inline alpha channel
186 HDC hScreenDC
=GetDC(NULL
);
187 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
188 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
, aSize
.getX(), aSize
.getY() );
192 aDIB
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
193 aDIB
.bmiHeader
.biWidth
= aSize
.getX();
194 aDIB
.bmiHeader
.biHeight
= -aSize
.getY();
195 aDIB
.bmiHeader
.biPlanes
= 1;
196 aDIB
.bmiHeader
.biBitCount
= 8;
197 aDIB
.bmiHeader
.biCompression
= BI_RGB
;
198 aDIB
.bmiHeader
.biSizeImage
= 0;
199 aDIB
.bmiHeader
.biXPelsPerMeter
= 0;
200 aDIB
.bmiHeader
.biYPelsPerMeter
= 0;
201 aDIB
.bmiHeader
.biClrUsed
= 0;
202 aDIB
.bmiHeader
.biClrImportant
= 0;
204 Gdiplus::BitmapData aBmpData
;
205 aBmpData
.Width
= aSize
.getX();
206 aBmpData
.Height
= aSize
.getY();
207 aBmpData
.Stride
= 4*aBmpData
.Width
;
208 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
209 aBmpData
.Scan0
= NULL
;
210 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
211 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
212 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
213 Gdiplus::ImageLockModeRead
,
214 PixelFormat32bppARGB
, // outputs ARGB (big endian)
217 // failed to lock, bail out
221 // copy only alpha channel to pAlphaBits
222 const sal_Int32
nScanWidth((aSize
.getX() + 3) & ~3);
223 boost::scoped_array
<sal_uInt8
> pAlphaBits( new sal_uInt8
[nScanWidth
*aSize
.getY()] );
224 const sal_uInt8
* pInBits
=(sal_uInt8
*)aBmpData
.Scan0
;
227 for( sal_Int32 y
=0; y
<aSize
.getY(); ++y
)
229 pOutBits
=pAlphaBits
.get()+y
*nScanWidth
;
230 for( sal_Int32 x
=0; x
<aSize
.getX(); ++x
)
232 *pOutBits
++ = 255-*pInBits
;
237 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
239 // set bits to newly create HBITMAP
240 SetDIBits( hScreenDC
, hBmpBitmap
, 0,
241 aSize
.getY(), pAlphaBits
.get(),
242 (PBITMAPINFO
)&aDIB
, DIB_RGB_COLORS
);
244 uno::Sequence
< uno::Any
> args(1);
245 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
256 #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap"
257 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
259 ::rtl::OUString SAL_CALL
CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException
)
261 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME
) );
264 sal_Bool SAL_CALL
CanvasBitmap::supportsService( const ::rtl::OUString
& ServiceName
) throw (uno::RuntimeException
)
266 return ServiceName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME
) );
269 uno::Sequence
< ::rtl::OUString
> SAL_CALL
CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException
)
271 uno::Sequence
< ::rtl::OUString
> aRet(1);
272 aRet
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME
) );