vcl/Library_vcl.mk | 1 vcl/inc/bitmap/BlendFrameCache.hxx | 40 ++++++++++ vcl/inc/svdata.hxx | 23 ----- vcl/source/app/svdata.cxx | 11 -- vcl/source/app/svmain.cxx | 2 vcl/source/bitmap/BitmapEx.cxx | 119 ++--------------------------- vcl/source/bitmap/BlendFrameCache.cxx | 136 ++++++++++++++++++++++++++++++++++ 7 files changed, 193 insertions(+), 139 deletions(-)
New commits: commit 9efbc448876d92d24697fa0eddd4580dcdbb9672 Author: Christopher Sherlock <chris.sherloc...@gmail.com> AuthorDate: Wed Dec 4 21:17:36 2024 +1100 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Fri Dec 20 07:16:49 2024 +0100 vcl: BlendFrameCache refactor - split off BlendFrameCache.hxx to own header - move functionality into constructor Much of the functionality in createAlphaBlendFrame() just updates the BlendFrameCache's bitmap frame. Really, this should be done when a BlendFrameCache is instantiated, so functionality has been moved out of createAlphaBlendFrame() and into the BlendFrameCache constructor. Change-Id: Ia53a6f1c058ccb5f0ee4314b7a6e0b02ad7db376 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177802 Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> Tested-by: Jenkins diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 79ea2cc1974a..8ce46293c988 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -434,6 +434,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/bitmap/BitmapColorQuantizationFilter \ vcl/source/bitmap/BitmapSimpleColorQuantizationFilter \ vcl/source/bitmap/BitmapTools \ + vcl/source/bitmap/BlendFrameCache \ vcl/source/bitmap/Octree \ vcl/source/bitmap/salbmp \ vcl/source/image/Image \ diff --git a/vcl/inc/bitmap/BlendFrameCache.hxx b/vcl/inc/bitmap/BlendFrameCache.hxx new file mode 100644 index 000000000000..61d4ff6de6aa --- /dev/null +++ b/vcl/inc/bitmap/BlendFrameCache.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <tools/color.hxx> +#include <tools/gen.hxx> + +#include <vcl/bitmapex.hxx> + +struct BlendFrameCache +{ + Size m_aLastSize; + sal_uInt8 m_nLastAlpha; + Color m_aLastColorTopLeft; + Color m_aLastColorTopRight; + Color m_aLastColorBottomRight; + Color m_aLastColorBottomLeft; + BitmapEx m_aLastResult; + + BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color const& rColorTopLeft, + Color const& rColorTopRight, Color const& rColorBottomRight, + Color const& rColorBottomLeft); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index c332894e1fc8..86b07bce6caa 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -69,6 +69,7 @@ namespace vcl::font class DirectFontSubstitution; class PhysicalFontCollection; } +struct BlendFrameCache; struct ImplHotKey; struct ImplEventHook; class Point; @@ -355,27 +356,6 @@ struct ImplSVNWFData int mnListBoxEntryMargin = 0; }; -struct BlendFrameCache -{ - Size m_aLastSize; - sal_uInt8 m_nLastAlpha; - Color m_aLastColorTopLeft; - Color m_aLastColorTopRight; - Color m_aLastColorBottomRight; - Color m_aLastColorBottomLeft; - BitmapEx m_aLastResult; - - BlendFrameCache() - : m_aLastSize(0, 0) - , m_nLastAlpha(0) - , m_aLastColorTopLeft(COL_BLACK) - , m_aLastColorTopRight(COL_BLACK) - , m_aLastColorBottomRight(COL_BLACK) - , m_aLastColorBottomLeft(COL_BLACK) - { - } -}; - struct ImplSchedulerContext { ImplSchedulerData* mpFirstSchedulerData[PRIO_COUNT] = { nullptr, }; ///< list of all active tasks per priority @@ -452,7 +432,6 @@ vcl::Window* ImplGetDefaultContextWindow(); const std::locale& ImplGetResLocale(); VCL_PLUGIN_PUBLIC OUString VclResId(TranslateId sContextAndId); DockingManager* ImplGetDockingManager(); -BlendFrameCache* ImplGetBlendFrameCache(); void GenerateAutoMnemonicsOnHierarchy(const vcl::Window* pWindow); VCL_PLUGIN_PUBLIC ImplSVHelpData& ImplGetSVHelpData(); diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index f767c2483925..2ff5e69abf48 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -38,6 +38,8 @@ #include <vcl/virdev.hxx> #include <vcl/wrkwin.hxx> #include <vcl/uitest/logger.hxx> + +#include <bitmap/BlendFrameCache.hxx> #include <salframe.hxx> #include <scrwnd.hxx> #include <helpwin.hxx> @@ -362,15 +364,6 @@ DockingManager* ImplGetDockingManager() return pSVData->mpDockingManager.get(); } -BlendFrameCache* ImplGetBlendFrameCache() -{ - ImplSVData* pSVData = ImplGetSVData(); - if ( !pSVData->mpBlendFrameCache) - pSVData->mpBlendFrameCache.reset( new BlendFrameCache() ); - - return pSVData->mpBlendFrameCache.get(); -} - void LocaleConfigurationListener::ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints nHint ) { AllSettings::LocaleSettingsChanged( nHint ); diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index 9ef22da996e6..4c81138c117f 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -51,6 +51,8 @@ #include <vcl/menu.hxx> #include <vcl/virdev.hxx> #include <vcl/print.hxx> + +#include <bitmap/BlendFrameCache.hxx> #include <debugevent.hxx> #include <scrwnd.hxx> #include <windowdev.hxx> diff --git a/vcl/source/bitmap/BitmapEx.cxx b/vcl/source/bitmap/BitmapEx.cxx index d20954b270dc..0d734eaa1831 100644 --- a/vcl/source/bitmap/BitmapEx.cxx +++ b/vcl/source/bitmap/BitmapEx.cxx @@ -40,6 +40,7 @@ #include <svdata.hxx> #include <vcl/BitmapWriteAccess.hxx> #include <bitmap/BitmapMaskToAlphaFilter.hxx> +#include <bitmap/BlendFrameCache.hxx> #include <o3tl/any.hxx> #include <tools/stream.hxx> @@ -1056,7 +1057,14 @@ BitmapEx createAlphaBlendFrame( const Color& rColorBottomRight, const Color& rColorBottomLeft) { - BlendFrameCache* pBlendFrameCache = ImplGetBlendFrameCache(); + 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 @@ -1068,113 +1076,8 @@ BitmapEx createAlphaBlendFrame( return pBlendFrameCache->m_aLastResult; } - pBlendFrameCache->m_aLastSize = rSize; - pBlendFrameCache->m_nLastAlpha = nAlpha; - pBlendFrameCache->m_aLastColorTopLeft = rColorTopLeft; - pBlendFrameCache->m_aLastColorTopRight = rColorTopRight; - pBlendFrameCache->m_aLastColorBottomRight = rColorBottomRight; - pBlendFrameCache->m_aLastColorBottomLeft = rColorBottomLeft; - pBlendFrameCache->m_aLastResult.Clear(); - - const tools::Long nW(rSize.Width()); - const tools::Long nH(rSize.Height()); - - if(nW > 1 && nH > 1) - { - sal_uInt8 aEraseTrans(0xff); - Bitmap aContent(rSize, vcl::PixelFormat::N24_BPP); - AlphaMask aAlpha(rSize, &aEraseTrans); - - aContent.Erase(COL_BLACK); - - BitmapScopedWriteAccess pContent(aContent); - BitmapScopedWriteAccess pAlpha(aAlpha); - - if(pContent && pAlpha) - { - tools::Long x(0); - tools::Long y(0); - 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)); - - // y == 0, top line left to right - for(x = 1; x < nW - 1; x++) - { - Color aMix(rColorTopLeft); - - aMix.Merge(rColorTopRight, 255 - sal_uInt8((x * 255) / nW)); - 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)); - } - - // x == 0 and nW - 1, left and right line top-down - 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)); - pContent->SetPixelOnData(pScanContent, 0, aMixA); - pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); - - // #i123690# Caution! When nW is 1, x == nW is possible (!) - if(x < nW) - { - Color aMixB(rColorTopRight); - - aMixB.Merge(rColorBottomRight, 255 - sal_uInt8((y * 255) / nH)); - pContent->SetPixelOnData(pScanContent, x, aMixB); - pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); - } - } - - // #i123690# Caution! When nH is 1, y == nH is possible (!) - if(y < nH) - { - // x == 0, y == nH - 1, bottom-left corner - pContent->SetPixelOnData(pScanContent, 0, rColorBottomLeft); - pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); - - // y == nH - 1, bottom line left to right - for(x = 1; x < nW - 1; x++) - { - Color aMix(rColorBottomLeft); - - aMix.Merge(rColorBottomRight, 255 - sal_uInt8(((x - 0)* 255) / nW)); - 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)); - } - } - - pContent.reset(); - pAlpha.reset(); - - pBlendFrameCache->m_aLastResult = BitmapEx(aContent, aAlpha); - } - } - - 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, diff --git a/vcl/source/bitmap/BlendFrameCache.cxx b/vcl/source/bitmap/BlendFrameCache.cxx new file mode 100644 index 000000000000..190dbf3d9e44 --- /dev/null +++ b/vcl/source/bitmap/BlendFrameCache.cxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <tools/color.hxx> + +#include <vcl/BitmapColor.hxx> +#include <vcl/BitmapWriteAccess.hxx> + +#include <bitmap/BlendFrameCache.hxx> + +BlendFrameCache::BlendFrameCache(Size const& rSize, sal_uInt8 nAlpha, Color const& rColorTopLeft, + Color const& rColorTopRight, Color const& rColorBottomRight, + Color const& rColorBottomLeft) + : m_aLastSize(rSize) + , m_nLastAlpha(nAlpha) + , m_aLastColorTopLeft(rColorTopLeft) + , m_aLastColorTopRight(rColorTopRight) + , m_aLastColorBottomRight(rColorBottomRight) + , m_aLastColorBottomLeft(rColorBottomLeft) +{ + const tools::Long nW(rSize.Width()); + const tools::Long nH(rSize.Height()); + + if (nW > 1 && nH > 1) + { + sal_uInt8 aEraseTrans(0xff); + Bitmap aContent(rSize, vcl::PixelFormat::N24_BPP); + AlphaMask aAlpha(rSize, &aEraseTrans); + + aContent.Erase(COL_BLACK); + + BitmapScopedWriteAccess pContent(aContent); + BitmapScopedWriteAccess pAlpha(aAlpha); + + if (pContent && pAlpha) + { + tools::Long x(0); + tools::Long y(0); + 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)); + + // y == 0, top line left to right + for (x = 1; x < nW - 1; x++) + { + Color aMix(rColorTopLeft); + + aMix.Merge(rColorTopRight, 255 - sal_uInt8((x * 255) / nW)); + 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)); + } + + // x == 0 and nW - 1, left and right line top-down + 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)); + pContent->SetPixelOnData(pScanContent, 0, aMixA); + pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); + + // #i123690# Caution! When nW is 1, x == nW is possible (!) + if (x < nW) + { + Color aMixB(rColorTopRight); + + aMixB.Merge(rColorBottomRight, 255 - sal_uInt8((y * 255) / nH)); + pContent->SetPixelOnData(pScanContent, x, aMixB); + pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha)); + } + } + + // #i123690# Caution! When nH is 1, y == nH is possible (!) + if (y < nH) + { + // x == 0, y == nH - 1, bottom-left corner + pContent->SetPixelOnData(pScanContent, 0, rColorBottomLeft); + pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha)); + + // y == nH - 1, bottom line left to right + for (x = 1; x < nW - 1; x++) + { + Color aMix(rColorBottomLeft); + + aMix.Merge(rColorBottomRight, 255 - sal_uInt8(((x - 0) * 255) / nW)); + 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)); + } + } + + pContent.reset(); + pAlpha.reset(); + + m_aLastResult = BitmapEx(aContent, aAlpha); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */