1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <canvas/debug.hxx>
23 #include <canvas/canvastools.hxx>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <tools/diagnose_ex.h>
27 #include <vcl/bitmapex.hxx>
29 #include <boost/preprocessor/repetition.hpp>
30 #include <boost/preprocessor/iteration/local.hpp>
31 #include <boost/scoped_array.hpp>
33 #include "dx_canvasbitmap.hxx"
34 #include "dx_impltools.hxx"
37 using namespace ::com::sun::star
;
41 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr
& rBitmap
,
42 const DeviceRef
& rDevice
) :
46 ENSURE_OR_THROW( mpDevice
.is() && mpBitmap
,
47 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
49 maCanvasHelper
.setDevice( *mpDevice
.get() );
50 maCanvasHelper
.setTarget( mpBitmap
);
53 void CanvasBitmap::disposeThis()
59 CanvasBitmap_Base::disposeThis();
64 BITMAPINFOHEADER bmiHeader
;
65 RGBQUAD bmiColors
[256];
68 uno::Any SAL_CALL
CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle
) throw (uno::RuntimeException
)
72 // 1 ... get Pixbuf with bitmap RGB content
73 // 2 ... get Pixbuf with bitmap alpha mask
76 // sorry, no BitmapEx here...
78 aRes
= ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64
>( (BitmapEx
*) NULL
) );
83 if(!mpBitmap
->hasAlpha())
86 mpBitmap
->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp
);
88 uno::Sequence
< uno::Any
> args(1);
89 args
[0] = uno::Any( sal_Int64(aHBmp
) );
95 // need to copy&convert the bitmap, since dx
96 // canvas uses inline alpha channel
97 HDC hScreenDC
=GetDC(NULL
);
98 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
99 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
,
105 BITMAPINFOHEADER aBIH
;
107 aBIH
.biSize
= sizeof( BITMAPINFOHEADER
);
108 aBIH
.biWidth
= aSize
.getX();
109 aBIH
.biHeight
= -aSize
.getY();
111 aBIH
.biBitCount
= 32;
112 aBIH
.biCompression
= BI_RGB
; // expects pixel in
115 aBIH
.biSizeImage
= 0;
116 aBIH
.biXPelsPerMeter
= 0;
117 aBIH
.biYPelsPerMeter
= 0;
119 aBIH
.biClrImportant
= 0;
121 Gdiplus::BitmapData aBmpData
;
122 aBmpData
.Width
= aSize
.getX();
123 aBmpData
.Height
= aSize
.getY();
124 aBmpData
.Stride
= 4*aBmpData
.Width
;
125 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
126 aBmpData
.Scan0
= NULL
;
127 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
128 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
129 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
130 Gdiplus::ImageLockModeRead
,
131 PixelFormat32bppARGB
, // outputs ARGB (big endian)
134 // failed to lock, bail out
138 // now aBmpData.Scan0 contains our bits - push
139 // them into HBITMAP, ignoring alpha
140 SetDIBits( hScreenDC
, hBmpBitmap
, 0, aSize
.getY(), aBmpData
.Scan0
, (PBITMAPINFO
)&aBIH
, DIB_RGB_COLORS
);
142 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
144 uno::Sequence
< uno::Any
> args(1);
145 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
154 if(!mpBitmap
->hasAlpha())
160 static AlphaDIB aDIB
=
162 {0,0,0,1,8,BI_RGB
,0,0,0,0,0},
164 // this here fills palette with grey
165 // level colors, starting from 0,0,0
167 #define BOOST_PP_LOCAL_MACRO(n_) \
168 BOOST_PP_COMMA_IF(n_) \
170 #define BOOST_PP_LOCAL_LIMITS (0, 255)
171 #include BOOST_PP_LOCAL_ITERATE()
175 // need to copy&convert the bitmap, since dx
176 // canvas uses inline alpha channel
177 HDC hScreenDC
=GetDC(NULL
);
178 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
179 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
, aSize
.getX(), aSize
.getY() );
183 aDIB
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
184 aDIB
.bmiHeader
.biWidth
= aSize
.getX();
185 aDIB
.bmiHeader
.biHeight
= -aSize
.getY();
186 aDIB
.bmiHeader
.biPlanes
= 1;
187 aDIB
.bmiHeader
.biBitCount
= 8;
188 aDIB
.bmiHeader
.biCompression
= BI_RGB
;
189 aDIB
.bmiHeader
.biSizeImage
= 0;
190 aDIB
.bmiHeader
.biXPelsPerMeter
= 0;
191 aDIB
.bmiHeader
.biYPelsPerMeter
= 0;
192 aDIB
.bmiHeader
.biClrUsed
= 0;
193 aDIB
.bmiHeader
.biClrImportant
= 0;
195 Gdiplus::BitmapData aBmpData
;
196 aBmpData
.Width
= aSize
.getX();
197 aBmpData
.Height
= aSize
.getY();
198 aBmpData
.Stride
= 4*aBmpData
.Width
;
199 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
200 aBmpData
.Scan0
= NULL
;
201 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
202 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
203 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
204 Gdiplus::ImageLockModeRead
,
205 PixelFormat32bppARGB
, // outputs ARGB (big endian)
208 // failed to lock, bail out
212 // copy only alpha channel to pAlphaBits
213 const sal_Int32
nScanWidth((aSize
.getX() + 3) & ~3);
214 boost::scoped_array
<sal_uInt8
> pAlphaBits( new sal_uInt8
[nScanWidth
*aSize
.getY()] );
215 const sal_uInt8
* pInBits
=(sal_uInt8
*)aBmpData
.Scan0
;
217 for( sal_Int32 y
=0; y
<aSize
.getY(); ++y
)
219 sal_uInt8
* pOutBits
=pAlphaBits
.get()+y
*nScanWidth
;
220 for( sal_Int32 x
=0; x
<aSize
.getX(); ++x
)
222 *pOutBits
++ = 255-*pInBits
;
227 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
229 // set bits to newly create HBITMAP
230 SetDIBits( hScreenDC
, hBmpBitmap
, 0,
231 aSize
.getY(), pAlphaBits
.get(),
232 (PBITMAPINFO
)&aDIB
, DIB_RGB_COLORS
);
234 uno::Sequence
< uno::Any
> args(1);
235 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
246 OUString SAL_CALL
CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException
)
248 return OUString( "DXCanvas.CanvasBitmap" );
251 sal_Bool SAL_CALL
CanvasBitmap::supportsService( const OUString
& ServiceName
) throw (uno::RuntimeException
)
253 return cppu::supportsService( this, ServiceName
);
256 uno::Sequence
< OUString
> SAL_CALL
CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException
)
258 uno::Sequence
< OUString
> aRet(1);
259 aRet
[0] = "com.sun.star.rendering.CanvasBitmap";
266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */