bump product version to 7.2.5.1
[LibreOffice.git] / canvas / source / directx / dx_vcltools.cxx
blob912adf8b0af24561329aa101a340e1b9b634b4c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <basegfx/numeric/ftools.hxx>
23 #include <com/sun/star/lang/XServiceInfo.hpp>
24 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
25 #include <tools/diagnose_ex.h>
26 #include <vcl/bitmap.hxx>
27 #include <vcl/bitmapex.hxx>
28 #include <vcl/BitmapReadAccess.hxx>
29 #include <vcl/canvastools.hxx>
31 #include "dx_impltools.hxx"
32 #include "dx_vcltools.hxx"
34 using namespace ::com::sun::star;
36 namespace dxcanvas::tools
38 namespace
40 /// Calc number of colors in given BitmapInfoHeader
41 sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
43 if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
45 if( rBIH.biBitCount <= 8 )
47 if( rBIH.biClrUsed )
48 return rBIH.biClrUsed;
49 else
50 return 1 << rBIH.biBitCount;
53 else
55 BITMAPCOREHEADER const * pCoreHeader = reinterpret_cast<BITMAPCOREHEADER const *>(&rBIH);
57 if( pCoreHeader->bcBitCount <= 8 )
58 return 1 << pCoreHeader->bcBitCount;
61 return 0; // nothing known
64 /// Draw DI bits to given Graphics
65 bool drawDIBits( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
66 const void* hDIB )
68 bool bRet( false );
69 BitmapSharedPtr pBitmap;
71 const BITMAPINFO* pBI = static_cast<BITMAPINFO*>(GlobalLock( const_cast<void *>(hDIB) ));
73 if( pBI )
75 const BYTE* pBits = reinterpret_cast<BYTE const *>(pBI) + pBI->bmiHeader.biSize +
76 calcDIBColorCount( pBI->bmiHeader ) * sizeof( RGBQUAD );
78 // forward to outsourced GDI+ rendering method
79 // (header clashes)
80 bRet = tools::drawDIBits( rGraphics, *pBI, pBits );
82 GlobalUnlock( const_cast<void *>(hDIB) );
85 return bRet;
88 /** Draw VCL bitmap to given Graphics
90 @param rBmp
91 Reference to bitmap. Might get modified, in such a way
92 that it will hold a DIB after a successful function call.
94 bool drawVCLBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
95 ::Bitmap& rBmp )
97 BitmapSystemData aBmpSysData;
99 if( !rBmp.GetSystemData( aBmpSysData ) ||
100 !aBmpSysData.pDIB )
102 // first of all, ensure that Bitmap contains a DIB, by
103 // acquiring a read access
104 BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
106 // TODO(P2): Acquiring a read access can actually
107 // force a read from VRAM, thus, avoiding this
108 // step somehow will increase performance
109 // here.
110 if( pReadAcc )
112 // try again: now, WinSalBitmap must have
113 // generated a DIB
114 if( rBmp.GetSystemData( aBmpSysData ) &&
115 aBmpSysData.pDIB )
117 return drawDIBits( rGraphics,
118 aBmpSysData.pDIB );
121 Bitmap::ReleaseAccess( pReadAcc );
124 else
126 return drawDIBits( rGraphics,
127 aBmpSysData.pDIB );
130 // failed to generate DIBits from vcl bitmap
131 return false;
134 /** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BitmapEx
136 RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
138 // TODO(P2): Avoid temporary bitmap generation, maybe
139 // even ensure that created DIBs are copied back to
140 // BmpEx (currently, every AcquireReadAccess() will
141 // make the local bitmap copy unique, effectively
142 // duplicating the memory used)
144 ENSURE_OR_THROW( rBmpEx.IsAlpha(),
145 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
146 "BmpEx has no alpha" );
148 // convert transparent bitmap to 32bit RGBA
149 // ========================================
151 const ::Size aBmpSize( rBmpEx.GetSizePixel() );
153 RawRGBABitmap aBmpData;
154 aBmpData.mnWidth = aBmpSize.Width();
155 aBmpData.mnHeight = aBmpSize.Height();
156 aBmpData.maBitmapData.resize(4*aBmpData.mnWidth*aBmpData.mnHeight);
158 Bitmap aBitmap( rBmpEx.GetBitmap() );
160 Bitmap::ScopedReadAccess pReadAccess( aBitmap );
162 const sal_Int32 nWidth( aBmpSize.Width() );
163 const sal_Int32 nHeight( aBmpSize.Height() );
165 ENSURE_OR_THROW( pReadAccess.get() != nullptr,
166 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
167 "Unable to acquire read access to bitmap" );
169 Bitmap aAlpha( rBmpEx.GetAlpha().GetBitmap() );
171 Bitmap::ScopedReadAccess pAlphaReadAccess( aAlpha );
173 // By convention, the access buffer always has
174 // one of the following formats:
176 // ScanlineFormat::N1BitMsbPal
177 // ScanlineFormat::N8BitPal
178 // ScanlineFormat::N24BitTcBgr
179 // ScanlineFormat::N32BitTcMask
181 // and is always ScanlineFormat::BottomUp
183 // This is the way
184 // WinSalBitmap::AcquireBuffer() sets up the
185 // buffer
187 ENSURE_OR_THROW( pAlphaReadAccess.get() != nullptr,
188 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
189 "Unable to acquire read access to alpha" );
191 ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal,
192 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
193 "Unsupported alpha scanline format" );
195 BitmapColor aCol;
196 sal_uInt8* pCurrOutput(aBmpData.maBitmapData.data());
197 int x, y;
199 for( y=0; y<nHeight; ++y )
201 switch( pReadAccess->GetScanlineFormat() )
203 case ScanlineFormat::N8BitPal:
205 Scanline pScan = pReadAccess->GetScanline( y );
206 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
208 for( x=0; x<nWidth; ++x )
210 aCol = pReadAccess->GetPaletteColor( *pScan++ );
212 *pCurrOutput++ = aCol.GetBlue();
213 *pCurrOutput++ = aCol.GetGreen();
214 *pCurrOutput++ = aCol.GetRed();
216 // our notion of alpha is
217 // different from the rest
218 // of the world's
219 *pCurrOutput++ = 255 - static_cast<BYTE>(*pAScan++);
222 break;
224 case ScanlineFormat::N24BitTcBgr:
226 Scanline pScan = pReadAccess->GetScanline( y );
227 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
229 for( x=0; x<nWidth; ++x )
231 // store as RGBA
232 *pCurrOutput++ = *pScan++;
233 *pCurrOutput++ = *pScan++;
234 *pCurrOutput++ = *pScan++;
236 // our notion of alpha is
237 // different from the rest
238 // of the world's
239 *pCurrOutput++ = 255 - static_cast<BYTE>(*pAScan++);
242 break;
244 // TODO(P2): Might be advantageous
245 // to hand-formulate the following
246 // formats, too.
247 case ScanlineFormat::N1BitMsbPal:
248 case ScanlineFormat::N32BitTcMask:
250 Scanline pAScan = pAlphaReadAccess->GetScanline( y );
252 // using fallback for those
253 // seldom formats
254 for( x=0; x<nWidth; ++x )
256 // yes. x and y are swapped on Get/SetPixel
257 aCol = pReadAccess->GetColor(y,x);
259 *pCurrOutput++ = aCol.GetBlue();
260 *pCurrOutput++ = aCol.GetGreen();
261 *pCurrOutput++ = aCol.GetRed();
263 // our notion of alpha is
264 // different from the rest
265 // of the world's
266 *pCurrOutput++ = 255 - static_cast<BYTE>(*pAScan++);
269 break;
271 case ScanlineFormat::N1BitLsbPal:
272 case ScanlineFormat::N24BitTcRgb:
273 case ScanlineFormat::N32BitTcAbgr:
274 case ScanlineFormat::N32BitTcArgb:
275 case ScanlineFormat::N32BitTcBgra:
276 case ScanlineFormat::N32BitTcRgba:
277 default:
278 ENSURE_OR_THROW( false,
279 "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
280 "Unexpected scanline format - has "
281 "WinSalBitmap::AcquireBuffer() changed?" );
285 return aBmpData;
288 bool drawVCLBitmapEx( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
289 const ::BitmapEx& rBmpEx )
291 if( !rBmpEx.IsAlpha() )
293 Bitmap aBmp( rBmpEx.GetBitmap() );
294 return drawVCLBitmap( rGraphics, aBmp );
296 else
298 return drawRGBABits( rGraphics,
299 bitmapFromVCLBitmapEx( rBmpEx ) );
304 bool drawVCLBitmapFromXBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
305 const uno::Reference< rendering::XBitmap >& xBitmap )
307 // TODO(F2): add support for floating point bitmap formats
308 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
309 xBitmap, uno::UNO_QUERY );
311 if( !xIntBmp.is() )
312 return false;
314 ::BitmapEx aBmpEx = vcl::unotools::bitmapExFromXBitmap( xIntBmp );
315 if( aBmpEx.IsEmpty() )
316 return false;
318 return drawVCLBitmapEx( rGraphics, aBmpEx );
323 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */