diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-08-19 20:36:03 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-08-20 11:28:26 +0200 |
commit | 02c9c9adf65883ecaeef0e86a4b0b70ee3d5cf52 (patch) | |
tree | 367be04bd1b33cdc64c93a1ae00fe99b79f95f6e | |
parent | 4bb59cd1f45133994d3d13642367470f528094f4 (diff) |
make BitmapPalette a COW type
so we can avoid copying it during rendering
Change-Id: Id83d2bb2682f46188ee6ccc90c92d338a1e05b98
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120759
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r-- | include/vcl/BitmapBuffer.hxx | 3 | ||||
-rw-r--r-- | include/vcl/BitmapPalette.hxx | 118 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/source/bitmap/bitmap.cxx | 40 | ||||
-rw-r--r-- | vcl/source/bitmap/bitmappalette.cxx | 215 | ||||
-rw-r--r-- | vcl/source/gdi/salmisc.cxx | 2 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salbmp.cxx | 19 | ||||
-rw-r--r-- | vcl/win/gdi/salbmp.cxx | 2 |
8 files changed, 256 insertions, 144 deletions
diff --git a/include/vcl/BitmapBuffer.hxx b/include/vcl/BitmapBuffer.hxx index 7468cb987f95..d67e42ac6cad 100644 --- a/include/vcl/BitmapBuffer.hxx +++ b/include/vcl/BitmapBuffer.hxx @@ -23,6 +23,7 @@ #include <sal/config.h> #include <memory> +#include <optional> #include <vcl/dllapi.h> #include <vcl/BitmapPalette.hxx> @@ -46,7 +47,7 @@ struct VCL_DLLPUBLIC BitmapBuffer VCL_DLLPUBLIC std::unique_ptr<BitmapBuffer> StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect, - ScanlineFormat nDstBitmapFormat, const BitmapPalette* pDstPal = nullptr, const ColorMask* pDstMask = nullptr ); + ScanlineFormat nDstBitmapFormat, std::optional<BitmapPalette> pDstPal = std::nullopt, const ColorMask* pDstMask = nullptr ); #endif // INCLUDED_VCL_BITMAPBUFFER_HXX diff --git a/include/vcl/BitmapPalette.hxx b/include/vcl/BitmapPalette.hxx index 046bd6c20f0a..53de5276b282 100644 --- a/include/vcl/BitmapPalette.hxx +++ b/include/vcl/BitmapPalette.hxx @@ -17,127 +17,63 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_VCL_BITMAPPALETTE_HXX -#define INCLUDED_VCL_BITMAPPALETTE_HXX +#pragma once #include <vcl/dllapi.h> #include <vcl/BitmapColor.hxx> #include <vcl/checksum.hxx> #include <vector> +#include <o3tl/cow_wrapper.hxx> + +class ImplBitmapPalette; class VCL_DLLPUBLIC BitmapPalette { friend class SalBitmap; friend class BitmapAccess; -private: - - std::vector<BitmapColor> maBitmapColor; - public: - SAL_DLLPRIVATE const BitmapColor* ImplGetColorBuffer() const - { - return maBitmapColor.data(); - } + SAL_DLLPRIVATE const BitmapColor* ImplGetColorBuffer() const; - SAL_DLLPRIVATE BitmapColor* ImplGetColorBuffer() - { - return maBitmapColor.data(); - } + SAL_DLLPRIVATE BitmapColor* ImplGetColorBuffer(); - BitmapChecksum GetChecksum() const - { - return vcl_get_checksum(0, maBitmapColor.data(), maBitmapColor.size() * sizeof(BitmapColor)); - } + BitmapChecksum GetChecksum() const; -public: + BitmapPalette(); + BitmapPalette( const BitmapPalette& ); + BitmapPalette( BitmapPalette&& ) noexcept; + BitmapPalette(std::initializer_list<BitmapColor> aBitmapColor); + explicit BitmapPalette(sal_uInt16 nCount); + ~BitmapPalette(); - BitmapPalette() - { - } - - BitmapPalette(std::initializer_list<BitmapColor> aBitmapColor) : maBitmapColor(aBitmapColor) - { - } - - BitmapPalette(sal_uInt16 nCount) - : maBitmapColor(nCount) - { - } - - bool operator==( const BitmapPalette& rBitmapPalette ) const - { - return maBitmapColor == rBitmapPalette.maBitmapColor; - } + BitmapPalette& operator=( const BitmapPalette& ); + BitmapPalette& operator=( BitmapPalette&& ) noexcept; + bool operator==( const BitmapPalette& rBitmapPalette ) const; bool operator!=(const BitmapPalette& rBitmapPalette) const { return !( *this == rBitmapPalette ); } + bool operator!() const; - bool operator!() const - { - return maBitmapColor.empty(); - } - - sal_uInt16 GetEntryCount() const - { - return maBitmapColor.size(); - } - - void SetEntryCount(sal_uInt16 nCount) - { - maBitmapColor.resize(nCount); - } - - const BitmapColor& operator[](sal_uInt16 nIndex) const - { - assert(nIndex < maBitmapColor.size() && "Palette index is out of range"); - return maBitmapColor[nIndex]; - } + sal_uInt16 GetEntryCount() const; + void SetEntryCount(sal_uInt16 nCount); - BitmapColor& operator[](sal_uInt16 nIndex) - { - assert(nIndex < maBitmapColor.size() && "Palette index is out of range"); - return maBitmapColor[nIndex]; - } + const BitmapColor& operator[](sal_uInt16 nIndex) const; + BitmapColor& operator[](sal_uInt16 nIndex); - sal_uInt16 GetBestIndex(const BitmapColor& rCol) const - { - sal_uInt16 nRetIndex = 0; - - if (!maBitmapColor.empty()) - { - for (size_t j = 0; j < maBitmapColor.size(); ++j) - { - if (rCol == maBitmapColor[j]) - { - return j; - } - } - - sal_uInt16 nLastErr = SAL_MAX_UINT16; - for (size_t i = 0; i < maBitmapColor.size(); ++i) - { - const sal_uInt16 nActErr = rCol.GetColorError(maBitmapColor[i]); - if ( nActErr < nLastErr ) - { - nLastErr = nActErr; - nRetIndex = i; - } - } - } - - return nRetIndex; - } + sal_uInt16 GetBestIndex(const BitmapColor& rCol) const; /// Returns true if the palette is 8-bit grey palette. bool IsGreyPalette8Bit() const; /// Returns true if the palette is a grey palette (may not be 8-bit). bool IsGreyPaletteAny() const; -}; -#endif // INCLUDED_VCL_BITMAPPALETTE_HXX + typedef o3tl::cow_wrapper< ImplBitmapPalette > ImplType; + +private: + ImplType mpImpl; +}; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index c7a0e5c48986..eb0af8aa8cc4 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -320,6 +320,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/graphic/VectorGraphicLoader \ vcl/source/bitmap/impvect \ vcl/source/bitmap/bitmap \ + vcl/source/bitmap/bitmappalette \ vcl/source/bitmap/BitmapEx \ vcl/source/bitmap/BitmapInfoAccess \ vcl/source/bitmap/BitmapReadAccess \ diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx index e688296aa606..07f2c7bf8219 100644 --- a/vcl/source/bitmap/bitmap.cxx +++ b/vcl/source/bitmap/bitmap.cxx @@ -229,46 +229,6 @@ const BitmapPalette& Bitmap::GetGreyPalette( int nEntries ) return GetGreyPalette(2); } -bool BitmapPalette::IsGreyPaletteAny() const -{ - const int nEntryCount = GetEntryCount(); - if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping - return true; - // See above: only certain entry values will result in a valid call to GetGreyPalette - if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 ) - { - const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount ); - if( rGreyPalette == *this ) - return true; - } - - bool bRet = false; - // TODO: is it worth to compare the entries for the general case? - if (nEntryCount == 2) - { - const BitmapColor& rCol0(maBitmapColor[0]); - const BitmapColor& rCol1(maBitmapColor[1]); - bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() && - rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue(); - } - return bRet; -} - -bool BitmapPalette::IsGreyPalette8Bit() const -{ - const int nEntryCount = GetEntryCount(); - if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping - return true; - if( nEntryCount != 256 ) - return false; - for (sal_uInt16 i = 0; i < 256; ++i) - { - if( maBitmapColor[i] != BitmapColor(i, i, i)) - return false; - } - return true; -} - Bitmap& Bitmap::operator=( const Bitmap& rBitmap ) { if (this == &rBitmap) diff --git a/vcl/source/bitmap/bitmappalette.cxx b/vcl/source/bitmap/bitmappalette.cxx new file mode 100644 index 000000000000..e782e34ba1a8 --- /dev/null +++ b/vcl/source/bitmap/bitmappalette.cxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <tools/helpers.hxx> + +#include <vcl/BitmapPalette.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/outdev.hxx> + +#include <svdata.hxx> +#include <salinst.hxx> + +class ImplBitmapPalette +{ +public: + ImplBitmapPalette(std::initializer_list<BitmapColor> aBitmapColor) + : maBitmapColor(aBitmapColor) + { + } + ImplBitmapPalette() {} + ImplBitmapPalette(sal_uInt16 nCount) + : maBitmapColor(nCount) + { + } + std::vector<BitmapColor>& GetBitmapData() { return maBitmapColor; } + const std::vector<BitmapColor>& GetBitmapData() const { return maBitmapColor; } + bool operator==(const ImplBitmapPalette& rBitmapPalette) const + { + return maBitmapColor == rBitmapPalette.maBitmapColor; + } + +private: + std::vector<BitmapColor> maBitmapColor; +}; + +namespace +{ +BitmapPalette::ImplType& GetGlobalDefault() +{ + static BitmapPalette::ImplType gDefault; + return gDefault; +} +} + +BitmapPalette::BitmapPalette() + : mpImpl(GetGlobalDefault()) +{ +} + +BitmapPalette::BitmapPalette(const BitmapPalette& rOther) + : mpImpl(rOther.mpImpl) +{ +} + +BitmapPalette::BitmapPalette(BitmapPalette&& rOther) noexcept + : mpImpl(std::move(rOther.mpImpl)) +{ +} + +BitmapPalette::BitmapPalette(std::initializer_list<BitmapColor> aBitmapColor) + : mpImpl(aBitmapColor) +{ +} + +BitmapPalette::BitmapPalette(sal_uInt16 nCount) + : mpImpl(nCount) +{ +} + +BitmapPalette::~BitmapPalette() {} + +BitmapPalette& BitmapPalette::operator=(const BitmapPalette& rOther) +{ + mpImpl = rOther.mpImpl; + return *this; +} + +BitmapPalette& BitmapPalette::operator=(BitmapPalette&& rOther) noexcept +{ + mpImpl = std::move(rOther.mpImpl); + return *this; +} + +SAL_DLLPRIVATE const BitmapColor* BitmapPalette::ImplGetColorBuffer() const +{ + return mpImpl->GetBitmapData().data(); +} + +SAL_DLLPRIVATE BitmapColor* BitmapPalette::ImplGetColorBuffer() +{ + return mpImpl->GetBitmapData().data(); +} + +BitmapChecksum BitmapPalette::GetChecksum() const +{ + auto const& rBitmapData = mpImpl->GetBitmapData(); + return vcl_get_checksum(0, rBitmapData.data(), rBitmapData.size() * sizeof(BitmapColor)); +} + +bool BitmapPalette::operator==(const BitmapPalette& rOther) const +{ + return mpImpl == rOther.mpImpl; +} + +bool BitmapPalette::operator!() const { return mpImpl->GetBitmapData().empty(); } + +sal_uInt16 BitmapPalette::GetEntryCount() const { return mpImpl->GetBitmapData().size(); } + +void BitmapPalette::SetEntryCount(sal_uInt16 nCount) { mpImpl->GetBitmapData().resize(nCount); } + +const BitmapColor& BitmapPalette::operator[](sal_uInt16 nIndex) const +{ + assert(nIndex < mpImpl->GetBitmapData().size() && "Palette index is out of range"); + return mpImpl->GetBitmapData()[nIndex]; +} + +BitmapColor& BitmapPalette::operator[](sal_uInt16 nIndex) +{ + assert(nIndex < mpImpl->GetBitmapData().size() && "Palette index is out of range"); + return mpImpl->GetBitmapData()[nIndex]; +} + +sal_uInt16 BitmapPalette::GetBestIndex(const BitmapColor& rCol) const +{ + auto const& rBitmapColor = mpImpl->GetBitmapData(); + sal_uInt16 nRetIndex = 0; + + if (!rBitmapColor.empty()) + { + for (size_t j = 0; j < rBitmapColor.size(); ++j) + { + if (rCol == rBitmapColor[j]) + { + return j; + } + } + + sal_uInt16 nLastErr = SAL_MAX_UINT16; + for (size_t i = 0; i < rBitmapColor.size(); ++i) + { + const sal_uInt16 nActErr = rCol.GetColorError(rBitmapColor[i]); + if (nActErr < nLastErr) + { + nLastErr = nActErr; + nRetIndex = i; + } + } + } + + return nRetIndex; +} + +bool BitmapPalette::IsGreyPaletteAny() const +{ + auto const& rBitmapColor = mpImpl->GetBitmapData(); + const int nEntryCount = GetEntryCount(); + if (!nEntryCount) // NOTE: an empty palette means 1:1 mapping + return true; + // See above: only certain entry values will result in a valid call to GetGreyPalette + if (nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256) + { + const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette(nEntryCount); + if (rGreyPalette == *this) + return true; + } + + bool bRet = false; + // TODO: is it worth to compare the entries for the general case? + if (nEntryCount == 2) + { + const BitmapColor& rCol0(rBitmapColor[0]); + const BitmapColor& rCol1(rBitmapColor[1]); + bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() + && rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue(); + } + return bRet; +} + +bool BitmapPalette::IsGreyPalette8Bit() const +{ + auto const& rBitmapColor = mpImpl->GetBitmapData(); + const int nEntryCount = GetEntryCount(); + if (!nEntryCount) // NOTE: an empty palette means 1:1 mapping + return true; + if (nEntryCount != 256) + return false; + for (sal_uInt16 i = 0; i < 256; ++i) + { + if (rBitmapColor[i] != BitmapColor(i, i, i)) + return false; + } + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/salmisc.cxx b/vcl/source/gdi/salmisc.cxx index 037ea8073bae..17161420dc4a 100644 --- a/vcl/source/gdi/salmisc.cxx +++ b/vcl/source/gdi/salmisc.cxx @@ -228,7 +228,7 @@ static void ImplTCToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer const & rD std::unique_ptr<BitmapBuffer> StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect, - ScanlineFormat nDstBitmapFormat, const BitmapPalette* pDstPal, const ColorMask* pDstMask ) + ScanlineFormat nDstBitmapFormat, std::optional<BitmapPalette> pDstPal, const ColorMask* pDstMask ) { FncGetPixel pFncGetPixel; FncSetPixel pFncSetPixel; diff --git a/vcl/unx/generic/gdi/salbmp.cxx b/vcl/unx/generic/gdi/salbmp.cxx index c73b40146eee..e3803a518d60 100644 --- a/vcl/unx/generic/gdi/salbmp.cxx +++ b/vcl/unx/generic/gdi/salbmp.cxx @@ -230,7 +230,7 @@ std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB( { const SalTwoRect aTwoRect = { 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight }; BitmapBuffer aSrcBuf; - const BitmapPalette* pDstPal = nullptr; + std::optional<BitmapPalette> pDstPal; aSrcBuf.mnFormat = ScanlineFormat::TopDown; aSrcBuf.mnWidth = nWidth; @@ -292,15 +292,13 @@ std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB( if( aSrcBuf.mnBitCount == 1 ) { rPal.SetEntryCount( 2 ); - pDstPal = &rPal; - rPal[ 0 ] = COL_BLACK; rPal[ 1 ] = COL_WHITE; + pDstPal = rPal; } else if( pImage->depth == 8 && bGrey ) { rPal.SetEntryCount( 256 ); - pDstPal = &rPal; for( sal_uInt16 i = 0; i < 256; i++ ) { @@ -311,6 +309,7 @@ std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB( rBmpCol.SetBlue( i ); } + pDstPal = rPal; } else if( aSrcBuf.mnBitCount <= 8 ) { @@ -319,7 +318,6 @@ std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB( sal_uLong(1) << nDrawableDepth); rPal.SetEntryCount( nCols ); - pDstPal = &rPal; for( sal_uInt16 i = 0; i < nCols; i++ ) { @@ -330,6 +328,7 @@ std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB( rBmpCol.SetGreen( nColor.GetGreen() ); rBmpCol.SetBlue( nColor.GetBlue() ); } + pDstPal = rPal; } pDIB = StretchAndConvert( aSrcBuf, aTwoRect, aSrcBuf.mnFormat, @@ -379,7 +378,7 @@ XImage* X11SalBitmap::ImplCreateXImage( { std::unique_ptr<BitmapBuffer> pDstBuf; ScanlineFormat nDstFormat = ScanlineFormat::TopDown; - std::unique_ptr<BitmapPalette> xPal; + std::optional<BitmapPalette> xPal; std::unique_ptr<ColorMask> xMask; switch( pImage->bits_per_pixel ) @@ -424,13 +423,13 @@ XImage* X11SalBitmap::ImplCreateXImage( if( pImage->depth == 1 ) { - xPal.reset(new BitmapPalette( 2 )); + xPal.emplace(2); (*xPal)[ 0 ] = COL_BLACK; (*xPal)[ 1 ] = COL_WHITE; } else if( pImage->depth == 8 && mbGrey ) { - xPal.reset(new BitmapPalette( 256 )); + xPal.emplace(256); for( sal_uInt16 i = 0; i < 256; i++ ) { @@ -449,7 +448,7 @@ XImage* X11SalBitmap::ImplCreateXImage( , static_cast<sal_uLong>(1 << pImage->depth) ); - xPal.reset(new BitmapPalette( nCols )); + xPal.emplace(nCols); for( sal_uInt16 i = 0; i < nCols; i++ ) { @@ -462,7 +461,7 @@ XImage* X11SalBitmap::ImplCreateXImage( } } - pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, xPal.get(), xMask.get() ); + pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, xPal, xMask.get() ); xPal.reset(); xMask.reset(); diff --git a/vcl/win/gdi/salbmp.cxx b/vcl/win/gdi/salbmp.cxx index 4602565ece51..3538b503f08d 100644 --- a/vcl/win/gdi/salbmp.cxx +++ b/vcl/win/gdi/salbmp.cxx @@ -353,7 +353,7 @@ std::shared_ptr<Gdiplus::Bitmap> WinSalBitmap::ImplCreateGdiPlusBitmap(const Win *pA, aSalTwoRect, ScanlineFormat::N8BitPal, - &rTargetPalette); + rTargetPalette); pSalA->ReleaseBuffer(pA, BitmapAccessMode::Read); pA = pExtraA.get(); |