update emoji autocorrect entries from po-files
[LibreOffice.git] / vcl / source / gdi / bmpacc.cxx
blob2e7982f07a68fd999f65125f43db97a760a03fb3
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/bmpacc.hxx>
24 #include <impbmp.hxx>
26 #include <osl/diagnose.h>
28 #include <string.h>
30 BitmapInfoAccess::BitmapInfoAccess( Bitmap& rBitmap, BitmapAccessMode nMode ) :
31 mpBuffer ( NULL ),
32 mnAccessMode ( nMode )
34 ImplCreate( rBitmap );
37 BitmapInfoAccess::BitmapInfoAccess( Bitmap& rBitmap ) :
38 mpBuffer ( NULL ),
39 mnAccessMode ( BITMAP_INFO_ACCESS )
41 ImplCreate( rBitmap );
44 BitmapInfoAccess::~BitmapInfoAccess()
46 ImplDestroy();
49 void BitmapInfoAccess::ImplCreate( Bitmap& rBitmap )
51 ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
53 DBG_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
55 if( pImpBmp )
57 if( mnAccessMode == BITMAP_WRITE_ACCESS && !maBitmap.ImplGetImpBitmap() )
59 rBitmap.ImplMakeUnique();
60 pImpBmp = rBitmap.ImplGetImpBitmap();
62 else
64 DBG_ASSERT( mnAccessMode != BITMAP_WRITE_ACCESS ||
65 pImpBmp->ImplGetRefCount() == 2,
66 "Unpredictable results: bitmap is referenced more than once!" );
69 mpBuffer = pImpBmp->ImplAcquireBuffer( mnAccessMode );
71 if( !mpBuffer )
73 ImpBitmap* pNewImpBmp = new ImpBitmap;
75 if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
77 pImpBmp = pNewImpBmp;
78 rBitmap.ImplSetImpBitmap( pImpBmp );
79 mpBuffer = pImpBmp->ImplAcquireBuffer( mnAccessMode );
81 else
82 delete pNewImpBmp;
85 maBitmap = rBitmap;
89 void BitmapInfoAccess::ImplDestroy()
91 ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
93 if( mpBuffer && pImpBmp )
95 pImpBmp->ImplReleaseBuffer( mpBuffer, mnAccessMode );
96 mpBuffer = NULL;
100 sal_uInt16 BitmapInfoAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
102 return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
105 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, BitmapAccessMode nMode ) :
106 BitmapInfoAccess( rBitmap, nMode ),
107 mpScanBuf ( NULL ),
108 mFncGetPixel ( NULL ),
109 mFncSetPixel ( NULL )
111 ImplInitScanBuffer( rBitmap );
114 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
115 BitmapInfoAccess( rBitmap, BITMAP_READ_ACCESS ),
116 mpScanBuf ( NULL ),
117 mFncGetPixel ( NULL ),
118 mFncSetPixel ( NULL )
120 ImplInitScanBuffer( rBitmap );
123 BitmapReadAccess::~BitmapReadAccess()
125 ImplClearScanBuffer();
128 void BitmapReadAccess::ImplInitScanBuffer( Bitmap& rBitmap )
130 ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
132 if( pImpBmp && mpBuffer )
134 const long nHeight = mpBuffer->mnHeight;
135 Scanline pTmpLine = mpBuffer->mpBits;
137 mpScanBuf = new Scanline[ nHeight ];
138 maColorMask = mpBuffer->maColorMask;
140 if( BMP_SCANLINE_ADJUSTMENT( mpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
142 for( long nY = 0L; nY < nHeight; nY++, pTmpLine += mpBuffer->mnScanlineSize )
143 mpScanBuf[ nY ] = pTmpLine;
145 else
147 for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
148 mpScanBuf[ nY ] = pTmpLine;
151 if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
153 delete[] mpScanBuf;
154 mpScanBuf = NULL;
156 pImpBmp->ImplReleaseBuffer( mpBuffer, mnAccessMode );
157 mpBuffer = NULL;
162 void BitmapReadAccess::ImplClearScanBuffer()
164 delete[] mpScanBuf;
165 mpScanBuf = NULL;
168 bool BitmapReadAccess::ImplSetAccessPointers( sal_uLong nFormat )
170 bool bRet = true;
172 switch( nFormat )
174 case BMP_FORMAT_1BIT_MSB_PAL:
176 mFncGetPixel = GetPixelFor_1BIT_MSB_PAL;
177 mFncSetPixel = SetPixelFor_1BIT_MSB_PAL;
179 break;
180 case BMP_FORMAT_1BIT_LSB_PAL:
182 mFncGetPixel = GetPixelFor_1BIT_LSB_PAL;
183 mFncSetPixel = SetPixelFor_1BIT_LSB_PAL;
185 break;
186 case BMP_FORMAT_4BIT_MSN_PAL:
188 mFncGetPixel = GetPixelFor_4BIT_MSN_PAL;
189 mFncSetPixel = SetPixelFor_4BIT_MSN_PAL;
191 break;
192 case BMP_FORMAT_4BIT_LSN_PAL:
194 mFncGetPixel = GetPixelFor_4BIT_LSN_PAL;
195 mFncSetPixel = SetPixelFor_4BIT_LSN_PAL;
197 break;
198 case BMP_FORMAT_8BIT_PAL:
200 mFncGetPixel = GetPixelFor_8BIT_PAL;
201 mFncSetPixel = SetPixelFor_8BIT_PAL;
203 break;
204 case BMP_FORMAT_8BIT_TC_MASK:
206 mFncGetPixel = GetPixelFor_8BIT_TC_MASK;
207 mFncSetPixel = SetPixelFor_8BIT_TC_MASK;
209 break;
210 case BMP_FORMAT_16BIT_TC_MSB_MASK:
212 mFncGetPixel = GetPixelFor_16BIT_TC_MSB_MASK;
213 mFncSetPixel = SetPixelFor_16BIT_TC_MSB_MASK;
215 break;
216 case BMP_FORMAT_16BIT_TC_LSB_MASK:
218 mFncGetPixel = GetPixelFor_16BIT_TC_LSB_MASK;
219 mFncSetPixel = SetPixelFor_16BIT_TC_LSB_MASK;
221 break;
222 case BMP_FORMAT_24BIT_TC_BGR:
224 mFncGetPixel = GetPixelFor_24BIT_TC_BGR;
225 mFncSetPixel = SetPixelFor_24BIT_TC_BGR;
227 break;
228 case BMP_FORMAT_24BIT_TC_RGB:
230 mFncGetPixel = GetPixelFor_24BIT_TC_RGB;
231 mFncSetPixel = SetPixelFor_24BIT_TC_RGB;
233 break;
234 case BMP_FORMAT_24BIT_TC_MASK:
236 mFncGetPixel = GetPixelFor_24BIT_TC_MASK;
237 mFncSetPixel = SetPixelFor_24BIT_TC_MASK;
239 break;
240 case BMP_FORMAT_32BIT_TC_ABGR:
242 mFncGetPixel = GetPixelFor_32BIT_TC_ABGR;
243 mFncSetPixel = SetPixelFor_32BIT_TC_ABGR;
245 break;
246 case BMP_FORMAT_32BIT_TC_ARGB:
248 mFncGetPixel = GetPixelFor_32BIT_TC_ARGB;
249 mFncSetPixel = SetPixelFor_32BIT_TC_ARGB;
251 break;
252 case BMP_FORMAT_32BIT_TC_BGRA:
254 mFncGetPixel = GetPixelFor_32BIT_TC_BGRA;
255 mFncSetPixel = SetPixelFor_32BIT_TC_BGRA;
257 break;
258 case BMP_FORMAT_32BIT_TC_RGBA:
260 mFncGetPixel = GetPixelFor_32BIT_TC_RGBA;
261 mFncSetPixel = SetPixelFor_32BIT_TC_RGBA;
263 break;
264 case BMP_FORMAT_32BIT_TC_MASK:
266 mFncGetPixel = GetPixelFor_32BIT_TC_MASK;
267 mFncSetPixel = SetPixelFor_32BIT_TC_MASK;
269 break;
271 default:
272 bRet = false;
273 break;
276 return bRet;
279 void BitmapReadAccess::ImplZeroInitUnusedBits()
281 const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
283 if( nWidth && nHeight && nScanSize && GetBuffer() )
285 sal_uInt32 nBits;
286 bool bMsb;
288 const sal_uLong nScanlineFormat = GetScanlineFormat();
289 switch( nScanlineFormat )
291 case( BMP_FORMAT_1BIT_MSB_PAL ):
292 nBits = 1;
293 bMsb = true;
294 break;
296 case( BMP_FORMAT_1BIT_LSB_PAL ):
297 nBits = 1;
298 bMsb = false;
299 break;
301 case( BMP_FORMAT_4BIT_MSN_PAL ):
302 nBits = 4;
303 bMsb = true;
304 break;
306 case( BMP_FORMAT_4BIT_LSN_PAL ):
307 nBits = 4;
308 bMsb = false;
309 break;
311 case( BMP_FORMAT_8BIT_PAL ):
312 case( BMP_FORMAT_8BIT_TC_MASK ):
313 bMsb = true;
314 nBits = 8;
315 break;
317 case( BMP_FORMAT_16BIT_TC_MSB_MASK ):
318 case( BMP_FORMAT_16BIT_TC_LSB_MASK ):
319 bMsb = true;
320 nBits = 16;
321 break;
323 case( BMP_FORMAT_24BIT_TC_BGR ):
324 case( BMP_FORMAT_24BIT_TC_RGB ):
325 case( BMP_FORMAT_24BIT_TC_MASK ):
326 bMsb = true;
327 nBits = 24;
328 break;
330 case( BMP_FORMAT_32BIT_TC_ABGR ):
331 case( BMP_FORMAT_32BIT_TC_ARGB ):
332 case( BMP_FORMAT_32BIT_TC_BGRA ):
333 case( BMP_FORMAT_32BIT_TC_RGBA ):
334 case( BMP_FORMAT_32BIT_TC_MASK ):
335 bMsb = true;
336 nBits = 32;
337 break;
339 default:
341 OSL_FAIL( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
342 nBits = 0;
343 bMsb = true;
345 break;
348 nBits *= nWidth;
349 if( nScanSize % 4 || !bMsb )
351 DBG_ASSERT( 8*nScanSize >= nBits,
352 "BitmapWriteAccess::ZeroInitUnusedBits: span size smaller than width?!");
353 const sal_uInt32 nLeftOverBits = 8*sizeof(sal_uInt8)*nScanSize - nBits;
354 if( nLeftOverBits != 0 ) // else there is really nothing to do
356 const sal_uInt32 nBytes = (nLeftOverBits + 7U) >> 3U;
357 sal_uInt8 nMask;
359 if( bMsb )
360 nMask = static_cast<sal_uInt8>(0xffU << (nLeftOverBits & 3UL));
361 else
362 nMask = static_cast<sal_uInt8>(0xffU >> (nLeftOverBits & 3UL));
364 sal_uInt8* pLastBytes = (sal_uInt8*)GetBuffer() + ( nScanSize - nBytes );
365 for( sal_uInt32 i = 0; i < nHeight; i++, pLastBytes += nScanSize )
367 *pLastBytes &= nMask;
368 for( sal_uInt32 j = 1; j < nBytes; j++ )
369 pLastBytes[j] = 0;
373 else if( nBits & 0x1f )
375 sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
376 sal_uInt8* pLast4Bytes = (sal_uInt8*) GetBuffer() + ( nScanSize - 4 );
378 #ifdef OSL_LITENDIAN
379 nMask = OSL_SWAPDWORD( nMask );
380 #endif
381 for( sal_uInt32 i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
382 *reinterpret_cast<sal_uInt32*>(pLast4Bytes) &= nMask;
387 BitmapColor BitmapReadAccess::GetInterpolatedColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
389 // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
390 // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
391 if(mpBuffer && fX >= 0.0 && fY >= 0.0)
393 const sal_Int32 nX(static_cast< sal_Int32 >(fX));
394 const sal_Int32 nY(static_cast< sal_Int32 >(fY));
396 if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
398 // get base-return value from inside pixel
399 BitmapColor aRetval(GetColor(nY, nX));
401 // calculate deltas and indices for neighbour accesses
402 sal_Int16 nDeltaX((fX - (nX + 0.5)) * 255.0); // [-255 .. 255]
403 sal_Int16 nDeltaY((fY - (nY + 0.5)) * 255.0); // [-255 .. 255]
404 sal_Int16 nIndX(0);
405 sal_Int16 nIndY(0);
407 if(nDeltaX > 0)
409 nIndX = nX + 1;
411 else
413 nIndX = nX - 1;
414 nDeltaX = -nDeltaX;
417 if(nDeltaY > 0)
419 nIndY = nY + 1;
421 else
423 nIndY = nY - 1;
424 nDeltaY = -nDeltaY;
427 // get right/left neighbour
428 BitmapColor aXCol(rFallback);
430 if(nDeltaX && nIndX >= 0 && nIndX < mpBuffer->mnWidth)
432 aXCol = GetColor(nY, nIndX);
435 // get top/bottom neighbour
436 BitmapColor aYCol(rFallback);
438 if(nDeltaY && nIndY >= 0 && nIndY < mpBuffer->mnHeight)
440 aYCol = GetColor(nIndY, nX);
443 // get one of four edge neighbours
444 BitmapColor aXYCol(rFallback);
446 if(nDeltaX && nDeltaY && nIndX >=0 && nIndY >= 0 && nIndX < mpBuffer->mnWidth && nIndY < mpBuffer->mnHeight)
448 aXYCol = GetColor(nIndY, nIndX);
451 // merge return value with right/left neighbour
452 if(aXCol != aRetval)
454 aRetval.Merge(aXCol, 255 - nDeltaX);
457 // merge top/bottom neighbour with edge
458 if(aYCol != aXYCol)
460 aYCol.Merge(aXYCol, 255 - nDeltaX);
463 // merge return value with already merged top/bottom neighbour
464 if(aRetval != aYCol)
466 aRetval.Merge(aYCol, 255 - nDeltaY);
469 return aRetval;
473 return rFallback;
476 BitmapColor BitmapReadAccess::GetColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
478 // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
479 // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
480 if(mpBuffer && fX >= 0.0 && fY >= 0.0)
482 const sal_Int32 nX(static_cast< sal_Int32 >(fX));
483 const sal_Int32 nY(static_cast< sal_Int32 >(fY));
485 if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
487 return GetColor(nY, nX);
491 return rFallback;
494 BitmapWriteAccess::BitmapWriteAccess(Bitmap& rBitmap)
495 : BitmapReadAccess(rBitmap, BITMAP_WRITE_ACCESS)
496 , mpLineColor()
497 , mpFillColor()
501 BitmapWriteAccess::~BitmapWriteAccess()
505 void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
507 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
508 DBG_ASSERT( nY < rReadAcc.Height(), "y-coordinate in source out of range!" );
509 DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
511 if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
512 ( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
514 memcpy( mpScanBuf[ nY ], rReadAcc.GetScanline( nY ), rReadAcc.GetScanlineSize() );
516 else
517 // TODO: use fastbmp infrastructure
518 for( long nX = 0L, nWidth = std::min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
519 SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
522 void BitmapWriteAccess::CopyScanline( long nY, ConstScanline aSrcScanline,
523 sal_uLong nSrcScanlineFormat, sal_uLong nSrcScanlineSize )
525 const sal_uLong nFormat = BMP_SCANLINE_FORMAT( nSrcScanlineFormat );
527 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
528 DBG_ASSERT( ( HasPalette() && nFormat <= BMP_FORMAT_8BIT_PAL ) ||
529 ( !HasPalette() && nFormat > BMP_FORMAT_8BIT_PAL ),
530 "No copying possible between palette and non palette scanlines!" );
532 const sal_uLong nCount = std::min( GetScanlineSize(), nSrcScanlineSize );
534 if( nCount )
536 if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
537 memcpy( mpScanBuf[ nY ], aSrcScanline, nCount );
538 else
540 DBG_ASSERT( nFormat != BMP_FORMAT_8BIT_TC_MASK &&
541 nFormat != BMP_FORMAT_16BIT_TC_MSB_MASK && nFormat != BMP_FORMAT_16BIT_TC_LSB_MASK &&
542 nFormat != BMP_FORMAT_24BIT_TC_MASK && nFormat != BMP_FORMAT_32BIT_TC_MASK,
543 "No support for pixel formats with color masks yet!" );
545 // TODO: use fastbmp infrastructure
546 FncGetPixel pFncGetPixel;
548 switch( nFormat )
550 case( BMP_FORMAT_1BIT_MSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_MSB_PAL; break;
551 case( BMP_FORMAT_1BIT_LSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_LSB_PAL; break;
552 case( BMP_FORMAT_4BIT_MSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_MSN_PAL; break;
553 case( BMP_FORMAT_4BIT_LSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_LSN_PAL; break;
554 case( BMP_FORMAT_8BIT_PAL ): pFncGetPixel = GetPixelFor_8BIT_PAL; break;
555 case( BMP_FORMAT_8BIT_TC_MASK ): pFncGetPixel = GetPixelFor_8BIT_TC_MASK; break;
556 case( BMP_FORMAT_16BIT_TC_MSB_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_MSB_MASK; break;
557 case( BMP_FORMAT_16BIT_TC_LSB_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_LSB_MASK; break;
558 case( BMP_FORMAT_24BIT_TC_BGR ): pFncGetPixel = GetPixelFor_24BIT_TC_BGR; break;
559 case( BMP_FORMAT_24BIT_TC_RGB ): pFncGetPixel = GetPixelFor_24BIT_TC_RGB; break;
560 case( BMP_FORMAT_24BIT_TC_MASK ): pFncGetPixel = GetPixelFor_24BIT_TC_MASK; break;
561 case( BMP_FORMAT_32BIT_TC_ABGR ): pFncGetPixel = GetPixelFor_32BIT_TC_ABGR; break;
562 case( BMP_FORMAT_32BIT_TC_ARGB ): pFncGetPixel = GetPixelFor_32BIT_TC_ARGB; break;
563 case( BMP_FORMAT_32BIT_TC_BGRA ): pFncGetPixel = GetPixelFor_32BIT_TC_BGRA; break;
564 case( BMP_FORMAT_32BIT_TC_RGBA ): pFncGetPixel = GetPixelFor_32BIT_TC_RGBA; break;
565 case( BMP_FORMAT_32BIT_TC_MASK ): pFncGetPixel = GetPixelFor_32BIT_TC_MASK; break;
567 default:
568 pFncGetPixel = NULL;
569 break;
572 if( pFncGetPixel )
574 const ColorMask aDummyMask;
576 for( long nX = 0L, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
577 SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
583 void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
585 DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
587 if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
588 ( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
590 const long nHeight = std::min( mpBuffer->mnHeight, rReadAcc.Height() );
591 const sal_uLong nCount = nHeight * mpBuffer->mnScanlineSize;
593 memcpy( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
595 else
596 for( long nY = 0L, nHeight = std::min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
597 CopyScanline( nY, rReadAcc );
600 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */