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 .
20 #include <sal/config.h>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <tools/diagnose_ex.h>
26 #include <vcl/bitmapex.hxx>
28 #include <canvas/canvastools.hxx>
30 #include "dx_canvasbitmap.hxx"
31 #include "dx_impltools.hxx"
34 using namespace ::com::sun::star
;
38 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr
& rBitmap
,
39 const DeviceRef
& rDevice
) :
43 ENSURE_OR_THROW( mpDevice
.is() && mpBitmap
,
44 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
46 maCanvasHelper
.setDevice( *mpDevice
);
47 maCanvasHelper
.setTarget( mpBitmap
);
50 void CanvasBitmap::disposeThis()
56 CanvasBitmap_Base::disposeThis();
63 BITMAPINFOHEADER bmiHeader
;
64 RGBQUAD bmiColors
[256];
66 : bmiHeader({0,0,0,1,8,BI_RGB
,0,0,0,0,0})
68 for (size_t i
= 0; i
< 256; ++i
)
70 // this here fills palette with grey level colors, starting
71 // from 0,0,0 up to 255,255,255
73 bmiColors
[i
] = { b
,b
,b
,b
};
80 uno::Any SAL_CALL
CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle
)
84 // 1 ... get Pixbuf with bitmap RGB content
85 // 2 ... get Pixbuf with bitmap alpha mask
88 // sorry, no BitmapEx here...
90 aRes
<<= reinterpret_cast<sal_Int64
>( nullptr );
95 if(!mpBitmap
->hasAlpha())
98 mpBitmap
->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp
);
100 uno::Sequence
< uno::Any
> args
{ uno::Any(reinterpret_cast<sal_Int64
>(aHBmp
)) };
105 // need to copy&convert the bitmap, since dx
106 // canvas uses inline alpha channel
107 HDC hScreenDC
=GetDC(nullptr);
108 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
109 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
,
115 BITMAPINFOHEADER aBIH
;
117 aBIH
.biSize
= sizeof( BITMAPINFOHEADER
);
118 aBIH
.biWidth
= aSize
.getX();
119 aBIH
.biHeight
= -aSize
.getY();
121 aBIH
.biBitCount
= 32;
122 aBIH
.biCompression
= BI_RGB
; // expects pixel in
125 aBIH
.biSizeImage
= 0;
126 aBIH
.biXPelsPerMeter
= 0;
127 aBIH
.biYPelsPerMeter
= 0;
129 aBIH
.biClrImportant
= 0;
131 Gdiplus::BitmapData aBmpData
;
132 aBmpData
.Width
= aSize
.getX();
133 aBmpData
.Height
= aSize
.getY();
134 aBmpData
.Stride
= 4*aBmpData
.Width
;
135 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
136 aBmpData
.Scan0
= nullptr;
137 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
138 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
139 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
140 Gdiplus::ImageLockModeRead
,
141 PixelFormat32bppARGB
, // outputs ARGB (big endian)
144 // failed to lock, bail out
148 // now aBmpData.Scan0 contains our bits - push
149 // them into HBITMAP, ignoring alpha
150 SetDIBits( hScreenDC
, hBmpBitmap
, 0, aSize
.getY(), aBmpData
.Scan0
, reinterpret_cast<PBITMAPINFO
>(&aBIH
), DIB_RGB_COLORS
);
152 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
154 uno::Sequence
< uno::Any
> args
{ uno::Any(reinterpret_cast<sal_Int64
>(hBmpBitmap
)) };
162 if(!mpBitmap
->hasAlpha())
168 static AlphaDIB aDIB
;
170 // need to copy&convert the bitmap, since dx
171 // canvas uses inline alpha channel
172 HDC hScreenDC
=GetDC(nullptr);
173 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
174 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
, aSize
.getX(), aSize
.getY() );
178 aDIB
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
179 aDIB
.bmiHeader
.biWidth
= aSize
.getX();
180 aDIB
.bmiHeader
.biHeight
= -aSize
.getY();
181 aDIB
.bmiHeader
.biPlanes
= 1;
182 aDIB
.bmiHeader
.biBitCount
= 8;
183 aDIB
.bmiHeader
.biCompression
= BI_RGB
;
184 aDIB
.bmiHeader
.biSizeImage
= 0;
185 aDIB
.bmiHeader
.biXPelsPerMeter
= 0;
186 aDIB
.bmiHeader
.biYPelsPerMeter
= 0;
187 aDIB
.bmiHeader
.biClrUsed
= 0;
188 aDIB
.bmiHeader
.biClrImportant
= 0;
190 Gdiplus::BitmapData aBmpData
;
191 aBmpData
.Width
= aSize
.getX();
192 aBmpData
.Height
= aSize
.getY();
193 aBmpData
.Stride
= 4*aBmpData
.Width
;
194 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
195 aBmpData
.Scan0
= nullptr;
196 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
197 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
198 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
199 Gdiplus::ImageLockModeRead
,
200 PixelFormat32bppARGB
, // outputs ARGB (big endian)
203 // failed to lock, bail out
207 // copy only alpha channel to pAlphaBits
208 const sal_Int32
nScanWidth((aSize
.getX() + 3) & ~3);
209 std::unique_ptr
<sal_uInt8
[]> pAlphaBits( new sal_uInt8
[nScanWidth
*aSize
.getY()] );
210 const sal_uInt8
* pInBits
=static_cast<sal_uInt8
*>(aBmpData
.Scan0
);
212 for( sal_Int32 y
=0; y
<aSize
.getY(); ++y
)
214 sal_uInt8
* pOutBits
=pAlphaBits
.get()+y
*nScanWidth
;
215 for( sal_Int32 x
=0; x
<aSize
.getX(); ++x
)
217 *pOutBits
++ = 255-*pInBits
;
222 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
224 // set bits to newly create HBITMAP
225 SetDIBits( hScreenDC
, hBmpBitmap
, 0,
226 aSize
.getY(), pAlphaBits
.get(),
227 reinterpret_cast<PBITMAPINFO
>(&aDIB
), DIB_RGB_COLORS
);
229 uno::Sequence
< uno::Any
> args
{ uno::Any(reinterpret_cast<sal_Int64
>(hBmpBitmap
)) };
239 OUString SAL_CALL
CanvasBitmap::getImplementationName( )
241 return "DXCanvas.CanvasBitmap";
244 sal_Bool SAL_CALL
CanvasBitmap::supportsService( const OUString
& ServiceName
)
246 return cppu::supportsService( this, ServiceName
);
249 uno::Sequence
< OUString
> SAL_CALL
CanvasBitmap::getSupportedServiceNames( )
251 return { "com.sun.star.rendering.CanvasBitmap" };
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */