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 #ifndef INCLUDED_VCL_SALBTYPE_HXX
21 #define INCLUDED_VCL_SALBTYPE_HXX
23 #include <tools/debug.hxx>
24 #include <vcl/checksum.hxx>
25 #include <vcl/salgtype.hxx>
26 #include <tools/color.hxx>
27 #include <tools/helpers.hxx>
28 #include <tools/solar.h>
29 #include <vcl/dllapi.h>
30 #include <o3tl/typed_flags_set.hxx>
33 typedef sal_uInt8
* Scanline
;
34 typedef const sal_uInt8
* ConstScanline
;
36 enum class ScanlineFormat
{
39 N1BitMsbPal
= 0x00000001,
40 N1BitLsbPal
= 0x00000002,
42 N4BitMsnPal
= 0x00000004,
43 N4BitLsnPal
= 0x00000008,
45 N8BitPal
= 0x00000010,
46 N8BitTcMask
= 0x00000020,
48 N16BitTcMsbMask
= 0x00000040,
49 N16BitTcLsbMask
= 0x00000080,
51 N24BitTcBgr
= 0x00000100,
52 N24BitTcRgb
= 0x00000200,
54 N32BitTcAbgr
= 0x00000800,
55 N32BitTcArgb
= 0x00001000,
56 N32BitTcBgra
= 0x00002000,
57 N32BitTcRgba
= 0x00004000,
58 N32BitTcMask
= 0x00008000,
60 TopDown
= 0x00010000 // scanline adjustment
63 template<> struct typed_flags
<ScanlineFormat
> : is_typed_flags
<ScanlineFormat
, 0x0001fbff> {};
65 inline ScanlineFormat
RemoveScanline(ScanlineFormat nFormat
) { return nFormat
& ~ScanlineFormat::TopDown
; }
68 #define MASK_TO_COLOR( d_nVal, d_RM, d_GM, d_BM, d_RS, d_GS, d_BS, d_Col ) \
69 const sal_uInt8 _def_cR = static_cast<sal_uInt8>( d_RS < 0 ? ( (d_nVal) & d_RM ) << -d_RS : ( (d_nVal) & d_RM ) >> d_RS ); \
70 const sal_uInt8 _def_cG = static_cast<sal_uInt8>( d_GS < 0 ? ( (d_nVal) & d_GM ) << -d_GS : ( (d_nVal) & d_GM ) >> d_GS ); \
71 const sal_uInt8 _def_cB = static_cast<sal_uInt8>( d_BS < 0 ? ( (d_nVal) & d_BM ) << -d_BS : ( (d_nVal) & d_BM ) >> d_BS ); \
72 d_Col = BitmapColor( (sal_uInt8) ( _def_cR | ( ( _def_cR & maR.mnOr ) >> maR.mnOrShift ) ), \
73 (sal_uInt8) ( _def_cG | ( ( _def_cG & maG.mnOr ) >> maG.mnOrShift ) ), \
74 (sal_uInt8) ( _def_cB | ( ( _def_cB & maB.mnOr ) >> maB.mnOrShift ) ) );
77 #define COLOR_TO_MASK( d_rCol, d_RM, d_GM, d_BM, d_RS, d_GS, d_BS, d_ALPHA ) \
78 ( ( ( ( d_RS < 0L ) ? ( (sal_uInt32) (d_rCol).GetRed() >> -d_RS ) : \
79 ( (sal_uInt32) (d_rCol).GetRed() << d_RS ) ) & d_RM ) | \
80 ( ( ( d_GS < 0L ) ? ( (sal_uInt32) (d_rCol).GetGreen() >> -d_GS ) : \
81 ( (sal_uInt32) (d_rCol).GetGreen() << d_GS ) ) & d_GM ) | \
82 ( ( ( d_BS < 0L ) ? ( (sal_uInt32) (d_rCol).GetBlue() >> -d_BS ) : \
83 ( (sal_uInt32) (d_rCol).GetBlue() << d_BS ) ) & d_BM ) | \
89 class VCL_DLLPUBLIC BitmapColor
93 sal_uInt8 mcBlueOrIndex
;
96 sal_uInt8 mbIndex
; // should be bool, but see above warning
100 inline BitmapColor();
101 inline BitmapColor( sal_uInt8 cRed
, sal_uInt8 cGreen
, sal_uInt8 cBlue
);
102 inline BitmapColor( const Color
& rColor
);
103 explicit inline BitmapColor( sal_uInt8 cIndex
);
105 inline bool operator==( const BitmapColor
& rBitmapColor
) const;
106 inline bool operator!=( const BitmapColor
& rBitmapColor
) const;
108 inline bool IsIndex() const;
110 inline sal_uInt8
GetRed() const;
111 inline void SetRed( sal_uInt8 cRed
);
113 inline sal_uInt8
GetGreen() const;
114 inline void SetGreen( sal_uInt8 cGreen
);
116 inline sal_uInt8
GetBlue() const;
117 inline void SetBlue( sal_uInt8 cBlue
);
119 inline sal_uInt8
GetIndex() const;
120 inline void SetIndex( sal_uInt8 cIndex
);
122 operator Color() const;
124 inline sal_uInt8
GetBlueOrIndex() const;
126 inline BitmapColor
& Invert();
128 inline sal_uInt8
GetLuminance() const;
130 inline BitmapColor
& Merge( const BitmapColor
& rColor
, sal_uInt8 cTransparency
);
132 inline sal_uInt16
GetColorError( const BitmapColor
& rBitmapColor
) const;
135 template<typename charT
, typename traits
>
136 inline std::basic_ostream
<charT
, traits
>& operator <<(std::basic_ostream
<charT
, traits
>& rStream
, const BitmapColor
& rColor
)
138 return rStream
<< "mcBlueOrIndex: " << (int)rColor
.GetBlueOrIndex() << ", mcGreen: "
139 << (int)rColor
.GetGreen() << ", mcRed: " << (int)rColor
.GetRed() << ", mbIndex: " << (int)rColor
.IsIndex();
144 class VCL_DLLPUBLIC BitmapPalette
146 friend class SalBitmap
;
147 friend class BitmapAccess
;
151 std::vector
<BitmapColor
> maBitmapColor
;
155 SAL_DLLPRIVATE
const BitmapColor
* ImplGetColorBuffer() const
157 return maBitmapColor
.data();
160 SAL_DLLPRIVATE BitmapColor
* ImplGetColorBuffer()
162 return maBitmapColor
.data();
165 BitmapChecksum
GetChecksum() const
167 return vcl_get_checksum(0, maBitmapColor
.data(), maBitmapColor
.size() * sizeof(BitmapColor
));
176 BitmapPalette(sal_uInt16 nCount
)
177 : maBitmapColor(nCount
)
181 bool operator==( const BitmapPalette
& rBitmapPalette
) const
183 return maBitmapColor
== rBitmapPalette
.maBitmapColor
;
186 bool operator!=(const BitmapPalette
& rBitmapPalette
) const
188 return !( *this == rBitmapPalette
);
193 return maBitmapColor
.empty();
196 sal_uInt16
GetEntryCount() const
198 return maBitmapColor
.size();
201 void SetEntryCount(sal_uInt16 nCount
)
203 maBitmapColor
.resize(nCount
);
206 const BitmapColor
& operator[](sal_uInt16 nIndex
) const
208 assert(nIndex
< maBitmapColor
.size() && "Palette index is out of range");
209 return maBitmapColor
[nIndex
];
212 BitmapColor
& operator[](sal_uInt16 nIndex
)
214 assert(nIndex
< maBitmapColor
.size() && "Palette index is out of range");
215 return maBitmapColor
[nIndex
];
218 sal_uInt16
GetBestIndex(const BitmapColor
& rCol
) const
220 sal_uInt16 nRetIndex
= 0;
222 if (!maBitmapColor
.empty())
224 for (size_t j
= 0; j
< maBitmapColor
.size(); ++j
)
226 if (rCol
== maBitmapColor
[j
])
232 sal_uInt16 nLastErr
= SAL_MAX_UINT16
;
233 for (size_t i
= 0; i
< maBitmapColor
.size(); ++i
)
235 const sal_uInt16 nActErr
= rCol
.GetColorError(maBitmapColor
[i
]);
236 if ( nActErr
< nLastErr
)
247 bool IsGreyPalette() const;
250 struct VCL_DLLPUBLIC ColorMaskElement
256 explicit ColorMaskElement(sal_uInt32 nMask
= 0)
268 // from which bit starts the mask?
271 while( nShift
>= 0 && !( mnMask
& ( 1 << nShift
) ) )
274 mnShift
= nShift
- 7;
277 // XXX determine number of bits set => walk right until null
278 while( nShift
>= 0 && ( mnMask
& ( 1 << nShift
) ) )
284 if (nLen
> 8) // mask length must be 8 bits or less
287 mnOrShift
= 8 - nLen
;
288 mnOr
= static_cast<sal_uInt8
>( ( 0xFF >> nLen
) << mnOrShift
);
294 class VCL_DLLPUBLIC ColorMask
296 ColorMaskElement maR
;
297 ColorMaskElement maG
;
298 ColorMaskElement maB
;
302 ColorMask(const ColorMaskElement
& rRedMask
= ColorMaskElement(),
303 const ColorMaskElement
& rGreenMask
= ColorMaskElement(),
304 const ColorMaskElement
& rBlueMask
= ColorMaskElement())
311 inline sal_uInt32
GetRedMask() const;
312 inline sal_uInt32
GetGreenMask() const;
313 inline sal_uInt32
GetBlueMask() const;
315 inline void GetColorFor8Bit( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const;
316 inline void SetColorFor8Bit( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const;
318 inline void GetColorFor16BitMSB( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const;
319 inline void SetColorFor16BitMSB( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const;
320 inline void GetColorFor16BitLSB( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const;
321 inline void SetColorFor16BitLSB( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const;
323 inline void GetColorFor32Bit( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const;
324 inline void GetColorAndAlphaFor32Bit( BitmapColor
& rColor
, sal_uInt8
& rAlpha
, const sal_uInt8
* pPixel
) const;
325 inline void SetColorFor32Bit( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const;
328 struct VCL_DLLPUBLIC BitmapBuffer
330 ScanlineFormat mnFormat
;
334 sal_uInt16 mnBitCount
;
335 ColorMask maColorMask
;
336 BitmapPalette maPalette
;
340 enum class BitmapAccessMode
347 VCL_DLLPUBLIC BitmapBuffer
* StretchAndConvert(
348 const BitmapBuffer
& rSrcBuffer
, const SalTwoRect
& rTwoRect
,
349 ScanlineFormat nDstBitmapFormat
, const BitmapPalette
* pDstPal
= nullptr, const ColorMask
* pDstMask
= nullptr );
351 inline BitmapColor::BitmapColor() :
355 mbIndex ( sal_uInt8(false) )
359 inline BitmapColor::BitmapColor( sal_uInt8 cRed
, sal_uInt8 cGreen
, sal_uInt8 cBlue
) :
360 mcBlueOrIndex ( cBlue
),
363 mbIndex ( sal_uInt8(false) )
367 inline BitmapColor::BitmapColor( const Color
& rColor
) :
368 mcBlueOrIndex ( rColor
.GetBlue() ),
369 mcGreen ( rColor
.GetGreen() ),
370 mcRed ( rColor
.GetRed() ),
371 mbIndex ( sal_uInt8(false) )
375 inline BitmapColor::BitmapColor( sal_uInt8 cIndex
) :
376 mcBlueOrIndex ( cIndex
),
379 mbIndex ( sal_uInt8(true) )
383 inline bool BitmapColor::operator==( const BitmapColor
& rBitmapColor
) const
385 return( ( mcBlueOrIndex
== rBitmapColor
.mcBlueOrIndex
) &&
386 ( mbIndex
? bool(rBitmapColor
.mbIndex
) :
387 ( mcGreen
== rBitmapColor
.mcGreen
&& mcRed
== rBitmapColor
.mcRed
) ) );
390 inline bool BitmapColor::operator!=( const BitmapColor
& rBitmapColor
) const
392 return !( *this == rBitmapColor
);
395 inline bool BitmapColor::IsIndex() const
400 inline sal_uInt8
BitmapColor::GetRed() const
402 assert( !mbIndex
&& "Pixel represents index into colortable" );
406 inline void BitmapColor::SetRed( sal_uInt8 cRed
)
408 assert( !mbIndex
&& "Pixel represents index into colortable" );
412 inline sal_uInt8
BitmapColor::GetGreen() const
414 assert( !mbIndex
&& "Pixel represents index into colortable" );
418 inline void BitmapColor::SetGreen( sal_uInt8 cGreen
)
420 assert( !mbIndex
&& "Pixel represents index into colortable" );
424 inline sal_uInt8
BitmapColor::GetBlue() const
426 assert( !mbIndex
&& "Pixel represents index into colortable" );
427 return mcBlueOrIndex
;
430 inline void BitmapColor::SetBlue( sal_uInt8 cBlue
)
432 assert( !mbIndex
&& "Pixel represents index into colortable" );
433 mcBlueOrIndex
= cBlue
;
436 inline sal_uInt8
BitmapColor::GetIndex() const
438 assert( mbIndex
&& "Pixel represents color values" );
439 return mcBlueOrIndex
;
442 inline void BitmapColor::SetIndex( sal_uInt8 cIndex
)
444 assert( mbIndex
&& "Pixel represents color values" );
445 mcBlueOrIndex
= cIndex
;
448 inline BitmapColor::operator Color() const
450 assert( !mbIndex
&& "Pixel represents index into colortable" );
451 return Color( mcRed
, mcGreen
, mcBlueOrIndex
);
454 inline sal_uInt8
BitmapColor::GetBlueOrIndex() const
456 // #i47518# Yield a value regardless of mbIndex
457 return mcBlueOrIndex
;
460 inline BitmapColor
& BitmapColor::Invert()
462 assert( !mbIndex
&& "Pixel represents index into colortable" );
463 mcBlueOrIndex
= ~mcBlueOrIndex
;
470 inline sal_uInt8
BitmapColor::GetLuminance() const
472 assert( !mbIndex
&& "Pixel represents index into colortable" );
473 return (static_cast<unsigned long>(mcBlueOrIndex
) * 28UL + static_cast<unsigned long>(mcGreen
) * 151UL + static_cast<unsigned long>(mcRed
) * 77UL) >> 8;
477 inline BitmapColor
& BitmapColor::Merge( const BitmapColor
& rBitmapColor
, sal_uInt8 cTransparency
)
479 assert( !mbIndex
&& "Pixel represents index into colortable" );
480 assert( !rBitmapColor
.mbIndex
&& "Pixel represents index into colortable" );
481 mcBlueOrIndex
= COLOR_CHANNEL_MERGE( mcBlueOrIndex
, rBitmapColor
.mcBlueOrIndex
, cTransparency
);
482 mcGreen
= COLOR_CHANNEL_MERGE( mcGreen
, rBitmapColor
.mcGreen
, cTransparency
);
483 mcRed
= COLOR_CHANNEL_MERGE( mcRed
, rBitmapColor
.mcRed
, cTransparency
);
489 inline sal_uInt16
BitmapColor::GetColorError( const BitmapColor
& rBitmapColor
) const
491 assert( !mbIndex
&& "Pixel represents index into colortable" );
492 assert( !rBitmapColor
.mbIndex
&& "Pixel represents index into colortable" );
493 return static_cast<sal_uInt16
>(
494 abs( static_cast<int>(mcBlueOrIndex
) - static_cast<int>(rBitmapColor
.mcBlueOrIndex
) ) +
495 abs( static_cast<int>(mcGreen
) - static_cast<int>(rBitmapColor
.mcGreen
) ) +
496 abs( static_cast<int>(mcRed
) - static_cast<int>(rBitmapColor
.mcRed
) ) );
499 inline sal_uInt32
ColorMask::GetRedMask() const
504 inline sal_uInt32
ColorMask::GetGreenMask() const
509 inline sal_uInt32
ColorMask::GetBlueMask() const
514 inline void ColorMask::GetColorFor8Bit( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const
516 const sal_uInt32 nVal
= *pPixel
;
517 MASK_TO_COLOR( nVal
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maR
.mnShift
, rColor
);
520 inline void ColorMask::SetColorFor8Bit( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const
522 *pPixel
= (sal_uInt8
) COLOR_TO_MASK( rColor
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, 0/*nAlphaChannel*/ );
525 inline void ColorMask::GetColorFor16BitMSB( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const
527 const sal_uInt32 nVal
= pPixel
[ 1 ] | ( (sal_uInt32
) pPixel
[ 0 ] << 8UL );
529 MASK_TO_COLOR( nVal
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, rColor
);
532 inline void ColorMask::SetColorFor16BitMSB( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const
534 const sal_uInt16 nVal
= (sal_uInt16
)COLOR_TO_MASK( rColor
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, 0/*nAlphaChannel*/ );
536 pPixel
[ 0 ] = (sal_uInt8
)(nVal
>> 8U);
537 pPixel
[ 1 ] = (sal_uInt8
) nVal
;
540 inline void ColorMask::GetColorFor16BitLSB( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const
542 const sal_uInt32 nVal
= pPixel
[ 0 ] | ( (sal_uInt32
) pPixel
[ 1 ] << 8UL );
544 MASK_TO_COLOR( nVal
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, rColor
);
547 inline void ColorMask::SetColorFor16BitLSB( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const
549 const sal_uInt16 nVal
= (sal_uInt16
)COLOR_TO_MASK( rColor
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, 0/*nAlphaChannel*/ );
551 pPixel
[ 0 ] = (sal_uInt8
) nVal
;
552 pPixel
[ 1 ] = (sal_uInt8
)(nVal
>> 8U);
555 inline void ColorMask::GetColorFor32Bit( BitmapColor
& rColor
, const sal_uInt8
* pPixel
) const
557 const sal_uInt32 nVal
= (sal_uInt32
) pPixel
[ 0 ] | ( (sal_uInt32
) pPixel
[ 1 ] << 8UL ) |
558 ( (sal_uInt32
) pPixel
[ 2 ] << 16UL ) | ( (sal_uInt32
) pPixel
[ 3 ] << 24UL );
560 MASK_TO_COLOR( nVal
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, rColor
);
563 inline void ColorMask::GetColorAndAlphaFor32Bit( BitmapColor
& rColor
, sal_uInt8
& rAlpha
, const sal_uInt8
* pPixel
) const
565 const sal_uInt32 nVal
= (sal_uInt32
) pPixel
[ 0 ] | ( (sal_uInt32
) pPixel
[ 1 ] << 8UL ) |
566 ( (sal_uInt32
) pPixel
[ 2 ] << 16UL ) | ( (sal_uInt32
) pPixel
[ 3 ] << 24UL );
567 rAlpha
= (sal_uInt8
)(nVal
>> 24);
569 MASK_TO_COLOR( nVal
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, rColor
);
572 inline void ColorMask::SetColorFor32Bit( const BitmapColor
& rColor
, sal_uInt8
* pPixel
) const
574 const sal_uInt32 nVal
= COLOR_TO_MASK( rColor
, maR
.mnMask
, maG
.mnMask
, maB
.mnMask
, maR
.mnShift
, maG
.mnShift
, maB
.mnShift
, 0/*nAlphaChannel*/ );
575 pPixel
[ 0 ] = (sal_uInt8
) nVal
;
576 pPixel
[ 1 ] = (sal_uInt8
) ( nVal
>> 8UL );
577 pPixel
[ 2 ] = (sal_uInt8
) ( nVal
>> 16UL );
578 pPixel
[ 3 ] = (sal_uInt8
) ( nVal
>> 24UL );
581 #endif // INCLUDED_VCL_SALBTYPE_HXX
583 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */