include/vcl/bitmap.hxx | 39 +++++++++++++++++++++++ include/vcl/bitmapex.hxx | 40 ------------------------ svtools/source/control/valueset.cxx | 4 +- vcl/inc/bitmap/BlendFrameCache.hxx | 4 +- vcl/source/app/svmain.cxx | 2 - vcl/source/bitmap/BitmapEx.cxx | 56 ---------------------------------- vcl/source/bitmap/BlendFrameCache.cxx | 44 ++++++++++++-------------- vcl/source/bitmap/bitmap.cxx | 56 ++++++++++++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 124 deletions(-)
New commits: commit 93907ff360ec3a26b1a9415210703bc9856cde32 Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Thu Aug 28 13:36:21 2025 +0200 Commit: Noel Grandin <noelgran...@gmail.com> CommitDate: Thu Aug 28 16:04:47 2025 +0200 BitmapEx->Bitmap in createAlphaBlendFrame now that Bitmap can handle transparency Change-Id: I443463f9fdfec6637349eaa3d515a519f9a73ac9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190326 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index d6ef3bbe5058..5fd2e04b1e44 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -714,6 +714,45 @@ inline sal_Int64 Bitmap::GetSizeBytes() const return aSizeInBytes; } +/** Create a blend frame as Bitmap using an alpha value + + @param nAlpha + The blend value defines how strong the frame will be blended with the + existing content, 255 == full coverage, 0 == no frame will be drawn + + @param aColorTopLeft, aColorBottomRight + The colors defining the frame. These colors are linearly interpolated from + aColorTopLeft and aColorBottomRight using the width and height of the area + + @param rSize + The size of the frame in pixels + */ +Bitmap VCL_DLLPUBLIC createAlphaBlendFrame( + const Size& rSize, + sal_uInt8 nAlpha, + const Color& rColorTopLeft, + const Color& rColorBottomRight); + +/** Create a blend frame as Bitmap using an alpha value + + @param nAlpha + The blend value defines how strong the frame will be blended with the + existing content, 255 == full coverage, 0 == no frame will be drawn + + @param aColorTopLeft, aColorBottomRight, aColorTopRight, aColorBottomLeft + The colors defining the frame. + + @param rSize + The size of the frame in pixels + */ +Bitmap createAlphaBlendFrame( + const Size& rSize, + sal_uInt8 nAlpha, + const Color& rColorTopLeft, + const Color& rColorTopRight, + const Color& rColorBottomRight, + const Color& rColorBottomLeft); + #endif // INCLUDED_VCL_BITMAP_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/bitmapex.hxx b/include/vcl/bitmapex.hxx index cf3055d2d607..35bb0248313a 100644 --- a/include/vcl/bitmapex.hxx +++ b/include/vcl/bitmapex.hxx @@ -464,46 +464,6 @@ private: Size maBitmapSize; }; - -/** Create a blend frame as BitmapEx using an alpha value - - @param nAlpha - The blend value defines how strong the frame will be blended with the - existing content, 255 == full coverage, 0 == no frame will be drawn - - @param aColorTopLeft, aColorBottomRight - The colors defining the frame. These colors are linearly interpolated from - aColorTopLeft and aColorBottomRight using the width and height of the area - - @param rSize - The size of the frame in pixels - */ -BitmapEx VCL_DLLPUBLIC createAlphaBlendFrame( - const Size& rSize, - sal_uInt8 nAlpha, - const Color& rColorTopLeft, - const Color& rColorBottomRight); - -/** Create a blend frame as BitmapEx using an alpha value - - @param nAlpha - The blend value defines how strong the frame will be blended with the - existing content, 255 == full coverage, 0 == no frame will be drawn - - @param aColorTopLeft, aColorBottomRight, aColorTopRight, aColorBottomLeft - The colors defining the frame. - - @param rSize - The size of the frame in pixels - */ -BitmapEx createAlphaBlendFrame( - const Size& rSize, - sal_uInt8 nAlpha, - const Color& rColorTopLeft, - const Color& rColorTopRight, - const Color& rColorBottomRight, - const Color& rColorBottomLeft); - #endif // INCLUDED_VCL_BITMAPEX_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx index 7e9604b75169..99240f5d4bee 100644 --- a/svtools/source/control/valueset.cxx +++ b/svtools/source/control/valueset.cxx @@ -23,7 +23,7 @@ #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <tools/debug.hxx> -#include <vcl/bitmapex.hxx> +#include <vcl/bitmap.hxx> #include <vcl/canvastools.hxx> #include <vcl/decoview.hxx> #include <vcl/event.hxx> @@ -1500,7 +1500,7 @@ void ValueSet::ImplFormatItem(vcl::RenderContext const & rRenderContext, ValueSe const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); const sal_uInt8 nAlpha(255 - ((nEdgeBlendingPercent * 255) / 100)); - const BitmapEx aBlendFrame(createAlphaBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight)); + const Bitmap aBlendFrame(createAlphaBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight)); if (!aBlendFrame.IsEmpty()) { diff --git a/vcl/inc/bitmap/BlendFrameCache.hxx b/vcl/inc/bitmap/BlendFrameCache.hxx index 61d4ff6de6aa..5c03ff94b819 100644 --- a/vcl/inc/bitmap/BlendFrameCache.hxx +++ b/vcl/inc/bitmap/BlendFrameCache.hxx @@ -20,7 +20,7 @@ #include <tools/color.hxx> #include <tools/gen.hxx> -#include <vcl/bitmapex.hxx> +#include <vcl/bitmap.hxx> struct BlendFrameCache { @@ -30,7 +30,7 @@ struct BlendFrameCache Color m_aLastColorTopRight; Color m_aLastColorBottomRight; Color m_aLastColorBottomLeft; - BitmapEx m_aLastResult; + Bitmap m_aLastResult; BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color const& rColorTopLeft, Color const& rColorTopRight, Color const& rColorBottomRight, diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index 56c30312f3e3..58eec341a555 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -427,7 +427,7 @@ void DeInitVCL() // lp#1560328: clear cache before disposing rest of VCL if(pSVData->mpBlendFrameCache) - pSVData->mpBlendFrameCache->m_aLastResult.Clear(); + pSVData->mpBlendFrameCache->m_aLastResult = Bitmap(); pSVData->mbDeInit = true; // Some events may need to access objects destroyed in ImplDeleteOnDeInit, so process them first diff --git a/vcl/source/bitmap/BitmapEx.cxx b/vcl/source/bitmap/BitmapEx.cxx index c920b643685d..34573ffc8cf2 100644 --- a/vcl/source/bitmap/BitmapEx.cxx +++ b/vcl/source/bitmap/BitmapEx.cxx @@ -41,7 +41,6 @@ #include <svdata.hxx> #include <vcl/BitmapWriteAccess.hxx> #include <bitmap/BitmapMaskToAlphaFilter.hxx> -#include <bitmap/BlendFrameCache.hxx> #include <tools/stream.hxx> #include <vcl/filter/PngImageWriter.hxx> @@ -967,61 +966,6 @@ BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorMod return BitmapEx(aChangedBitmap); } -BitmapEx createAlphaBlendFrame( - const Size& rSize, - sal_uInt8 nAlpha, - const Color& rColorTopLeft, - const Color& rColorBottomRight) -{ - const sal_uInt32 nW(rSize.Width()); - const sal_uInt32 nH(rSize.Height()); - - if(nW || nH) - { - Color aColTopRight(rColorTopLeft); - Color aColBottomLeft(rColorTopLeft); - const sal_uInt32 nDE(nW + nH); - - aColTopRight.Merge(rColorBottomRight, 255 - sal_uInt8((nW * 255) / nDE)); - aColBottomLeft.Merge(rColorBottomRight, 255 - sal_uInt8((nH * 255) / nDE)); - - return createAlphaBlendFrame(rSize, nAlpha, rColorTopLeft, aColTopRight, rColorBottomRight, aColBottomLeft); - } - - return BitmapEx(); -} - -BitmapEx createAlphaBlendFrame( - const Size& rSize, - sal_uInt8 nAlpha, - const Color& rColorTopLeft, - const Color& rColorTopRight, - const Color& rColorBottomRight, - const Color& rColorBottomLeft) -{ - ImplSVData* pSVData = ImplGetSVData(); - if (!pSVData->mpBlendFrameCache) - { - pSVData->mpBlendFrameCache.reset(new BlendFrameCache(rSize, nAlpha, rColorTopLeft, rColorTopRight, rColorBottomRight, rColorBottomLeft)); - return pSVData->mpBlendFrameCache->m_aLastResult; - } - - BlendFrameCache* pBlendFrameCache = pSVData->mpBlendFrameCache.get(); - - if(pBlendFrameCache->m_aLastSize == rSize - && pBlendFrameCache->m_nLastAlpha == nAlpha - && pBlendFrameCache->m_aLastColorTopLeft == rColorTopLeft - && pBlendFrameCache->m_aLastColorTopRight == rColorTopRight - && pBlendFrameCache->m_aLastColorBottomRight == rColorBottomRight - && pBlendFrameCache->m_aLastColorBottomLeft == rColorBottomLeft) - { - return pBlendFrameCache->m_aLastResult; - } - - pSVData->mpBlendFrameCache.reset(new BlendFrameCache(rSize, nAlpha, rColorTopLeft, rColorTopRight, rColorBottomRight, rColorBottomLeft)); - return pSVData->mpBlendFrameCache->m_aLastResult; -} - void BitmapEx::Replace(const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTolerance) diff --git a/vcl/source/bitmap/BlendFrameCache.cxx b/vcl/source/bitmap/BlendFrameCache.cxx index 92d982d5e4d8..38bd35897c12 100644 --- a/vcl/source/bitmap/BlendFrameCache.cxx +++ b/vcl/source/bitmap/BlendFrameCache.cxx @@ -37,25 +37,21 @@ BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color cons if (rSize.Width() <= 1 || rSize.Height() <= 1) return; - sal_uInt8 aEraseTrans(0xff); - Bitmap aContent(rSize, vcl::PixelFormat::N24_BPP); - AlphaMask aAlpha(rSize, &aEraseTrans); - - aContent.Erase(COL_BLACK); + Bitmap aContent(rSize, vcl::PixelFormat::N32_BPP); + aContent.Erase(COL_TRANSPARENT); { BitmapScopedWriteAccess pContent(aContent); - BitmapScopedWriteAccess pAlpha(aAlpha); - - if (!pContent || !pAlpha) + assert(pContent); + if (!pContent) return; Scanline pScanContent = pContent->GetScanline(0); - Scanline pScanAlpha = pContent->GetScanline(0); // x == 0, y == 0, top-left corner - pContent->SetPixelOnData(pScanContent, 0, rColorTopLeft); - pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); + Color aCol(rColorTopLeft); + aCol.SetAlpha(nAlpha); + pContent->SetPixelOnData(pScanContent, 0, aCol); tools::Long x; const tools::Long nW(rSize.Width()); @@ -66,16 +62,17 @@ BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color cons Color aMix(rColorTopLeft); aMix.Merge(rColorTopRight, 255 - sal_uInt8((x * 255) / nW)); + aMix.SetAlpha(nAlpha); pContent->SetPixelOnData(pScanContent, x, aMix); - pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); } // x == nW - 1, y == 0, top-right corner // #i123690# Caution! When nW is 1, x == nW is possible (!) if (x < nW) { - pContent->SetPixelOnData(pScanContent, x, rColorTopRight); - pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); + aCol = rColorTopRight; + aCol.SetAlpha(nAlpha); + pContent->SetPixelOnData(pScanContent, x, aCol); } tools::Long y; @@ -85,12 +82,11 @@ BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color cons for (y = 1; y < nH - 1; y++) { pScanContent = pContent->GetScanline(y); - pScanAlpha = pContent->GetScanline(y); Color aMixA(rColorTopLeft); aMixA.Merge(rColorBottomLeft, 255 - sal_uInt8((y * 255) / nH)); + aMixA.SetAlpha(nAlpha); pContent->SetPixelOnData(pScanContent, 0, aMixA); - pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); // #i123690# Caution! When nW is 1, x == nW is possible (!) if (x < nW) @@ -98,8 +94,8 @@ BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color cons Color aMixB(rColorTopRight); aMixB.Merge(rColorBottomRight, 255 - sal_uInt8((y * 255) / nH)); + aMixB.SetAlpha(nAlpha); pContent->SetPixelOnData(pScanContent, x, aMixB); - pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); } } @@ -107,8 +103,9 @@ BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color cons if (y < nH) { // x == 0, y == nH - 1, bottom-left corner - pContent->SetPixelOnData(pScanContent, 0, rColorBottomLeft); - pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); + aCol = rColorBottomLeft; + aCol.SetAlpha(nAlpha); + pContent->SetPixelOnData(pScanContent, 0, aCol); // y == nH - 1, bottom line left to right for (x = 1; x < nW - 1; x++) @@ -116,21 +113,22 @@ BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color cons Color aMix(rColorBottomLeft); aMix.Merge(rColorBottomRight, 255 - sal_uInt8(((x - 0) * 255) / nW)); + aMix.SetAlpha(nAlpha); pContent->SetPixelOnData(pScanContent, x, aMix); - pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); } // x == nW - 1, y == nH - 1, bottom-right corner // #i123690# Caution! When nW is 1, x == nW is possible (!) if (x < nW) { - pContent->SetPixelOnData(pScanContent, x, rColorBottomRight); - pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); + aCol = rColorBottomRight; + aCol.SetAlpha(nAlpha); + pContent->SetPixelOnData(pScanContent, x, aCol); } } } - m_aLastResult = BitmapEx(aContent, aAlpha); + m_aLastResult = aContent; } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx index 9051b5ed4a78..9e252731200e 100644 --- a/vcl/source/bitmap/bitmap.cxx +++ b/vcl/source/bitmap/bitmap.cxx @@ -46,6 +46,7 @@ #include <vcl/BitmapWriteAccess.hxx> #include <bitmap/impoctree.hxx> #include <bitmap/Octree.hxx> +#include <bitmap/BlendFrameCache.hxx> #include <com/sun/star/beans/XFastPropertySet.hpp> #include <o3tl/any.hxx> @@ -2456,4 +2457,59 @@ void Bitmap::GetColorModel(css::uno::Sequence< sal_Int32 >& rRGBPalette, rnBitCount = pReadAccess->GetBitCount(); } +Bitmap createAlphaBlendFrame( + const Size& rSize, + sal_uInt8 nAlpha, + const Color& rColorTopLeft, + const Color& rColorBottomRight) +{ + const sal_uInt32 nW(rSize.Width()); + const sal_uInt32 nH(rSize.Height()); + + if(nW || nH) + { + Color aColTopRight(rColorTopLeft); + Color aColBottomLeft(rColorTopLeft); + const sal_uInt32 nDE(nW + nH); + + aColTopRight.Merge(rColorBottomRight, 255 - sal_uInt8((nW * 255) / nDE)); + aColBottomLeft.Merge(rColorBottomRight, 255 - sal_uInt8((nH * 255) / nDE)); + + return createAlphaBlendFrame(rSize, nAlpha, rColorTopLeft, aColTopRight, rColorBottomRight, aColBottomLeft); + } + + return Bitmap(); +} + +Bitmap createAlphaBlendFrame( + const Size& rSize, + sal_uInt8 nAlpha, + const Color& rColorTopLeft, + const Color& rColorTopRight, + const Color& rColorBottomRight, + const Color& rColorBottomLeft) +{ + ImplSVData* pSVData = ImplGetSVData(); + if (!pSVData->mpBlendFrameCache) + { + pSVData->mpBlendFrameCache.reset(new BlendFrameCache(rSize, nAlpha, rColorTopLeft, rColorTopRight, rColorBottomRight, rColorBottomLeft)); + return pSVData->mpBlendFrameCache->m_aLastResult; + } + + BlendFrameCache* pBlendFrameCache = pSVData->mpBlendFrameCache.get(); + + if(pBlendFrameCache->m_aLastSize == rSize + && pBlendFrameCache->m_nLastAlpha == nAlpha + && pBlendFrameCache->m_aLastColorTopLeft == rColorTopLeft + && pBlendFrameCache->m_aLastColorTopRight == rColorTopRight + && pBlendFrameCache->m_aLastColorBottomRight == rColorBottomRight + && pBlendFrameCache->m_aLastColorBottomLeft == rColorBottomLeft) + { + return pBlendFrameCache->m_aLastResult; + } + + pSVData->mpBlendFrameCache.reset(new BlendFrameCache(rSize, nAlpha, rColorTopLeft, rColorTopRight, rColorBottomRight, rColorBottomLeft)); + return pSVData->mpBlendFrameCache->m_aLastResult; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */