nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / bitmap / salbmp.cxx
blob8393df96f47dde0f52b2edc571d23d29f6ca4fa0
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 <salbmp.hxx>
22 static BitmapChecksum scanlineChecksum(BitmapChecksum nCrc, const sal_uInt8* bits, int lineBitsCount, sal_uInt8 extraBitsMask)
24 if( lineBitsCount / 8 > 0 )
25 nCrc = vcl_get_checksum( nCrc, bits, lineBitsCount / 8 );
26 if( extraBitsMask != 0 )
28 sal_uInt8 extraByte = bits[ lineBitsCount / 8 ] & extraBitsMask;
29 nCrc = vcl_get_checksum( nCrc, &extraByte, 1 );
31 return nCrc;
34 void SalBitmap::updateChecksum() const
36 if (mbChecksumValid)
37 return;
39 BitmapChecksum nCrc = 0;
40 SalBitmap* pThis = const_cast<SalBitmap*>(this);
41 BitmapBuffer* pBuf = pThis->AcquireBuffer(BitmapAccessMode::Read);
42 if (pBuf)
44 nCrc = pBuf->maPalette.GetChecksum();
45 const int lineBitsCount = pBuf->mnWidth * pBuf->mnBitCount;
46 // With 1bpp/4bpp format we need to check only used bits in the last byte.
47 sal_uInt8 extraBitsMask = 0;
48 if( lineBitsCount % 8 != 0 )
50 const int extraBitsCount = lineBitsCount % 8;
51 switch( RemoveScanline( pBuf->mnFormat ))
53 case ScanlineFormat::N1BitMsbPal:
55 static const sal_uInt8 mask1Bit[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
56 extraBitsMask = mask1Bit[ extraBitsCount ];
57 break;
59 case ScanlineFormat::N1BitLsbPal:
61 static const sal_uInt8 mask1Bit[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
62 extraBitsMask = mask1Bit[ extraBitsCount ];
63 break;
65 case ScanlineFormat::N4BitMsnPal:
66 assert(extraBitsCount == 4);
67 extraBitsMask = 0xf0;
68 break;
69 case ScanlineFormat::N4BitLsnPal:
70 assert(extraBitsCount == 4);
71 extraBitsMask = 0x0f;
72 break;
73 default:
74 break;
77 if( pBuf->mnFormat & ScanlineFormat::TopDown )
79 if( pBuf->mnScanlineSize == lineBitsCount / 8 )
80 nCrc = vcl_get_checksum(nCrc, pBuf->mpBits, pBuf->mnScanlineSize * pBuf->mnHeight);
81 else // Do not include padding with undefined content in the checksum.
82 for( tools::Long y = 0; y < pBuf->mnHeight; ++y )
83 nCrc = scanlineChecksum(nCrc, pBuf->mpBits + y * pBuf->mnScanlineSize, lineBitsCount, extraBitsMask);
85 else // Compute checksum in the order of scanlines, to make it consistent between different bitmap implementations.
87 for( tools::Long y = pBuf->mnHeight - 1; y >= 0; --y )
88 nCrc = scanlineChecksum(nCrc, pBuf->mpBits + y * pBuf->mnScanlineSize, lineBitsCount, extraBitsMask);
90 pThis->ReleaseBuffer(pBuf, BitmapAccessMode::Read);
91 pThis->mnChecksum = nCrc;
92 pThis->mbChecksumValid = true;
94 else
96 pThis->mbChecksumValid = false;
100 namespace
103 class ImplPixelFormat
105 protected:
106 const sal_uInt8* mpData;
107 public:
108 static ImplPixelFormat* GetFormat( sal_uInt16 nBits, const BitmapPalette& rPalette );
110 virtual void StartLine( const sal_uInt8* pLine ) { mpData = pLine; }
111 virtual const BitmapColor& ReadPixel() = 0;
112 virtual ~ImplPixelFormat() { }
115 class ImplPixelFormat8 : public ImplPixelFormat
117 private:
118 const BitmapPalette& mrPalette;
120 public:
121 explicit ImplPixelFormat8( const BitmapPalette& rPalette )
122 : mrPalette( rPalette )
125 virtual const BitmapColor& ReadPixel() override
127 assert( mrPalette.GetEntryCount() > *mpData );
128 return mrPalette[ *mpData++ ];
132 class ImplPixelFormat4 : public ImplPixelFormat
134 private:
135 const BitmapPalette& mrPalette;
136 sal_uInt32 mnX;
137 sal_uInt32 mnShift;
139 public:
140 explicit ImplPixelFormat4( const BitmapPalette& rPalette )
141 : mrPalette( rPalette )
142 , mnX(0)
143 , mnShift(4)
146 virtual void StartLine( const sal_uInt8* pLine ) override
148 mpData = pLine;
149 mnX = 0;
150 mnShift = 4;
152 virtual const BitmapColor& ReadPixel() override
154 sal_uInt32 nIdx = ( mpData[mnX >> 1] >> mnShift) & 0x0f;
155 assert( mrPalette.GetEntryCount() > nIdx );
156 const BitmapColor& rColor = mrPalette[nIdx];
157 mnX++;
158 mnShift ^= 4;
159 return rColor;
163 class ImplPixelFormat1 : public ImplPixelFormat
165 private:
166 const BitmapPalette& mrPalette;
167 sal_uInt32 mnX;
169 public:
170 explicit ImplPixelFormat1( const BitmapPalette& rPalette )
171 : mrPalette(rPalette)
172 , mnX(0)
175 virtual void StartLine( const sal_uInt8* pLine ) override
177 mpData = pLine;
178 mnX = 0;
180 virtual const BitmapColor& ReadPixel() override
182 const BitmapColor& rColor = mrPalette[ (mpData[mnX >> 3 ] >> ( 7 - ( mnX & 7 ) )) & 1];
183 mnX++;
184 return rColor;
188 ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalette& rPalette )
190 switch( nBits )
192 case 1: return new ImplPixelFormat1( rPalette );
193 case 4: return new ImplPixelFormat4( rPalette );
194 case 8: return new ImplPixelFormat8( rPalette );
197 return nullptr;
200 // Optimized conversion from 1bpp. Currently LO uses 1bpp bitmaps for masks, which is nowadays
201 // a lousy obsolete format, as the memory saved is just not worth the cost of fiddling with the bits.
202 // Ideally LO should move to RGBA bitmaps. Until then, try to be faster with 1bpp bitmaps.
203 typedef void(*WriteColorFunction)( sal_uInt8 color8Bit, sal_uInt8*& dst );
204 void writeColorA8(sal_uInt8 color8Bit, sal_uInt8*& dst ) { *dst++ = color8Bit; };
205 void writeColorRGB(sal_uInt8 color8Bit, sal_uInt8*& dst ) { *dst++ = color8Bit; *dst++ = color8Bit; *dst++ = color8Bit; };
206 void writeColorRGBA(sal_uInt8 color8Bit, sal_uInt8*& dst ) { *dst++ = color8Bit; *dst++ = color8Bit; *dst++ = color8Bit; *dst++ = 0xff; };
207 typedef void(*WriteBlackWhiteFunction)( sal_uInt8*& dst, int count );
208 void writeBlackA8(sal_uInt8*& dst, int count ) { memset( dst, 0, count ); dst += count; };
209 void writeWhiteA8(sal_uInt8*& dst, int count ) { memset( dst, 0xff, count ); dst += count; };
210 void writeBlackRGB(sal_uInt8*& dst, int count ) { memset( dst, 0, count * 3 ); dst += count * 3; };
211 void writeWhiteRGB(sal_uInt8*& dst, int count ) { memset( dst, 0xff, count * 3 ); dst += count * 3; };
212 void writeWhiteRGBA(sal_uInt8*& dst, int count ) { memset( dst, 0xff, count * 4 ); dst += count * 4; };
213 void writeBlackRGBA(sal_uInt8*& dst, int count )
215 for( int i = 0; i < count; ++i )
217 dst[0] = 0x00;
218 dst[1] = 0x00;
219 dst[2] = 0x00;
220 dst[3] = 0xff;
221 dst += 4;
225 template< WriteColorFunction func, WriteBlackWhiteFunction funcBlack, WriteBlackWhiteFunction funcWhite >
226 void writeBlackWhiteData( const sal_uInt8* src, sal_uInt8* dst, int width, int height, int bytesPerRow )
228 for( int y = 0; y < height; ++y )
230 const sal_uInt8* srcLine = src;
231 int xsize = width;
232 while( xsize >= 64 )
234 // TODO alignment?
235 const sal_uInt64* src64 = reinterpret_cast< const sal_uInt64* >( src );
236 if( *src64 == 0x00 )
237 funcBlack( dst, 64 );
238 else if( *src64 == static_cast< sal_uInt64 >( -1 ))
239 funcWhite( dst, 64 );
240 else
241 break;
242 src += sizeof( sal_uInt64 );
243 xsize -= 64;
245 while( xsize >= 8 )
247 if( *src == 0x00 ) // => eight black pixels
248 funcBlack( dst, 8 );
249 else if( *src == 0xff ) // => eight white pixels
250 funcWhite( dst, 8 );
251 else
252 for( int bit = 7; bit >= 0; --bit )
253 func(( *src >> bit ) & 1 ? 0xff : 0, dst );
254 ++src;
255 xsize -= 8;
257 for( int bit = 7; bit > 7 - xsize; --bit )
258 func(( *src >> bit ) & 1 ? 0xff : 0, dst );
259 ++src;
260 src = srcLine + bytesPerRow;
264 } // namespace
266 std::unique_ptr< sal_uInt8[] > SalBitmap::convertDataBitCount( const sal_uInt8* src,
267 int width, int height, int bitCount, int bytesPerRow, const BitmapPalette& palette, BitConvert type )
269 assert( bitCount == 1 || bitCount == 4 || bitCount == 8 );
270 static const int bpp[] = { 1, 3, 3, 4, 4 };
271 std::unique_ptr< sal_uInt8[] > data( new sal_uInt8[width * height * bpp[ static_cast<int>(type) ]] );
273 if(type == BitConvert::A8 && bitCount == 8 && palette.IsGreyPalette8Bit())
274 { // no actual data conversion
275 for( int y = 0; y < height; ++y )
276 memcpy( data.get() + y * width, src + y * bytesPerRow, width );
277 return data;
280 if(bitCount == 1 && palette.GetEntryCount() == 2 && palette[ 0 ] == COL_BLACK && palette[ 1 ] == COL_WHITE)
282 switch( type )
284 case BitConvert::A8 :
285 writeBlackWhiteData< writeColorA8, writeBlackA8, writeWhiteA8 >
286 ( src, data.get(), width, height, bytesPerRow );
287 return data;
288 case BitConvert::BGR :
289 case BitConvert::RGB :
290 // BGR/RGB is the same, all 3 values get the same value
291 writeBlackWhiteData< writeColorRGB, writeBlackRGB, writeWhiteRGB >
292 ( src, data.get(), width, height, bytesPerRow );
293 return data;
294 case BitConvert::BGRA :
295 case BitConvert::RGBA :
296 // BGRA/RGBA is the same, all 3 values get the same value
297 writeBlackWhiteData< writeColorRGBA, writeBlackRGBA, writeWhiteRGBA >
298 ( src, data.get(), width, height, bytesPerRow );
299 return data;
303 std::unique_ptr<ImplPixelFormat> pSrcFormat(ImplPixelFormat::GetFormat(bitCount, palette));
305 const sal_uInt8* pSrcData = src;
306 sal_uInt8* pDstData = data.get();
308 sal_uInt32 nY = height;
309 while( nY-- )
311 pSrcFormat->StartLine( pSrcData );
313 sal_uInt32 nX = width;
314 switch( type )
316 case BitConvert::A8 :
317 while( nX-- )
319 const BitmapColor& c = pSrcFormat->ReadPixel();
320 *pDstData++ = c.GetBlue();
322 break;
323 case BitConvert::BGR :
324 while( nX-- )
326 const BitmapColor& c = pSrcFormat->ReadPixel();
327 *pDstData++ = c.GetBlue();
328 *pDstData++ = c.GetGreen();
329 *pDstData++ = c.GetRed();
331 break;
332 case BitConvert::RGB :
333 while( nX-- )
335 const BitmapColor& c = pSrcFormat->ReadPixel();
336 *pDstData++ = c.GetRed();
337 *pDstData++ = c.GetGreen();
338 *pDstData++ = c.GetBlue();
340 break;
341 case BitConvert::BGRA :
342 while( nX-- )
344 const BitmapColor& c = pSrcFormat->ReadPixel();
345 *pDstData++ = c.GetBlue();
346 *pDstData++ = c.GetGreen();
347 *pDstData++ = c.GetRed();
348 *pDstData++ = 0xff;
350 break;
351 case BitConvert::RGBA :
352 while( nX-- )
354 const BitmapColor& c = pSrcFormat->ReadPixel();
355 *pDstData++ = c.GetRed();
356 *pDstData++ = c.GetGreen();
357 *pDstData++ = c.GetBlue();
358 *pDstData++ = 0xff;
360 break;
363 pSrcData += bytesPerRow;
365 return data;
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */