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 <vcl/salbtype.hxx>
21 #include <vcl/bitmap.hxx>
22 #include <vcl/bitmapaccess.hxx>
29 BitmapInfoAccess::BitmapInfoAccess( Bitmap
& rBitmap
, BitmapAccessMode nMode
) :
31 mnAccessMode ( nMode
)
33 ImplCreate( rBitmap
);
36 BitmapInfoAccess::BitmapInfoAccess( Bitmap
& rBitmap
) :
38 mnAccessMode ( BitmapAccessMode::Info
)
40 ImplCreate( rBitmap
);
43 BitmapInfoAccess::~BitmapInfoAccess()
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!" );
56 if( mnAccessMode
== BitmapAccessMode::Write
&& !maBitmap
.ImplGetImpBitmap() )
59 rBitmap
.ImplMakeUnique();
60 xImpBmp
= rBitmap
.ImplGetImpBitmap();
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
);
73 std::shared_ptr
<ImpBitmap
> xNewImpBmp(new ImpBitmap
);
74 if (xNewImpBmp
->ImplCreate(*xImpBmp
, rBitmap
.GetBitCount()))
77 rBitmap
.ImplSetImpBitmap( xImpBmp
);
78 mpBuffer
= xImpBmp
->ImplAcquireBuffer( mnAccessMode
);
86 void BitmapInfoAccess::ImplDestroy()
88 std::shared_ptr
<ImpBitmap
> xImpBmp
= maBitmap
.ImplGetImpBitmap();
90 if (mpBuffer
&& xImpBmp
)
92 xImpBmp
->ImplReleaseBuffer( mpBuffer
, mnAccessMode
);
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
)
127 std::shared_ptr
<ImpBitmap
> xImpBmp
= rBitmap
.ImplGetImpBitmap();
131 maColorMask
= mpBuffer
->maColorMask
;
133 bool bOk
= ImplSetAccessPointers(RemoveScanline(mpBuffer
->mnFormat
));
137 xImpBmp
->ImplReleaseBuffer( mpBuffer
, mnAccessMode
);
142 bool BitmapReadAccess::ImplSetAccessPointers( ScanlineFormat nFormat
)
148 case ScanlineFormat::N1BitMsbPal
:
150 mFncGetPixel
= GetPixelForN1BitMsbPal
;
151 mFncSetPixel
= SetPixelForN1BitMsbPal
;
154 case ScanlineFormat::N1BitLsbPal
:
156 mFncGetPixel
= GetPixelForN1BitLsbPal
;
157 mFncSetPixel
= SetPixelForN1BitLsbPal
;
160 case ScanlineFormat::N4BitMsnPal
:
162 mFncGetPixel
= GetPixelForN4BitMsnPal
;
163 mFncSetPixel
= SetPixelForN4BitMsnPal
;
166 case ScanlineFormat::N4BitLsnPal
:
168 mFncGetPixel
= GetPixelForN4BitLsnPal
;
169 mFncSetPixel
= SetPixelForN4BitLsnPal
;
172 case ScanlineFormat::N8BitPal
:
174 mFncGetPixel
= GetPixelForN8BitPal
;
175 mFncSetPixel
= SetPixelForN8BitPal
;
178 case ScanlineFormat::N8BitTcMask
:
180 mFncGetPixel
= GetPixelForN8BitTcMask
;
181 mFncSetPixel
= SetPixelForN8BitTcMask
;
184 case ScanlineFormat::N16BitTcMsbMask
:
186 mFncGetPixel
= GetPixelForN16BitTcMsbMask
;
187 mFncSetPixel
= SetPixelForN16BitTcMsbMask
;
190 case ScanlineFormat::N16BitTcLsbMask
:
192 mFncGetPixel
= GetPixelForN16BitTcLsbMask
;
193 mFncSetPixel
= SetPixelForN16BitTcLsbMask
;
196 case ScanlineFormat::N24BitTcBgr
:
198 mFncGetPixel
= GetPixelForN24BitTcBgr
;
199 mFncSetPixel
= SetPixelForN24BitTcBgr
;
202 case ScanlineFormat::N24BitTcRgb
:
204 mFncGetPixel
= GetPixelForN24BitTcRgb
;
205 mFncSetPixel
= SetPixelForN24BitTcRgb
;
208 case ScanlineFormat::N32BitTcAbgr
:
210 mFncGetPixel
= GetPixelForN32BitTcAbgr
;
211 mFncSetPixel
= SetPixelForN32BitTcAbgr
;
214 case ScanlineFormat::N32BitTcArgb
:
216 mFncGetPixel
= GetPixelForN32BitTcArgb
;
217 mFncSetPixel
= SetPixelForN32BitTcArgb
;
220 case ScanlineFormat::N32BitTcBgra
:
222 mFncGetPixel
= GetPixelForN32BitTcBgra
;
223 mFncSetPixel
= SetPixelForN32BitTcBgra
;
226 case ScanlineFormat::N32BitTcRgba
:
228 mFncGetPixel
= GetPixelForN32BitTcRgba
;
229 mFncSetPixel
= SetPixelForN32BitTcRgba
;
232 case ScanlineFormat::N32BitTcMask
:
234 mFncGetPixel
= GetPixelForN32BitTcMask
;
235 mFncSetPixel
= SetPixelForN32BitTcMask
;
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]
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
314 aRetval
.Merge(aXCol
, 255 - nDeltaX
);
317 // merge top/bottom neighbour with edge
320 aYCol
.Merge(aXYCol
, 255 - nDeltaX
);
323 // merge return value with already merged top/bottom neighbour
326 aRetval
.Merge(aYCol
, 255 - nDeltaY
);
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
);
354 BitmapWriteAccess::BitmapWriteAccess(Bitmap
& rBitmap
)
355 : BitmapReadAccess(rBitmap
, BitmapAccessMode::Write
)
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());
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
);
396 if( GetScanlineFormat() == RemoveScanline( nSrcScanlineFormat
) )
397 memcpy(GetScanline(nY
), aSrcScanline
, nCount
);
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
;
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;
427 pFncGetPixel
= nullptr;
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
);
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: */