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 .
21 #include <ctype.h> // don't ask. msdev breaks otherwise...
22 #include <canvas/debug.hxx>
23 #include <canvas/canvastools.hxx>
24 #include <tools/diagnose_ex.h>
26 #include <vcl/bitmapex.hxx>
28 #include <boost/preprocessor/repetition.hpp>
29 #include <boost/preprocessor/iteration/local.hpp>
30 #include <boost/scoped_array.hpp>
32 #include "dx_canvasbitmap.hxx"
33 #include "dx_impltools.hxx"
36 using namespace ::com::sun::star
;
40 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr
& rBitmap
,
41 const DeviceRef
& rDevice
) :
45 ENSURE_OR_THROW( mpDevice
.is() && mpBitmap
,
46 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
48 maCanvasHelper
.setDevice( *mpDevice
.get() );
49 maCanvasHelper
.setTarget( mpBitmap
);
52 void CanvasBitmap::disposeThis()
58 CanvasBitmap_Base::disposeThis();
63 BITMAPINFOHEADER bmiHeader
;
64 RGBQUAD bmiColors
[256];
67 uno::Any SAL_CALL
CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle
) throw (uno::RuntimeException
)
71 // 1 ... get Pixbuf with bitmap RGB content
72 // 2 ... get Pixbuf with bitmap alpha mask
75 // sorry, no BitmapEx here...
77 aRes
= ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64
>( (BitmapEx
*) NULL
) );
82 if(!mpBitmap
->hasAlpha())
85 mpBitmap
->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp
);
87 uno::Sequence
< uno::Any
> args(1);
88 args
[0] = uno::Any( sal_Int64(aHBmp
) );
94 // need to copy&convert the bitmap, since dx
95 // canvas uses inline alpha channel
96 HDC hScreenDC
=GetDC(NULL
);
97 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
98 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
,
104 BITMAPINFOHEADER aBIH
;
106 aBIH
.biSize
= sizeof( BITMAPINFOHEADER
);
107 aBIH
.biWidth
= aSize
.getX();
108 aBIH
.biHeight
= -aSize
.getY();
110 aBIH
.biBitCount
= 32;
111 aBIH
.biCompression
= BI_RGB
; // expects pixel in
114 aBIH
.biSizeImage
= 0;
115 aBIH
.biXPelsPerMeter
= 0;
116 aBIH
.biYPelsPerMeter
= 0;
118 aBIH
.biClrImportant
= 0;
120 Gdiplus::BitmapData aBmpData
;
121 aBmpData
.Width
= aSize
.getX();
122 aBmpData
.Height
= aSize
.getY();
123 aBmpData
.Stride
= 4*aBmpData
.Width
;
124 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
125 aBmpData
.Scan0
= NULL
;
126 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
127 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
128 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
129 Gdiplus::ImageLockModeRead
,
130 PixelFormat32bppARGB
, // outputs ARGB (big endian)
133 // failed to lock, bail out
137 // now aBmpData.Scan0 contains our bits - push
138 // them into HBITMAP, ignoring alpha
139 SetDIBits( hScreenDC
, hBmpBitmap
, 0, aSize
.getY(), aBmpData
.Scan0
, (PBITMAPINFO
)&aBIH
, DIB_RGB_COLORS
);
141 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
143 uno::Sequence
< uno::Any
> args(1);
144 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
153 if(!mpBitmap
->hasAlpha())
159 static AlphaDIB aDIB
=
161 {0,0,0,1,8,BI_RGB
,0,0,0,0,0},
163 // this here fills palette with grey
164 // level colors, starting from 0,0,0
166 #define BOOST_PP_LOCAL_MACRO(n_) \
167 BOOST_PP_COMMA_IF(n_) \
169 #define BOOST_PP_LOCAL_LIMITS (0, 255)
170 #include BOOST_PP_LOCAL_ITERATE()
174 // need to copy&convert the bitmap, since dx
175 // canvas uses inline alpha channel
176 HDC hScreenDC
=GetDC(NULL
);
177 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
178 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
, aSize
.getX(), aSize
.getY() );
182 aDIB
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
183 aDIB
.bmiHeader
.biWidth
= aSize
.getX();
184 aDIB
.bmiHeader
.biHeight
= -aSize
.getY();
185 aDIB
.bmiHeader
.biPlanes
= 1;
186 aDIB
.bmiHeader
.biBitCount
= 8;
187 aDIB
.bmiHeader
.biCompression
= BI_RGB
;
188 aDIB
.bmiHeader
.biSizeImage
= 0;
189 aDIB
.bmiHeader
.biXPelsPerMeter
= 0;
190 aDIB
.bmiHeader
.biYPelsPerMeter
= 0;
191 aDIB
.bmiHeader
.biClrUsed
= 0;
192 aDIB
.bmiHeader
.biClrImportant
= 0;
194 Gdiplus::BitmapData aBmpData
;
195 aBmpData
.Width
= aSize
.getX();
196 aBmpData
.Height
= aSize
.getY();
197 aBmpData
.Stride
= 4*aBmpData
.Width
;
198 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
199 aBmpData
.Scan0
= NULL
;
200 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
201 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
202 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
203 Gdiplus::ImageLockModeRead
,
204 PixelFormat32bppARGB
, // outputs ARGB (big endian)
207 // failed to lock, bail out
211 // copy only alpha channel to pAlphaBits
212 const sal_Int32
nScanWidth((aSize
.getX() + 3) & ~3);
213 boost::scoped_array
<sal_uInt8
> pAlphaBits( new sal_uInt8
[nScanWidth
*aSize
.getY()] );
214 const sal_uInt8
* pInBits
=(sal_uInt8
*)aBmpData
.Scan0
;
217 for( sal_Int32 y
=0; y
<aSize
.getY(); ++y
)
219 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 #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap"
247 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
249 OUString SAL_CALL
CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException
)
251 return OUString( IMPLEMENTATION_NAME
);
254 sal_Bool SAL_CALL
CanvasBitmap::supportsService( const OUString
& ServiceName
) throw (uno::RuntimeException
)
256 return ServiceName
== SERVICE_NAME
;
259 uno::Sequence
< OUString
> SAL_CALL
CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException
)
261 uno::Sequence
< OUString
> aRet(1);
262 aRet
[0] = SERVICE_NAME
;
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */