LibreOffice Module canvas (master) 1
dx_vcltools.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
23#include <com/sun/star/lang/XServiceInfo.hpp>
24#include <com/sun/star/rendering/XIntegerBitmap.hpp>
26#include <vcl/bitmap.hxx>
27#include <vcl/bitmapex.hxx>
29#include <vcl/canvastools.hxx>
30
31#include "dx_impltools.hxx"
32#include "dx_vcltools.hxx"
33
34using namespace ::com::sun::star;
35
36namespace dxcanvas::tools
37{
38 namespace
39 {
41 sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
42 {
43 if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
44 {
45 if( rBIH.biBitCount <= 8 )
46 {
47 if( rBIH.biClrUsed )
48 return rBIH.biClrUsed;
49 else
50 return 1 << rBIH.biBitCount;
51 }
52 }
53 else
54 {
55 BITMAPCOREHEADER const * pCoreHeader = reinterpret_cast<BITMAPCOREHEADER const *>(&rBIH);
56
57 if( pCoreHeader->bcBitCount <= 8 )
58 return 1 << pCoreHeader->bcBitCount;
59 }
60
61 return 0; // nothing known
62 }
63
65 bool drawDIBits( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
66 const void* hDIB )
67 {
68 bool bRet( false );
69
70 const BITMAPINFO* pBI = static_cast<BITMAPINFO*>(GlobalLock( const_cast<void *>(hDIB) ));
71
72 if( pBI )
73 {
74 const BYTE* pBits = reinterpret_cast<BYTE const *>(pBI) + pBI->bmiHeader.biSize +
75 calcDIBColorCount( pBI->bmiHeader ) * sizeof( RGBQUAD );
76
77 // forward to outsourced GDI+ rendering method
78 // (header clashes)
79 bRet = tools::drawDIBits( rGraphics, *pBI, pBits );
80
81 GlobalUnlock( const_cast<void *>(hDIB) );
82 }
83
84 return bRet;
85 }
86
93 bool drawVCLBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
94 ::Bitmap& rBmp )
95 {
96 BitmapSystemData aBmpSysData;
97
98 if( !rBmp.GetSystemData( aBmpSysData ) ||
99 !aBmpSysData.pDIB )
100 {
101 // first of all, ensure that Bitmap contains a DIB, by
102 // acquiring a read access
103 BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
104
105 // TODO(P2): Acquiring a read access can actually
106 // force a read from VRAM, thus, avoiding this
107 // step somehow will increase performance
108 // here.
109 if( pReadAcc )
110 {
111 // try again: now, WinSalBitmap must have
112 // generated a DIB
113 if( rBmp.GetSystemData( aBmpSysData ) &&
114 aBmpSysData.pDIB )
115 {
116 return drawDIBits( rGraphics,
117 aBmpSysData.pDIB );
118 }
119
120 Bitmap::ReleaseAccess( pReadAcc );
121 }
122 }
123 else
124 {
125 return drawDIBits( rGraphics,
126 aBmpSysData.pDIB );
127 }
128
129 // failed to generate DIBits from vcl bitmap
130 return false;
131 }
132
135 RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
136 {
137 // TODO(P2): Avoid temporary bitmap generation, maybe
138 // even ensure that created DIBs are copied back to
139 // BmpEx (currently, every AcquireReadAccess() will
140 // make the local bitmap copy unique, effectively
141 // duplicating the memory used)
142
143 ENSURE_OR_THROW( rBmpEx.IsAlpha(),
144 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
145 "BmpEx has no alpha" );
146
147 // convert transparent bitmap to 32bit RGBA
148 // ========================================
149
150 const ::Size aBmpSize( rBmpEx.GetSizePixel() );
151
152 RawRGBABitmap aBmpData;
153 aBmpData.mnWidth = aBmpSize.Width();
154 aBmpData.mnHeight = aBmpSize.Height();
155 aBmpData.maBitmapData.resize(4*aBmpData.mnWidth*aBmpData.mnHeight);
156
157 Bitmap aBitmap( rBmpEx.GetBitmap() );
158
159 Bitmap::ScopedReadAccess pReadAccess( aBitmap );
160
161 const sal_Int32 nWidth( aBmpSize.Width() );
162 const sal_Int32 nHeight( aBmpSize.Height() );
163
164 ENSURE_OR_THROW( pReadAccess.get() != nullptr,
165 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
166 "Unable to acquire read access to bitmap" );
167
168 Bitmap aAlpha( rBmpEx.GetAlphaMask().GetBitmap() );
169
170 Bitmap::ScopedReadAccess pAlphaReadAccess( aAlpha );
171
172 // By convention, the access buffer always has
173 // one of the following formats:
174
175 // ScanlineFormat::N1BitMsbPal
176 // ScanlineFormat::N8BitPal
177 // ScanlineFormat::N24BitTcBgr
178 // ScanlineFormat::N32BitTcMask
179
180 // and is always ScanlineFormat::BottomUp
181
182 // This is the way
183 // WinSalBitmap::AcquireBuffer() sets up the
184 // buffer
185
186 ENSURE_OR_THROW( pAlphaReadAccess.get() != nullptr,
187 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
188 "Unable to acquire read access to alpha" );
189
190 ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal,
191 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
192 "Unsupported alpha scanline format" );
193
194 BitmapColor aCol;
195 sal_uInt8* pCurrOutput(aBmpData.maBitmapData.data());
196 int x, y;
197
198 for( y=0; y<nHeight; ++y )
199 {
200 switch( pReadAccess->GetScanlineFormat() )
201 {
202 case ScanlineFormat::N8BitPal:
203 {
204 Scanline pScan = pReadAccess->GetScanline( y );
205 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
206
207 for( x=0; x<nWidth; ++x )
208 {
209 aCol = pReadAccess->GetPaletteColor( *pScan++ );
210
211 *pCurrOutput++ = aCol.GetBlue();
212 *pCurrOutput++ = aCol.GetGreen();
213 *pCurrOutput++ = aCol.GetRed();
214 *pCurrOutput++ = static_cast<BYTE>(*pAScan++);
215 }
216 }
217 break;
218
219 case ScanlineFormat::N24BitTcBgr:
220 {
221 Scanline pScan = pReadAccess->GetScanline( y );
222 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
223
224 for( x=0; x<nWidth; ++x )
225 {
226 // store as RGBA
227 *pCurrOutput++ = *pScan++;
228 *pCurrOutput++ = *pScan++;
229 *pCurrOutput++ = *pScan++;
230 *pCurrOutput++ = static_cast<BYTE>(*pAScan++);
231 }
232 }
233 break;
234
235 // TODO(P2): Might be advantageous
236 // to hand-formulate the following
237 // formats, too.
238 case ScanlineFormat::N1BitMsbPal:
239 case ScanlineFormat::N32BitTcMask:
240 {
241 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
242
243 // using fallback for those
244 // seldom formats
245 for( x=0; x<nWidth; ++x )
246 {
247 // yes. x and y are swapped on Get/SetPixel
248 aCol = pReadAccess->GetColor(y,x);
249
250 *pCurrOutput++ = aCol.GetBlue();
251 *pCurrOutput++ = aCol.GetGreen();
252 *pCurrOutput++ = aCol.GetRed();
253 *pCurrOutput++ = static_cast<BYTE>(*pAScan++);
254 }
255 }
256 break;
257
258 case ScanlineFormat::N24BitTcRgb:
259 case ScanlineFormat::N32BitTcAbgr:
260 case ScanlineFormat::N32BitTcArgb:
261 case ScanlineFormat::N32BitTcBgra:
262 case ScanlineFormat::N32BitTcRgba:
263 default:
264 ENSURE_OR_THROW( false,
265 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
266 "Unexpected scanline format - has "
267 "WinSalBitmap::AcquireBuffer() changed?" );
268 }
269 }
270
271 return aBmpData;
272 }
273
274 bool drawVCLBitmapEx( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
275 const ::BitmapEx& rBmpEx )
276 {
277 if( !rBmpEx.IsAlpha() )
278 {
279 Bitmap aBmp( rBmpEx.GetBitmap() );
280 return drawVCLBitmap( rGraphics, aBmp );
281 }
282 else
283 {
284 return drawRGBABits( rGraphics,
285 bitmapFromVCLBitmapEx( rBmpEx ) );
286 }
287 }
288 }
289
290 bool drawVCLBitmapFromXBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
291 const uno::Reference< rendering::XBitmap >& xBitmap )
292 {
293 // TODO(F2): add support for floating point bitmap formats
294 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
295 xBitmap, uno::UNO_QUERY );
296
297 if( !xIntBmp.is() )
298 return false;
299
301 if( aBmpEx.IsEmpty() )
302 return false;
303
304 return drawVCLBitmapEx( rGraphics, aBmpEx );
305 }
306}
307
308
309/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 * Scanline
bool IsEmpty() const
static void ReleaseAccess(BitmapInfoAccess *pAccess)
BitmapReadAccess * AcquireReadAccess()
bool GetSystemData(BitmapSystemData &rData) const
#define ENSURE_OR_THROW(c, m)
float y
Definition: dx_9rm.cxx:190
float x
Definition: dx_9rm.cxx:190
Gdiplus::BitmapData aBmpData
bool drawDIBits(const std::shared_ptr< Gdiplus::Graphics > &rGraphics, const BITMAPINFO &rBI, const void *pBits)
bool drawVCLBitmapFromXBitmap(const std::shared_ptr< Gdiplus::Graphics > &rGraphics, const uno::Reference< rendering::XBitmap > &xBitmap)
bool drawRGBABits(const std::shared_ptr< Gdiplus::Graphics > &rGraphics, const RawRGBABitmap &rRawRGBAData)
::BitmapEx bitmapExFromXBitmap(const uno::Reference< rendering::XIntegerReadOnlyBitmap > &xInputBitmap)
unsigned char sal_uInt8
unsigned char BYTE