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 <osl/diagnose.h>
21 #include <tools/helpers.hxx>
22 #include <vcl/bitmap.hxx>
23 #include <vcl/bitmapaccess.hxx>
24 #include <vcl/outdev.hxx>
27 #include <salinst.hxx>
29 #include <bitmapwriteaccess.hxx>
38 Bitmap::Bitmap(const Bitmap
& rBitmap
)
39 : mxSalBmp(rBitmap
.mxSalBmp
)
40 , maPrefMapMode(rBitmap
.maPrefMapMode
)
41 , maPrefSize(rBitmap
.maPrefSize
)
45 Bitmap::Bitmap(std::shared_ptr
<SalBitmap
> const & pSalBitmap
)
46 : mxSalBmp(pSalBitmap
)
47 , maPrefMapMode(MapMode(MapUnit::MapPixel
))
48 , maPrefSize(mxSalBmp
->GetSize())
52 Bitmap::Bitmap( const Size
& rSizePixel
, sal_uInt16 nBitCount
, const BitmapPalette
* pPal
)
54 if (rSizePixel
.Width() && rSizePixel
.Height())
57 BitmapPalette
* pRealPal
= nullptr;
65 aPal
.SetEntryCount( 2 );
66 aPal
[ 0 ] = COL_BLACK
;
67 aPal
[ 1 ] = COL_WHITE
;
69 else if( ( 4 == nBitCount
) || ( 8 == nBitCount
) )
71 aPal
.SetEntryCount( 1 << nBitCount
);
72 aPal
[ 0 ] = COL_BLACK
;
74 aPal
[ 2 ] = COL_GREEN
;
77 aPal
[ 5 ] = COL_MAGENTA
;
78 aPal
[ 6 ] = COL_BROWN
;
80 aPal
[ 8 ] = COL_LIGHTGRAY
;
81 aPal
[ 9 ] = COL_LIGHTBLUE
;
82 aPal
[ 10 ] = COL_LIGHTGREEN
;
83 aPal
[ 11 ] = COL_LIGHTCYAN
;
84 aPal
[ 12 ] = COL_LIGHTRED
;
85 aPal
[ 13 ] = COL_LIGHTMAGENTA
;
86 aPal
[ 14 ] = COL_YELLOW
;
87 aPal
[ 15 ] = COL_WHITE
;
89 // Create dither palette
92 sal_uInt16 nActCol
= 16;
94 for( sal_uInt16 nB
= 0; nB
< 256; nB
+= 51 )
95 for( sal_uInt16 nG
= 0; nG
< 256; nG
+= 51 )
96 for( sal_uInt16 nR
= 0; nR
< 256; nR
+= 51 )
97 aPal
[ nActCol
++ ] = BitmapColor( static_cast<sal_uInt8
>(nR
), static_cast<sal_uInt8
>(nG
), static_cast<sal_uInt8
>(nB
) );
99 // Set standard Office colors
100 aPal
[ nActCol
++ ] = BitmapColor( 0, 184, 255 );
105 pRealPal
= const_cast<BitmapPalette
*>(pPal
);
108 mxSalBmp
= ImplGetSVData()->mpDefInst
->CreateSalBitmap();
109 mxSalBmp
->Create( rSizePixel
, nBitCount
, pRealPal
? *pRealPal
: aPal
);
117 const BitmapPalette
& Bitmap::GetGreyPalette( int nEntries
)
119 static BitmapPalette aGreyPalette2
;
120 static BitmapPalette aGreyPalette4
;
121 static BitmapPalette aGreyPalette16
;
122 static BitmapPalette aGreyPalette256
;
124 // Create greyscale palette with 2, 4, 16 or 256 entries
125 if( 2 == nEntries
|| 4 == nEntries
|| 16 == nEntries
|| 256 == nEntries
)
129 if( !aGreyPalette2
.GetEntryCount() )
131 aGreyPalette2
.SetEntryCount( 2 );
132 aGreyPalette2
[ 0 ] = BitmapColor( 0, 0, 0 );
133 aGreyPalette2
[ 1 ] = BitmapColor( 255, 255, 255 );
136 return aGreyPalette2
;
138 else if( 4 == nEntries
)
140 if( !aGreyPalette4
.GetEntryCount() )
142 aGreyPalette4
.SetEntryCount( 4 );
143 aGreyPalette4
[ 0 ] = BitmapColor( 0, 0, 0 );
144 aGreyPalette4
[ 1 ] = BitmapColor( 85, 85, 85 );
145 aGreyPalette4
[ 2 ] = BitmapColor( 170, 170, 170 );
146 aGreyPalette4
[ 3 ] = BitmapColor( 255, 255, 255 );
149 return aGreyPalette4
;
151 else if( 16 == nEntries
)
153 if( !aGreyPalette16
.GetEntryCount() )
156 sal_uInt8
const cGreyInc
= 17;
158 aGreyPalette16
.SetEntryCount( 16 );
160 for( sal_uInt16 i
= 0; i
< 16; i
++, cGrey
= sal::static_int_cast
<sal_uInt8
>(cGrey
+ cGreyInc
) )
161 aGreyPalette16
[ i
] = BitmapColor( cGrey
, cGrey
, cGrey
);
164 return aGreyPalette16
;
168 if( !aGreyPalette256
.GetEntryCount() )
170 aGreyPalette256
.SetEntryCount( 256 );
172 for( sal_uInt16 i
= 0; i
< 256; i
++ )
173 aGreyPalette256
[ i
] = BitmapColor( static_cast<sal_uInt8
>(i
), static_cast<sal_uInt8
>(i
), static_cast<sal_uInt8
>(i
) );
176 return aGreyPalette256
;
181 OSL_FAIL( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
182 return aGreyPalette2
;
186 bool BitmapPalette::IsGreyPalette() const
188 const int nEntryCount
= GetEntryCount();
189 if( !nEntryCount
) // NOTE: an empty palette means 1:1 mapping
191 // See above: only certain entry values will result in a valid call to GetGreyPalette
192 if( nEntryCount
== 2 || nEntryCount
== 4 || nEntryCount
== 16 || nEntryCount
== 256 )
194 const BitmapPalette
& rGreyPalette
= Bitmap::GetGreyPalette( nEntryCount
);
195 if( rGreyPalette
== *this )
200 // TODO: is it worth to compare the entries for the general case?
201 if (nEntryCount
== 2)
203 const BitmapColor
& rCol0(maBitmapColor
[0]);
204 const BitmapColor
& rCol1(maBitmapColor
[1]);
205 bRet
= rCol0
.GetRed() == rCol0
.GetGreen() && rCol0
.GetRed() == rCol0
.GetBlue() &&
206 rCol1
.GetRed() == rCol1
.GetGreen() && rCol1
.GetRed() == rCol1
.GetBlue();
211 Bitmap
& Bitmap::operator=( const Bitmap
& rBitmap
)
213 if (this == &rBitmap
)
216 maPrefSize
= rBitmap
.maPrefSize
;
217 maPrefMapMode
= rBitmap
.maPrefMapMode
;
218 mxSalBmp
= rBitmap
.mxSalBmp
;
223 Bitmap
& Bitmap::operator=( Bitmap
&& rBitmap
) noexcept
225 maPrefSize
= std::move(rBitmap
.maPrefSize
);
226 maPrefMapMode
= std::move(rBitmap
.maPrefMapMode
);
227 mxSalBmp
= std::move(rBitmap
.mxSalBmp
);
232 bool Bitmap::operator==( const Bitmap
& rBmp
) const
234 if (rBmp
.mxSalBmp
== mxSalBmp
) // Includes both are nullptr
236 if (!rBmp
.mxSalBmp
|| !mxSalBmp
)
238 if (rBmp
.mxSalBmp
->GetSize() != mxSalBmp
->GetSize() ||
239 rBmp
.mxSalBmp
->GetBitCount() != mxSalBmp
->GetBitCount())
241 BitmapChecksum aChecksum1
, aChecksum2
;
242 rBmp
.mxSalBmp
->GetChecksum(aChecksum1
);
243 mxSalBmp
->GetChecksum(aChecksum2
);
244 // If the bitmaps can't calculate a checksum, best to regard them as different.
245 if (aChecksum1
== 0 || aChecksum2
== 0)
247 return aChecksum1
== aChecksum2
;
250 void Bitmap::SetEmpty()
252 maPrefMapMode
= MapMode();
257 Size
Bitmap::GetSizePixel() const
259 return( mxSalBmp
? mxSalBmp
->GetSize() : Size() );
262 sal_uInt16
Bitmap::GetBitCount() const
267 sal_uInt16 nBitCount
= mxSalBmp
->GetBitCount();
281 bool Bitmap::HasGreyPalette() const
283 const sal_uInt16 nBitCount
= GetBitCount();
284 bool bRet
= nBitCount
== 1;
286 ScopedInfoAccess
pIAcc(const_cast<Bitmap
&>(*this));
290 bRet
= pIAcc
->HasPalette() && pIAcc
->GetPalette().IsGreyPalette();
296 BitmapChecksum
Bitmap::GetChecksum() const
298 BitmapChecksum nRet
= 0;
302 mxSalBmp
->GetChecksum(nRet
);
306 // nRet == 0 => probably, we were not able to acquire
307 // the buffer in SalBitmap::updateChecksum;
308 // so, we need to update the imp bitmap for this bitmap instance
309 // as we do in BitmapInfoAccess::ImplCreate
310 std::shared_ptr
<SalBitmap
> xNewImpBmp(ImplGetSVData()->mpDefInst
->CreateSalBitmap());
311 if (xNewImpBmp
->Create(*mxSalBmp
, GetBitCount()))
313 Bitmap
* pThis
= const_cast<Bitmap
*>(this);
314 pThis
->mxSalBmp
= xNewImpBmp
;
315 mxSalBmp
->GetChecksum(nRet
);
323 void Bitmap::ImplMakeUnique()
325 if (mxSalBmp
&& mxSalBmp
.use_count() > 1)
327 std::shared_ptr
<SalBitmap
> xOldImpBmp
= mxSalBmp
;
328 mxSalBmp
= ImplGetSVData()->mpDefInst
->CreateSalBitmap();
329 mxSalBmp
->Create(*xOldImpBmp
);
333 void Bitmap::ReassignWithSize(const Bitmap
& rBitmap
)
335 const Size
aOldSizePix(GetSizePixel());
336 const Size
aNewSizePix(rBitmap
.GetSizePixel());
337 const MapMode
aOldMapMode(maPrefMapMode
);
340 if ((aOldSizePix
!= aNewSizePix
) && aOldSizePix
.Width() && aOldSizePix
.Height())
342 aNewPrefSize
.setWidth(FRound(maPrefSize
.Width() * aNewSizePix
.Width() / aOldSizePix
.Width()));
343 aNewPrefSize
.setHeight(FRound(maPrefSize
.Height() * aNewSizePix
.Height() / aOldSizePix
.Height()));
347 aNewPrefSize
= maPrefSize
;
352 maPrefSize
= aNewPrefSize
;
353 maPrefMapMode
= aOldMapMode
;
357 void Bitmap::ImplSetSalBitmap(const std::shared_ptr
<SalBitmap
>& xImpBmp
)
362 BitmapInfoAccess
* Bitmap::AcquireInfoAccess()
364 std::unique_ptr
<BitmapInfoAccess
> pInfoAccess(new BitmapInfoAccess( *this ));
371 return pInfoAccess
.release();
374 BitmapReadAccess
* Bitmap::AcquireReadAccess()
376 std::unique_ptr
<BitmapReadAccess
> pReadAccess(new BitmapReadAccess( *this ));
383 return pReadAccess
.release();
386 BitmapWriteAccess
* Bitmap::AcquireWriteAccess()
388 std::unique_ptr
<BitmapWriteAccess
> pWriteAccess(new BitmapWriteAccess( *this ));
395 return pWriteAccess
.release();
398 void Bitmap::ReleaseAccess( BitmapInfoAccess
* pBitmapAccess
)
400 delete pBitmapAccess
;
403 bool Bitmap::Crop( const tools::Rectangle
& rRectPixel
)
405 const Size
aSizePix( GetSizePixel() );
406 tools::Rectangle
aRect( rRectPixel
);
409 aRect
.Intersection( tools::Rectangle( Point(), aSizePix
) );
411 if( !aRect
.IsEmpty() && aSizePix
!= aRect
.GetSize())
413 ScopedReadAccess
pReadAcc(*this);
417 const tools::Rectangle
aNewRect( Point(), aRect
.GetSize() );
418 Bitmap
aNewBmp( aNewRect
.GetSize(), GetBitCount(), &pReadAcc
->GetPalette() );
419 BitmapScopedWriteAccess
pWriteAcc(aNewBmp
);
423 const long nOldX
= aRect
.Left();
424 const long nOldY
= aRect
.Top();
425 const long nNewWidth
= aNewRect
.GetWidth();
426 const long nNewHeight
= aNewRect
.GetHeight();
428 for( long nY
= 0, nY2
= nOldY
; nY
< nNewHeight
; nY
++, nY2
++ )
430 Scanline pScanline
= pWriteAcc
->GetScanline(nY
);
431 Scanline pScanlineRead
= pReadAcc
->GetScanline(nY2
);
432 for( long nX
= 0, nX2
= nOldX
; nX
< nNewWidth
; nX
++, nX2
++ )
433 pWriteAcc
->SetPixelOnData( pScanline
, nX
, pReadAcc
->GetPixelFromData( pScanlineRead
, nX2
) );
443 ReassignWithSize( aNewBmp
);
450 bool Bitmap::CopyPixel( const tools::Rectangle
& rRectDst
,
451 const tools::Rectangle
& rRectSrc
, const Bitmap
* pBmpSrc
)
453 const Size
aSizePix( GetSizePixel() );
454 tools::Rectangle
aRectDst( rRectDst
);
457 aRectDst
.Intersection( tools::Rectangle( Point(), aSizePix
) );
459 if( !aRectDst
.IsEmpty() )
461 if( pBmpSrc
&& ( pBmpSrc
->mxSalBmp
!= mxSalBmp
) )
463 Bitmap
* pSrc
= const_cast<Bitmap
*>(pBmpSrc
);
464 const Size
aCopySizePix( pSrc
->GetSizePixel() );
465 tools::Rectangle
aRectSrc( rRectSrc
);
466 const sal_uInt16 nSrcBitCount
= pBmpSrc
->GetBitCount();
467 const sal_uInt16 nDstBitCount
= GetBitCount();
469 if( nSrcBitCount
> nDstBitCount
)
473 if (nSrcBitCount
== 24)
474 Convert( BmpConversion::N24Bit
);
475 else if (nSrcBitCount
== 8)
477 Convert( BmpConversion::N8BitColors
);
480 else if (nSrcBitCount
== 4)
482 Convert( BmpConversion::N4BitColors
);
488 ScopedReadAccess
pSrcAcc(*pSrc
);
489 BitmapScopedWriteAccess
pDstAcc(*this);
491 if( pSrcAcc
&& pDstAcc
)
493 const int nSrcCount
= pDstAcc
->GetPaletteEntryCount();
494 const int nDstCount
= 1 << nDstBitCount
;
496 for (int i
= 0; ( i
< nSrcCount
) && ( nNextIndex
< nSrcCount
); ++i
)
498 const BitmapColor
& rSrcCol
= pSrcAcc
->GetPaletteColor( static_cast<sal_uInt16
>(i
) );
502 for (int j
= 0; j
< nDstCount
; ++j
)
504 if( rSrcCol
== pDstAcc
->GetPaletteColor( static_cast<sal_uInt16
>(j
) ) )
512 pDstAcc
->SetPaletteColor( static_cast<sal_uInt16
>(nNextIndex
++), rSrcCol
);
518 aRectSrc
.Intersection( tools::Rectangle( Point(), aCopySizePix
) );
520 if( !aRectSrc
.IsEmpty() )
522 ScopedReadAccess
pReadAcc(*pSrc
);
526 BitmapScopedWriteAccess
pWriteAcc(*this);
530 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
531 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
532 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
533 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
534 long nDstY
= aRectDst
.Top();
536 if( pReadAcc
->HasPalette() && pWriteAcc
->HasPalette() )
538 const sal_uInt16 nCount
= pReadAcc
->GetPaletteEntryCount();
539 std::unique_ptr
<sal_uInt8
[]> pMap(new sal_uInt8
[ nCount
]);
541 // Create index map for the color table, as the bitmap should be copied
542 // retaining it's color information relatively well
543 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
544 pMap
[ i
] = static_cast<sal_uInt8
>(pWriteAcc
->GetBestPaletteIndex( pReadAcc
->GetPaletteColor( i
) ));
546 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
548 Scanline pScanline
= pWriteAcc
->GetScanline(nDstY
);
549 Scanline pScanlineRead
= pReadAcc
->GetScanline(nSrcY
);
550 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
551 pWriteAcc
->SetPixelOnData( pScanline
, nDstX
, BitmapColor( pMap
[ pReadAcc
->GetIndexFromData( pScanlineRead
, nSrcX
) ] ));
554 else if( pReadAcc
->HasPalette() )
556 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
558 Scanline pScanline
= pWriteAcc
->GetScanline(nDstY
);
559 Scanline pScanlineRead
= pReadAcc
->GetScanline(nSrcY
);
560 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
561 pWriteAcc
->SetPixelOnData( pScanline
, nDstX
, pReadAcc
->GetPaletteColor( pReadAcc
->GetIndexFromData( pScanlineRead
, nSrcX
) ) );
565 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
567 Scanline pScanline
= pWriteAcc
->GetScanline(nDstY
);
568 Scanline pScanlineRead
= pReadAcc
->GetScanline(nSrcY
);
569 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
570 pWriteAcc
->SetPixelOnData( pScanline
, nDstX
, pReadAcc
->GetPixelFromData( pScanlineRead
, nSrcX
) );
574 bRet
= ( nWidth
> 0 ) && ( nHeight
> 0 );
583 tools::Rectangle
aRectSrc( rRectSrc
);
585 aRectSrc
.Intersection( tools::Rectangle( Point(), aSizePix
) );
587 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
589 BitmapScopedWriteAccess
pWriteAcc(*this);
593 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
594 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
595 const long nSrcX
= aRectSrc
.Left();
596 const long nSrcY
= aRectSrc
.Top();
597 const long nSrcEndX1
= nSrcX
+ nWidth
- 1;
598 const long nSrcEndY1
= nSrcY
+ nHeight
- 1;
599 const long nDstX
= aRectDst
.Left();
600 const long nDstY
= aRectDst
.Top();
601 const long nDstEndX1
= nDstX
+ nWidth
- 1;
602 const long nDstEndY1
= nDstY
+ nHeight
- 1;
604 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
606 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
608 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
609 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
610 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
611 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
614 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
616 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
618 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
619 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
620 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
621 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
624 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
626 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
628 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
629 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
630 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
631 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
636 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
638 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
639 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
640 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
641 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
655 bool Bitmap::CopyPixel_AlphaOptimized( const tools::Rectangle
& rRectDst
, const tools::Rectangle
& rRectSrc
,
656 const Bitmap
* pBmpSrc
)
658 // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
659 // This optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
660 const Size
aSizePix( GetSizePixel() );
661 tools::Rectangle
aRectDst( rRectDst
);
664 aRectDst
.Intersection( tools::Rectangle( Point(), aSizePix
) );
666 if( !aRectDst
.IsEmpty() )
668 if( pBmpSrc
&& ( pBmpSrc
->mxSalBmp
!= mxSalBmp
) )
670 Bitmap
* pSrc
= const_cast<Bitmap
*>(pBmpSrc
);
671 const Size
aCopySizePix( pSrc
->GetSizePixel() );
672 tools::Rectangle
aRectSrc( rRectSrc
);
674 aRectSrc
.Intersection( tools::Rectangle( Point(), aCopySizePix
) );
676 if( !aRectSrc
.IsEmpty() )
678 ScopedReadAccess
pReadAcc(*pSrc
);
682 BitmapScopedWriteAccess
pWriteAcc(*this);
686 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
687 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
688 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
689 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
690 long nDstY
= aRectDst
.Top();
692 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++)
694 Scanline pScanline
= pWriteAcc
->GetScanline(nDstY
);
695 Scanline pScanlineRead
= pReadAcc
->GetScanline(nSrcY
);
696 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
697 pWriteAcc
->SetPixelOnData( pScanline
, nDstX
, pReadAcc
->GetPixelFromData( pScanlineRead
, nSrcX
) );
701 bRet
= ( nWidth
> 0 ) && ( nHeight
> 0 );
710 tools::Rectangle
aRectSrc( rRectSrc
);
712 aRectSrc
.Intersection( tools::Rectangle( Point(), aSizePix
) );
714 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
716 BitmapScopedWriteAccess
pWriteAcc(*this);
720 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
721 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
722 const long nSrcX
= aRectSrc
.Left();
723 const long nSrcY
= aRectSrc
.Top();
724 const long nSrcEndX1
= nSrcX
+ nWidth
- 1;
725 const long nSrcEndY1
= nSrcY
+ nHeight
- 1;
726 const long nDstX
= aRectDst
.Left();
727 const long nDstY
= aRectDst
.Top();
728 const long nDstEndX1
= nDstX
+ nWidth
- 1;
729 const long nDstEndY1
= nDstY
+ nHeight
- 1;
731 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
733 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
735 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
736 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
737 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
738 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
741 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
743 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
745 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
746 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
747 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
748 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
751 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
753 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
755 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
756 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
757 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
758 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
763 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
765 Scanline pScanline
= pWriteAcc
->GetScanline(nYN
);
766 Scanline pScanlineSrc
= pWriteAcc
->GetScanline(nY
);
767 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
768 pWriteAcc
->SetPixelOnData( pScanline
, nXN
, pWriteAcc
->GetPixelFromData( pScanlineSrc
, nX
) );
783 bool Bitmap::Expand( sal_uLong nDX
, sal_uLong nDY
, const Color
* pInitColor
)
789 const Size
aSizePixel( GetSizePixel() );
790 const long nWidth
= aSizePixel
.Width();
791 const long nHeight
= aSizePixel
.Height();
792 const Size
aNewSize( nWidth
+ nDX
, nHeight
+ nDY
);
793 ScopedReadAccess
pReadAcc(*this);
797 BitmapPalette
aBmpPal( pReadAcc
->GetPalette() );
798 Bitmap
aNewBmp( aNewSize
, GetBitCount(), &aBmpPal
);
799 BitmapScopedWriteAccess
pWriteAcc(aNewBmp
);
804 const long nNewX
= nWidth
;
805 const long nNewY
= nHeight
;
806 const long nNewWidth
= pWriteAcc
->Width();
807 const long nNewHeight
= pWriteAcc
->Height();
812 aColor
= pWriteAcc
->GetBestMatchingColor( *pInitColor
);
814 for( nY
= 0; nY
< nHeight
; nY
++ )
816 pWriteAcc
->CopyScanline( nY
, *pReadAcc
);
818 if( pInitColor
&& nDX
)
820 Scanline pScanline
= pWriteAcc
->GetScanline(nY
);
821 for( nX
= nNewX
; nX
< nNewWidth
; nX
++ )
822 pWriteAcc
->SetPixelOnData( pScanline
, nX
, aColor
);
826 if( pInitColor
&& nDY
)
827 for( nY
= nNewY
; nY
< nNewHeight
; nY
++ )
829 Scanline pScanline
= pWriteAcc
->GetScanline(nY
);
830 for( nX
= 0; nX
< nNewWidth
; nX
++ )
831 pWriteAcc
->SetPixelOnData( pScanline
, nX
, aColor
);
841 ReassignWithSize(aNewBmp
);
848 Bitmap
Bitmap::CreateDisplayBitmap( OutputDevice
* pDisplay
)
850 Bitmap
aDispBmp( *this );
852 SalGraphics
* pDispGraphics
= pDisplay
->GetGraphics();
854 if( mxSalBmp
&& pDispGraphics
)
856 std::shared_ptr
<SalBitmap
> xImpDispBmp(ImplGetSVData()->mpDefInst
->CreateSalBitmap());
857 if (xImpDispBmp
->Create(*mxSalBmp
, pDispGraphics
))
858 aDispBmp
.ImplSetSalBitmap(xImpDispBmp
);
864 bool Bitmap::GetSystemData( BitmapSystemData
& rData
) const
866 return mxSalBmp
&& mxSalBmp
->GetSystemData(rData
);
869 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */