Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / source / gdi / bmpacc.cxx
blob84ca679f66dd4e82c4e0b5935f27775e338d6a18
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 <vcl/salbtype.hxx>
21 #include <vcl/bitmap.hxx>
22 #include <vcl/bitmapaccess.hxx>
24 #include <impbmp.hxx>
27 #include <string.h>
29 BitmapInfoAccess::BitmapInfoAccess( Bitmap& rBitmap, BitmapAccessMode nMode ) :
30 mpBuffer ( nullptr ),
31 mnAccessMode ( nMode )
33 ImplCreate( rBitmap );
36 BitmapInfoAccess::BitmapInfoAccess( Bitmap& rBitmap ) :
37 mpBuffer ( nullptr ),
38 mnAccessMode ( BitmapAccessMode::Info )
40 ImplCreate( rBitmap );
43 BitmapInfoAccess::~BitmapInfoAccess()
45 ImplDestroy();
48 void BitmapInfoAccess::ImplCreate( Bitmap& rBitmap )
50 std::shared_ptr<ImpBitmap> xImpBmp = rBitmap.ImplGetImpBitmap();
52 SAL_WARN_IF( !xImpBmp, "vcl", "Forbidden Access to empty bitmap!" );
54 if( xImpBmp )
56 if( mnAccessMode == BitmapAccessMode::Write && !maBitmap.ImplGetImpBitmap() )
58 xImpBmp.reset();
59 rBitmap.ImplMakeUnique();
60 xImpBmp = rBitmap.ImplGetImpBitmap();
62 else
64 DBG_ASSERT( mnAccessMode != BitmapAccessMode::Write ||
65 xImpBmp.use_count() == 2,
66 "Unpredictable results: bitmap is referenced more than once!" );
69 mpBuffer = xImpBmp->ImplAcquireBuffer( mnAccessMode );
71 if( !mpBuffer )
73 std::shared_ptr<ImpBitmap> xNewImpBmp(new ImpBitmap);
74 if (xNewImpBmp->ImplCreate(*xImpBmp, rBitmap.GetBitCount()))
76 xImpBmp = xNewImpBmp;
77 rBitmap.ImplSetImpBitmap( xImpBmp );
78 mpBuffer = xImpBmp->ImplAcquireBuffer( mnAccessMode );
82 maBitmap = rBitmap;
86 void BitmapInfoAccess::ImplDestroy()
88 std::shared_ptr<ImpBitmap> xImpBmp = maBitmap.ImplGetImpBitmap();
90 if (mpBuffer && xImpBmp)
92 xImpBmp->ImplReleaseBuffer( mpBuffer, mnAccessMode );
93 mpBuffer = nullptr;
97 sal_uInt16 BitmapInfoAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
99 return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
102 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, BitmapAccessMode nMode ) :
103 BitmapInfoAccess( rBitmap, nMode ),
104 mFncGetPixel ( nullptr ),
105 mFncSetPixel ( nullptr )
107 ImplInitScanBuffer( rBitmap );
110 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
111 BitmapInfoAccess( rBitmap, BitmapAccessMode::Read ),
112 mFncGetPixel ( nullptr ),
113 mFncSetPixel ( nullptr )
115 ImplInitScanBuffer( rBitmap );
118 BitmapReadAccess::~BitmapReadAccess()
122 void BitmapReadAccess::ImplInitScanBuffer( Bitmap& rBitmap )
124 if (!mpBuffer)
125 return;
127 std::shared_ptr<ImpBitmap> xImpBmp = rBitmap.ImplGetImpBitmap();
128 if (!xImpBmp)
129 return;
131 maColorMask = mpBuffer->maColorMask;
133 bool bOk = ImplSetAccessPointers(RemoveScanline(mpBuffer->mnFormat));
135 if (!bOk)
137 xImpBmp->ImplReleaseBuffer( mpBuffer, mnAccessMode );
138 mpBuffer = nullptr;
142 bool BitmapReadAccess::ImplSetAccessPointers( ScanlineFormat nFormat )
144 bool bRet = true;
146 switch( nFormat )
148 case ScanlineFormat::N1BitMsbPal:
150 mFncGetPixel = GetPixelForN1BitMsbPal;
151 mFncSetPixel = SetPixelForN1BitMsbPal;
153 break;
154 case ScanlineFormat::N1BitLsbPal:
156 mFncGetPixel = GetPixelForN1BitLsbPal;
157 mFncSetPixel = SetPixelForN1BitLsbPal;
159 break;
160 case ScanlineFormat::N4BitMsnPal:
162 mFncGetPixel = GetPixelForN4BitMsnPal;
163 mFncSetPixel = SetPixelForN4BitMsnPal;
165 break;
166 case ScanlineFormat::N4BitLsnPal:
168 mFncGetPixel = GetPixelForN4BitLsnPal;
169 mFncSetPixel = SetPixelForN4BitLsnPal;
171 break;
172 case ScanlineFormat::N8BitPal:
174 mFncGetPixel = GetPixelForN8BitPal;
175 mFncSetPixel = SetPixelForN8BitPal;
177 break;
178 case ScanlineFormat::N8BitTcMask:
180 mFncGetPixel = GetPixelForN8BitTcMask;
181 mFncSetPixel = SetPixelForN8BitTcMask;
183 break;
184 case ScanlineFormat::N16BitTcMsbMask:
186 mFncGetPixel = GetPixelForN16BitTcMsbMask;
187 mFncSetPixel = SetPixelForN16BitTcMsbMask;
189 break;
190 case ScanlineFormat::N16BitTcLsbMask:
192 mFncGetPixel = GetPixelForN16BitTcLsbMask;
193 mFncSetPixel = SetPixelForN16BitTcLsbMask;
195 break;
196 case ScanlineFormat::N24BitTcBgr:
198 mFncGetPixel = GetPixelForN24BitTcBgr;
199 mFncSetPixel = SetPixelForN24BitTcBgr;
201 break;
202 case ScanlineFormat::N24BitTcRgb:
204 mFncGetPixel = GetPixelForN24BitTcRgb;
205 mFncSetPixel = SetPixelForN24BitTcRgb;
207 break;
208 case ScanlineFormat::N32BitTcAbgr:
210 mFncGetPixel = GetPixelForN32BitTcAbgr;
211 mFncSetPixel = SetPixelForN32BitTcAbgr;
213 break;
214 case ScanlineFormat::N32BitTcArgb:
216 mFncGetPixel = GetPixelForN32BitTcArgb;
217 mFncSetPixel = SetPixelForN32BitTcArgb;
219 break;
220 case ScanlineFormat::N32BitTcBgra:
222 mFncGetPixel = GetPixelForN32BitTcBgra;
223 mFncSetPixel = SetPixelForN32BitTcBgra;
225 break;
226 case ScanlineFormat::N32BitTcRgba:
228 mFncGetPixel = GetPixelForN32BitTcRgba;
229 mFncSetPixel = SetPixelForN32BitTcRgba;
231 break;
232 case ScanlineFormat::N32BitTcMask:
234 mFncGetPixel = GetPixelForN32BitTcMask;
235 mFncSetPixel = SetPixelForN32BitTcMask;
237 break;
239 default:
240 bRet = false;
241 break;
244 return bRet;
247 BitmapColor BitmapReadAccess::GetInterpolatedColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
249 // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
250 // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
251 if(mpBuffer && fX >= 0.0 && fY >= 0.0)
253 const sal_Int32 nX(static_cast< sal_Int32 >(fX));
254 const sal_Int32 nY(static_cast< sal_Int32 >(fY));
256 if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
258 // get base-return value from inside pixel
259 BitmapColor aRetval(GetColor(nY, nX));
261 // calculate deltas and indices for neighbour accesses
262 sal_Int16 nDeltaX((fX - (nX + 0.5)) * 255.0); // [-255 .. 255]
263 sal_Int16 nDeltaY((fY - (nY + 0.5)) * 255.0); // [-255 .. 255]
264 sal_Int16 nIndX(0);
265 sal_Int16 nIndY(0);
267 if(nDeltaX > 0)
269 nIndX = nX + 1;
271 else
273 nIndX = nX - 1;
274 nDeltaX = -nDeltaX;
277 if(nDeltaY > 0)
279 nIndY = nY + 1;
281 else
283 nIndY = nY - 1;
284 nDeltaY = -nDeltaY;
287 // get right/left neighbour
288 BitmapColor aXCol(rFallback);
290 if(nDeltaX && nIndX >= 0 && nIndX < mpBuffer->mnWidth)
292 aXCol = GetColor(nY, nIndX);
295 // get top/bottom neighbour
296 BitmapColor aYCol(rFallback);
298 if(nDeltaY && nIndY >= 0 && nIndY < mpBuffer->mnHeight)
300 aYCol = GetColor(nIndY, nX);
303 // get one of four edge neighbours
304 BitmapColor aXYCol(rFallback);
306 if(nDeltaX && nDeltaY && nIndX >=0 && nIndY >= 0 && nIndX < mpBuffer->mnWidth && nIndY < mpBuffer->mnHeight)
308 aXYCol = GetColor(nIndY, nIndX);
311 // merge return value with right/left neighbour
312 if(aXCol != aRetval)
314 aRetval.Merge(aXCol, 255 - nDeltaX);
317 // merge top/bottom neighbour with edge
318 if(aYCol != aXYCol)
320 aYCol.Merge(aXYCol, 255 - nDeltaX);
323 // merge return value with already merged top/bottom neighbour
324 if(aRetval != aYCol)
326 aRetval.Merge(aYCol, 255 - nDeltaY);
329 return aRetval;
333 return rFallback;
336 BitmapColor BitmapReadAccess::GetColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
338 // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
339 // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
340 if(mpBuffer && fX >= 0.0 && fY >= 0.0)
342 const sal_Int32 nX(static_cast< sal_Int32 >(fX));
343 const sal_Int32 nY(static_cast< sal_Int32 >(fY));
345 if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
347 return GetColor(nY, nX);
351 return rFallback;
354 BitmapWriteAccess::BitmapWriteAccess(Bitmap& rBitmap)
355 : BitmapReadAccess(rBitmap, BitmapAccessMode::Write)
356 , mpLineColor()
357 , mpFillColor()
361 BitmapWriteAccess::~BitmapWriteAccess()
365 void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
367 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
368 SAL_WARN_IF( nY >= rReadAcc.Height(), "vcl", "y-coordinate in source out of range!" );
369 SAL_WARN_IF( ( !HasPalette() || !rReadAcc.HasPalette() ) && ( HasPalette() || rReadAcc.HasPalette() ), "vcl", "No copying possible between palette bitmap and TC bitmap!" );
371 if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
372 ( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
374 memcpy(GetScanline(nY), rReadAcc.GetScanline(nY), rReadAcc.GetScanlineSize());
376 else
377 // TODO: use fastbmp infrastructure
378 for( long nX = 0, nWidth = std::min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
379 SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
382 void BitmapWriteAccess::CopyScanline( long nY, ConstScanline aSrcScanline,
383 ScanlineFormat nSrcScanlineFormat, sal_uLong nSrcScanlineSize )
385 const ScanlineFormat nFormat = RemoveScanline( nSrcScanlineFormat );
387 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
388 DBG_ASSERT( ( HasPalette() && nFormat <= ScanlineFormat::N8BitPal ) ||
389 ( !HasPalette() && nFormat > ScanlineFormat::N8BitPal ),
390 "No copying possible between palette and non palette scanlines!" );
392 const sal_uLong nCount = std::min( GetScanlineSize(), nSrcScanlineSize );
394 if( nCount )
396 if( GetScanlineFormat() == RemoveScanline( nSrcScanlineFormat ) )
397 memcpy(GetScanline(nY), aSrcScanline, nCount);
398 else
400 DBG_ASSERT( nFormat != ScanlineFormat::N8BitTcMask &&
401 nFormat != ScanlineFormat::N16BitTcMsbMask && nFormat != ScanlineFormat::N16BitTcLsbMask &&
402 nFormat != ScanlineFormat::N32BitTcMask,
403 "No support for pixel formats with color masks yet!" );
405 // TODO: use fastbmp infrastructure
406 FncGetPixel pFncGetPixel;
408 switch( nFormat )
410 case ScanlineFormat::N1BitMsbPal: pFncGetPixel = GetPixelForN1BitMsbPal; break;
411 case ScanlineFormat::N1BitLsbPal: pFncGetPixel = GetPixelForN1BitLsbPal; break;
412 case ScanlineFormat::N4BitMsnPal: pFncGetPixel = GetPixelForN4BitMsnPal; break;
413 case ScanlineFormat::N4BitLsnPal: pFncGetPixel = GetPixelForN4BitLsnPal; break;
414 case ScanlineFormat::N8BitPal: pFncGetPixel = GetPixelForN8BitPal; break;
415 case ScanlineFormat::N8BitTcMask: pFncGetPixel = GetPixelForN8BitTcMask; break;
416 case ScanlineFormat::N16BitTcMsbMask: pFncGetPixel = GetPixelForN16BitTcMsbMask; break;
417 case ScanlineFormat::N16BitTcLsbMask: pFncGetPixel = GetPixelForN16BitTcLsbMask; break;
418 case ScanlineFormat::N24BitTcBgr: pFncGetPixel = GetPixelForN24BitTcBgr; break;
419 case ScanlineFormat::N24BitTcRgb: pFncGetPixel = GetPixelForN24BitTcRgb; break;
420 case ScanlineFormat::N32BitTcAbgr: pFncGetPixel = GetPixelForN32BitTcAbgr; break;
421 case ScanlineFormat::N32BitTcArgb: pFncGetPixel = GetPixelForN32BitTcArgb; break;
422 case ScanlineFormat::N32BitTcBgra: pFncGetPixel = GetPixelForN32BitTcBgra; break;
423 case ScanlineFormat::N32BitTcRgba: pFncGetPixel = GetPixelForN32BitTcRgba; break;
424 case ScanlineFormat::N32BitTcMask: pFncGetPixel = GetPixelForN32BitTcMask; break;
426 default:
427 pFncGetPixel = nullptr;
428 break;
431 if( pFncGetPixel )
433 const ColorMask aDummyMask;
435 for( long nX = 0, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
436 SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
442 void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
444 SAL_WARN_IF( ( !HasPalette() || !rReadAcc.HasPalette() ) && ( HasPalette() || rReadAcc.HasPalette() ), "vcl", "No copying possible between palette bitmap and TC bitmap!" );
446 if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
447 ( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
449 const long nHeight = std::min( mpBuffer->mnHeight, rReadAcc.Height() );
450 const sal_uLong nCount = nHeight * mpBuffer->mnScanlineSize;
452 memcpy( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
454 else
455 for( long nY = 0, nHeight = std::min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
456 CopyScanline( nY, rReadAcc );
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */