editeng/source/outliner/outlin2.cxx | 9 --- editeng/source/outliner/outliner.cxx | 25 +++++--- editeng/source/outliner/paralist.cxx | 12 ---- include/docmodel/color/ComplexColor.hxx | 59 +++++++++++++++++++++ include/editeng/outliner.hxx | 73 ++++++++++++++++++++++---- include/svx/ColorSets.hxx | 3 - sd/qa/unit/export-tests-ooxml2.cxx | 7 ++ sd/qa/unit/import-tests.cxx | 35 ++++++++---- sd/qa/unit/uiimpress.cxx | 10 +-- sd/source/core/drawdoc4.cxx | 25 +++++++- sd/source/ui/unoidl/unopage.cxx | 18 +++++- svx/source/styles/ColorSets.cxx | 40 ++++++++++++-- svx/source/svdraw/svdmodel.cxx | 10 +-- svx/source/svdraw/svdpage.cxx | 12 +++- svx/source/theme/ThemeColorPaletteManager.cxx | 39 +------------ 15 files changed, 264 insertions(+), 113 deletions(-)
New commits: commit 8b7da6ae2f5f056806e491a8002f20b0d1b912df Author: Tomaž Vajngerl <[email protected]> AuthorDate: Mon Jan 19 13:00:43 2026 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Feb 23 14:08:58 2026 +0100 sd: Fix different rendering when in view and edit when scaling If the text box is scaled and the scaling changes, we need to invalidate the bullet sizes, but we only do this when scaling is set from the outside. If the scaling adjustment is done internally we don't invalidate the bullet size, which results to different rendering. So instead of relying that the bullet size is invalidated at some point, we store the scaling factor with the bullet and recalculate it when it doesn't match with the current scaling factor. Change-Id: I116249f111bd8dd57ab38c4066d4ab51ae396f49 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197537 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200025 Tested-by: Tomaž Vajngerl <[email protected]> diff --git a/editeng/source/outliner/outlin2.cxx b/editeng/source/outliner/outlin2.cxx index a53c11db8676..c2cbca480b16 100644 --- a/editeng/source/outliner/outlin2.cxx +++ b/editeng/source/outliner/outlin2.cxx @@ -479,15 +479,6 @@ const ScalingParameters & Outliner::getScalingParameters() const void Outliner::setScalingParameters(ScalingParameters const& rScalingParameters) { - // reset bullet size - sal_Int32 nParagraphs = pParaList->GetParagraphCount(); - for ( sal_Int32 nPara = 0; nPara < nParagraphs; nPara++ ) - { - Paragraph* pPara = pParaList->GetParagraph( nPara ); - if ( pPara ) - pPara->aBulSize.setWidth( -1 ); - } - pEditEngine->setScalingParameters(rScalingParameters); } diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index 760b7dca4eb0..b09dfc33cc4f 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -676,7 +676,7 @@ void Outliner::ImplCheckNumBulletItem( sal_Int32 nPara ) { Paragraph* pPara = pParaList->GetParagraph( nPara ); if (pPara) - pPara->aBulSize.setWidth( -1 ); + pPara->Invalidate(); } void Outliner::ImplSetLevelDependentStyleSheet( sal_Int32 nPara ) @@ -994,7 +994,7 @@ void Outliner::StripBullet( DrawBulletInfo aDrawBulletInfo( *pFmt->GetBrush()->GetGraphicObject(), aBulletPos, - pPara->aBulSize); + pPara->GetBulletSize()); rStripPortionsHelper.processDrawBulletInfo(aDrawBulletInfo); } } @@ -1316,14 +1316,16 @@ Size Outliner::ImplGetBulletSize( sal_Int32 nPara ) if (!pPara) return Size(); - if( pPara->aBulSize.Width() == -1 ) + auto aScalingParameters = getScalingParameters(); + Size aSize; + + if (pPara->IsBulletInvalid(aScalingParameters)) { const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); assert(pFmt && "ImplGetBulletSize - no Bullet!"); - if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE ) { - pPara->aBulSize = Size( 0, 0 ); + aSize = Size(0, 0); } else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) { @@ -1332,19 +1334,22 @@ Size Outliner::ImplGetBulletSize( sal_Int32 nPara ) vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) ); vcl::Font aRefFont( pRefDev->GetFont()); pRefDev->SetFont( aBulletFont ); - pPara->aBulSize.setWidth( pRefDev->GetTextWidth( aBulletText ) ); - pPara->aBulSize.setHeight( pRefDev->GetTextHeight() ); + tools::Long x = pRefDev->GetTextWidth(aBulletText); + tools::Long y = pRefDev->GetTextHeight(); + aSize = Size(x, y); pRefDev->SetFont( aRefFont ); } else { - pPara->aBulSize = OutputDevice::LogicToLogic(pFmt->GetGraphicSize(), + aSize = OutputDevice::LogicToLogic(pFmt->GetGraphicSize(), MapMode(MapUnit::Map100thMM), pEditEngine->GetRefDevice()->GetMapMode()); } + + pPara->SetBulletSize(aSize, aScalingParameters); } - return pPara->aBulSize; + return pPara->GetBulletSize(); } void Outliner::ImplCheckParagraphs( sal_Int32 nStart, sal_Int32 nEnd ) @@ -1778,7 +1783,7 @@ void Outliner::SetFlatMode( bool bFlat ) if( bFlat != pEditEngine->IsFlatMode() ) { for ( sal_Int32 nPara = pParaList->GetParagraphCount(); nPara; ) - pParaList->GetParagraph( --nPara )->aBulSize.setWidth( -1 ); + pParaList->GetParagraph( --nPara )->Invalidate(); pEditEngine->SetFlatMode( bFlat ); } diff --git a/editeng/source/outliner/paralist.cxx b/editeng/source/outliner/paralist.cxx index d25a00b18207..d46fc8cf7d48 100644 --- a/editeng/source/outliner/paralist.cxx +++ b/editeng/source/outliner/paralist.cxx @@ -43,30 +43,18 @@ bool ParagraphData::operator==(const ParagraphData& rCandidate) const } Paragraph::Paragraph( sal_Int16 nDDepth ) -: aBulSize( -1, -1) { - DBG_ASSERT( ( nDDepth >= -1 ) && ( nDDepth < SVX_MAX_NUM ), "Paragraph-CTOR: nDepth invalid!" ); - nDepth = nDDepth; - nFlags = ParaFlag::NONE; - bVisible = true; } Paragraph::Paragraph( const ParagraphData& rData ) -: aBulSize( -1, -1) -, nFlags( ParaFlag::NONE ) -, bVisible( true ) { nDepth = rData.nDepth; mnNumberingStartValue = rData.mnNumberingStartValue; mbParaIsNumberingRestart = rData.mbParaIsNumberingRestart; } -Paragraph::~Paragraph() -{ -} - void Paragraph::SetNumberingStartValue( sal_Int16 nNumberingStartValue ) { mnNumberingStartValue = nNumberingStartValue; diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index 274ac4f23c14..e2052f215e89 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -115,6 +115,15 @@ namespace o3tl #define OLUNDO_INSERT EDITUNDO_USER+6 // #define OLUNDO_MOVEPARAGRAPHS EDITUNDO_USER+7 +/** Information about the bullet in the paragraph*/ +struct BulletInfo +{ +public: + OUString maText; + Size maSize = Size(-1, -1); + ScalingParameters maScalingParameters; +}; + class Paragraph : protected ParagraphData { private: @@ -128,17 +137,61 @@ private: Paragraph& operator=(const Paragraph& rPara ) = delete; - OUString aBulText; - Size aBulSize; - ParaFlag nFlags; - bool bVisible; + BulletInfo maBullet; + ParaFlag nFlags = ParaFlag::NONE; + bool bVisible = true; bool IsVisible() const { return bVisible; } - void SetText( const OUString& rText ) { aBulText = rText; aBulSize.setWidth(-1); } - void Invalidate() { aBulSize.setWidth(-1); } - void SetDepth( sal_Int16 nNewDepth ) { nDepth = nNewDepth; aBulSize.setWidth(-1); } - const OUString& GetText() const { return aBulText; } + void SetText(const OUString& rText) + { + maBullet.maText = rText; + Invalidate(); + } + + /// Sets the bullet size as well as the scaling parameters used to calculate the size + void SetBulletSize(Size const& rSize, ScalingParameters const& rScalingParameters) + { + maBullet.maSize = rSize; + maBullet.maScalingParameters = rScalingParameters; + } + + /// Current size of the bullet + Size const& GetBulletSize() + { + return maBullet.maSize; + } + + /// Is the bullet size invalid for the current scaling parameters + bool IsBulletInvalid(ScalingParameters const& rCurrentScalingParameters) + { + return rCurrentScalingParameters != maBullet.maScalingParameters + || maBullet.maSize.Width() == -1 + || maBullet.maSize.Height() == -1; + } + + /// Invalidate paragraph calculated information: bullet size + void Invalidate() + { + maBullet.maSize.setWidth(-1); + maBullet.maSize.setHeight(-1); + } + + void SetDepth(sal_Int16 nNewDepth) + { + nDepth = nNewDepth; + Invalidate(); + } + + const OUString& GetText() const + { + return maBullet.maText; + } + + BulletInfo const& GetBullet() + { + return maBullet; + } Paragraph( sal_Int16 nDepth ); Paragraph( const Paragraph& ) = delete; Paragraph( const ParagraphData& ); @@ -154,9 +207,9 @@ private: void SetFlag( ParaFlag nFlag ) { nFlags |= nFlag; } void RemoveFlag( ParaFlag nFlag ) { nFlags &= ~nFlag; } bool HasFlag( ParaFlag nFlag ) const { return bool(nFlags & nFlag); } + public: - ~Paragraph(); - void dumpAsXml(xmlTextWriterPtr pWriter) const; + void dumpAsXml(xmlTextWriterPtr pWriter) const; }; struct ParaRange commit 65b3f5255135ab9bc338d188b58bb8fdca3acd3c Author: Tomaž Vajngerl <[email protected]> AuthorDate: Wed Dec 17 20:56:56 2025 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Feb 23 14:08:43 2026 +0100 sd: Default drawing style to use ComplexColor for fill and line This changes the default drawing style to use theme colors for fill and line colors that will be used by by shapes. The use of theme color is needed so that changing the document theme will have an effect by default. This also means the default color will be different than before - it will use the colors defined by the default theme used by documents (LibreOffice theme). Additionally it increases the default line size to make the shapes more atttractive. Test testThemeShapeInsert has been re-added and changed to pass. Other tests have been fixed or changed to set to use the default theme by force, which uses the old fill color for accent{1,2,3} and old line color for accent{4,5,6}. With this the tests don't need to be changed if they check the FillColor, which is set to a default color (from the style). Change-Id: Ibb16961dec79232603619efe040db70d90e07cee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195787 Reviewed-by: Tomaž Vajngerl <[email protected]> Tested-by: Jenkins Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200024 Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/include/docmodel/color/ComplexColor.hxx b/include/docmodel/color/ComplexColor.hxx index b83b63a23fa3..d681a03b99d1 100644 --- a/include/docmodel/color/ComplexColor.hxx +++ b/include/docmodel/color/ComplexColor.hxx @@ -15,8 +15,10 @@ #include <docmodel/theme/ThemeColorType.hxx> #include <docmodel/color/Transformation.hxx> #include <o3tl/hash_combine.hxx> +#include <basegfx/color/bcolortools.hxx> #include <vector> +#include <array> namespace model { @@ -200,6 +202,63 @@ public: aComplexColor.setThemeColor(eThemeColorType); return aComplexColor; } + + static sal_Int32 getLumMod(size_t nIndex, size_t nEffect) + { + static constexpr std::array<const std::array<sal_Int32, 6>, 5> g_aLumMods = { + std::array<sal_Int32, 6>{ 10'000, 5'000, 6'500, 7'500, 8'500, 9'500 }, + std::array<sal_Int32, 6>{ 10'000, 1'000, 2'500, 5'000, 7'500, 9'000 }, + std::array<sal_Int32, 6>{ 10'000, 2'000, 4'000, 6'000, 7'500, 5'000 }, + std::array<sal_Int32, 6>{ 10'000, 9'000, 7'500, 5'000, 2'500, 1'000 }, + std::array<sal_Int32, 6>{ 10'000, 9'500, 8'500, 7'500, 6'500, 5'000 }, + }; + return g_aLumMods[nIndex][nEffect]; + } + + static sal_Int32 getLumOff(size_t nIndex, size_t nEffect) + { + static constexpr std::array<const std::array<sal_Int32, 6>, 5> g_aLumOffs = { + std::array<sal_Int32, 6>{ 0, 5'000, 3'500, 2'500, 1'500, 0'500 }, + std::array<sal_Int32, 6>{ 0, 9'000, 7'500, 5'000, 2'500, 1'000 }, + std::array<sal_Int32, 6>{ 0, 8'000, 6'000, 4'000, 0, 0 }, + std::array<sal_Int32, 6>{ 0, 0, 0, 0, 0, 0 }, + std::array<sal_Int32, 6>{ 0, 0, 0, 0, 0, 0 }, + }; + return g_aLumOffs[nIndex][nEffect]; + } + + static size_t getIndexForLuminance(Color const& rColor) + { + basegfx::BColor aHSLColor = basegfx::utils::rgb2hsl(rColor.getBColor()); + double aLuminanceValue = aHSLColor.getBlue() * 255.0; + + if (aLuminanceValue < 0.5) + return 0; // Black + else if (aLuminanceValue > 254.5) + return 4; // White + else if (aLuminanceValue < 50.5) + return 1; // Low + else if (aLuminanceValue > 203.5) + return 3; // High + else + return 2; // Middle + } + + static model::ComplexColor create(model::ThemeColorType eThemeType, Color const& rThemeColor, + sal_Int32 nEffect) + { + size_t nIndex = getIndexForLuminance(rThemeColor); + + auto aComplexColor = model::ComplexColor::Theme(eThemeType); + + aComplexColor.addTransformation( + { model::TransformationType::LumMod, getLumMod(nIndex, nEffect) }); + + aComplexColor.addTransformation( + { model::TransformationType::LumOff, getLumOff(nIndex, nEffect) }); + + return aComplexColor; + } }; } // end of namespace model diff --git a/include/svx/ColorSets.hxx b/include/svx/ColorSets.hxx index a3557debca19..372243424956 100644 --- a/include/svx/ColorSets.hxx +++ b/include/svx/ColorSets.hxx @@ -25,13 +25,14 @@ private: void init(); public: static ColorSets& get(); + static model::ColorSet const* getDefault(); const std::vector<model::ColorSet>& getColorSetVector() const { return maColorSets; } - const model::ColorSet& getColorSet(sal_uInt32 nIndex) const + model::ColorSet const& getColorSet(sal_uInt32 nIndex) const { return maColorSets[nIndex]; } diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index d009c43cde0f..ccd6f1be815e 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -480,7 +480,12 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTdf132472) xCell.set(xTable->getCellByPosition(0, 0), uno::UNO_QUERY_THROW); xCell->getPropertyValue(u"FillColor"_ustr) >>= nColor; - CPPUNIT_ASSERT_EQUAL(Color(0x729fcf), nColor); + // Fill color is set to default (from style). + CPPUNIT_ASSERT_EQUAL(Color(0x18a303), nColor); + drawing::FillStyle aFillStyle(drawing::FillStyle_NONE); + xCell->getPropertyValue(u"FillStyle"_ustr) >>= aFillStyle; + // But fill style is NONE anyway. + CPPUNIT_ASSERT_EQUAL(int(drawing::FillStyle_NONE), static_cast<int>(aFillStyle)); uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xCell)); uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph)); diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index bafca667088e..6fd736cb80c4 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -33,6 +33,10 @@ #include <svx/sdmetitm.hxx> #include <animations/animationnodehelper.hxx> #include <sax/tools/converter.hxx> +#include <docmodel/theme/ColorSet.hxx> +#include <docmodel/theme/Theme.hxx> +#include <docmodel/uno/UnoTheme.hxx> +#include <o3tl/environment.hxx> #include <com/sun/star/awt/Gradient.hpp> #include <com/sun/star/awt/Gradient2.hpp> @@ -123,12 +127,19 @@ the test, and re-running; it should break. */ CPPUNIT_TEST_FIXTURE(SdImportTest, testDocumentLayout) { - static const struct + // Use fallback document theme, which uses previous default + // fill and line colors as accent colors. + o3tl::setEnvironment(u"LO_FORCE_FALLBACK_DOCUMENT_THEME"_ustr, u"1"_ustr); + + struct TestDumpInfo { - std::u16string_view sInput, sDump; + std::u16string_view sInput; + std::u16string_view sDump; TestFilter sExportType; - } aFilesToCompare[] - = { { u"odp/shapes-test.odp", u"xml/shapes-test_page", TestFilter::NONE }, + }; + + auto aFilesToCompare = std::to_array<TestDumpInfo>({ + { u"odp/shapes-test.odp", u"xml/shapes-test_page", TestFilter::NONE }, { u"fdo47434.pptx", u"xml/fdo47434_", TestFilter::NONE }, { u"n758621.ppt", u"xml/n758621_", TestFilter::NONE }, { u"fdo64586.ppt", u"xml/fdo64586_", TestFilter::NONE }, @@ -155,17 +166,18 @@ CPPUNIT_TEST_FIXTURE(SdImportTest, testDocumentLayout) { u"tdf100491.pptx", u"xml/tdf100491_", TestFilter::NONE }, #endif { u"tdf109317.pptx", u"xml/tdf109317_", TestFilter::ODP }, - // { u"pptx/n828390.pptx", u"pptx/xml/n828390_", TestFilter::PPTX }, // Example - }; + // { u"pptx/n828390.pptx", u"pptx/xml/n828390_", TestFilter::PPTX }, // Example + }); - for (int i = 0; i < static_cast<int>(SAL_N_ELEMENTS(aFilesToCompare)); ++i) + for (size_t i = 0; i < aFilesToCompare.size(); ++i) { - int const nUpdateMe - = -1; // index of test we want to update; supposedly only when the test is created + size_t const nUpdateMe + = SAL_MAX_UINT32; // index of test we want to update; supposedly only when the test is created loadFromFile(aFilesToCompare[i].sInput); if (aFilesToCompare[i].sExportType != TestFilter::NONE) saveAndReload(aFilesToCompare[i].sExportType); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY_THROW); uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages(); @@ -174,9 +186,8 @@ CPPUNIT_TEST_FIXTURE(SdImportTest, testDocumentLayout) sal_Int32 nLength = xDrawPages->getCount(); for (sal_Int32 j = 0; j < nLength; ++j) { - uno::Reference<drawing::XDrawPage> xDrawPage; - uno::Any aAny = xDrawPages->getByIndex(j); - aAny >>= xDrawPage; + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(j), uno::UNO_QUERY); + CPPUNIT_ASSERT(xDrawPage.is()); uno::Reference<drawing::XShapes> xShapes(xDrawPage, uno::UNO_QUERY_THROW); OUString aString = XShapeDumper::dump(xShapes); diff --git a/sd/qa/unit/uiimpress.cxx b/sd/qa/unit/uiimpress.cxx index 638e367ca2da..9c29597a3e61 100644 --- a/sd/qa/unit/uiimpress.cxx +++ b/sd/qa/unit/uiimpress.cxx @@ -2074,8 +2074,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf127696) CPPUNIT_ASSERT(bContoured); } -// TODO - Readd when we implement style level fill color and set that for default style -/*CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testThemeShapeInsert) +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testThemeShapeInsert) { // Given a document with a theme, accent1 color is set to 0x000004: createSdImpressDoc(); @@ -2108,6 +2107,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf127696) uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("CreateDirectly", true), }; + dispatchCommand(mxComponent, ".uno:BasicShapes.round-rectangle", aArgs); // Then make sure the that fill color of the last shape is the accent1 color: @@ -2115,11 +2115,9 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf127696) uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(nShapeIndex), uno::UNO_QUERY); sal_Int32 nFillColor{}; xShape->getPropertyValue("FillColor") >>= nFillColor; - // Without the accompanying fix in place, this test would have failed with: - // - Expected: 0 / 0x000004 (~black) - // - Actual : 7512015 / 0x729fcf (~blue) + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0x4), nFillColor); -}*/ +} CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf166647_userpaint) { diff --git a/sd/source/core/drawdoc4.cxx b/sd/source/core/drawdoc4.cxx index 543417cc3bfb..37606a66bcc7 100644 --- a/sd/source/core/drawdoc4.cxx +++ b/sd/source/core/drawdoc4.cxx @@ -105,6 +105,7 @@ #include <sfx2/viewfrm.hxx> #include <editeng/frmdiritem.hxx> #include <svx/sdasitm.hxx> +#include <docmodel/theme/Theme.hxx> #include <sdresid.hxx> #include <drawdoc.hxx> @@ -164,10 +165,26 @@ void SdDrawDocument::CreateLayoutTemplates() aNullGrad.SetEndIntens(100); XHatch aNullHatch(aNullCol); + // Setup default colors, sizes + const tools::Long nDefaultLineSize = pointsToHMM(3); + + auto eLineAndFillThemeType = model::ThemeColorType::Accent1; + auto aFillComplexColor = model::ComplexColor::Theme(eLineAndFillThemeType); + Color aFillColor = getTheme()->getColorSet()->resolveColor(aFillComplexColor); + aFillComplexColor.setFinalColor(aFillColor); + + Color aBaseThemeColor = getTheme()->getColorSet()->getColor(eLineAndFillThemeType); + auto aLineComplexColor = model::ComplexColor::create(eLineAndFillThemeType, aBaseThemeColor, 4); + + Color aLineColor = getTheme()->getColorSet()->resolveColor(aLineComplexColor); + aLineComplexColor.setFinalColor(aLineColor); + // Line attributes (Extended OutputDevice) rISet.Put(XLineStyleItem(drawing::LineStyle_SOLID)); - rISet.Put(XLineColorItem(OUString(), COL_DEFAULT_SHAPE_STROKE)); - rISet.Put(XLineWidthItem(0)); + XLineColorItem aLineColorItem(OUString(), aLineColor); + aLineColorItem.setComplexColor(aLineComplexColor); + rISet.Put(aLineColorItem); + rISet.Put(XLineWidthItem(nDefaultLineSize)); rISet.Put(XLineDashItem(aNullDash)); rISet.Put(XLineStartItem(basegfx::B2DPolyPolygon())); rISet.Put(XLineEndItem(basegfx::B2DPolyPolygon())); @@ -179,7 +196,9 @@ void SdDrawDocument::CreateLayoutTemplates() // Fill attributes (Extended OutputDevice) rISet.Put(XFillStyleItem(drawing::FillStyle_SOLID)); - rISet.Put(XFillColorItem(OUString(), COL_DEFAULT_SHAPE_FILLING)); + XFillColorItem aFillColorItem(OUString(), aFillColor); + aFillColorItem.setComplexColor(aFillComplexColor); + rISet.Put(aFillColorItem); rISet.Put(XFillGradientItem(aNullGrad)); rISet.Put(XFillHatchItem(aNullHatch)); diff --git a/sd/source/ui/unoidl/unopage.cxx b/sd/source/ui/unoidl/unopage.cxx index 738fad066bec..56f3da3e8157 100644 --- a/sd/source/ui/unoidl/unopage.cxx +++ b/sd/source/ui/unoidl/unopage.cxx @@ -68,6 +68,7 @@ #include <DrawViewShell.hxx> #include <editeng/unoprnms.hxx> #include "unoobj.hxx" +#include <theme/ThemeColorChanger.hxx> #include <strings.hxx> #include <bitmaps.hlst> @@ -80,6 +81,7 @@ #include <docmodel/theme/Theme.hxx> #include <o3tl/string_view.hxx> + using ::com::sun::star::animations::XAnimationNode; using ::com::sun::star::animations::XAnimationNodeSupplier; @@ -284,7 +286,7 @@ static const SvxItemPropertySet* ImplGetMasterPagePropertySet( PageKind ePageKin { u"BackgroundFullSize"_ustr, WID_PAGE_BACKFULL, cppu::UnoType<bool>::get(), 0, 0}, { sUNO_Prop_UserDefinedAttributes,WID_PAGE_USERATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, { u"IsBackgroundDark"_ustr, WID_PAGE_ISDARK, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0}, - { u"Theme"_ustr, WID_PAGE_THEME, cppu::UnoType<util::XTheme>::get(), 0, 0}, + { sUNO_Prop_Theme, WID_PAGE_THEME, cppu::UnoType<util::XTheme>::get(), 0, 0}, // backwards compatible view of the theme for use in tests { u"ThemeUnoRepresentation"_ustr, WID_PAGE_THEME_UNO_REPRESENTATION, cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get(), 0, 0}, { u"SlideLayout"_ustr, WID_PAGE_SLIDE_LAYOUT, ::cppu::UnoType<sal_Int16>::get(), 0, 0} @@ -994,7 +996,19 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName if (uno::Reference<util::XTheme> xTheme; aValue >>= xTheme) { auto& rUnoTheme = dynamic_cast<UnoTheme&>(*xTheme); - GetPage()->getSdrPageProperties().setTheme(rUnoTheme.getTheme()); + auto pTheme = rUnoTheme.getTheme(); + auto* pPage = GetPage(); + pPage->getSdrPageProperties().setTheme(pTheme); + SdrPage* pMasterPage = nullptr; + if (pPage->IsMasterPage()) + pMasterPage = pPage; + else + { + if (pPage->TRG_HasMasterPage()) + pMasterPage = &pPage->TRG_GetMasterPage(); + } + sd::ThemeColorChanger aChanger(pMasterPage, GetModel()->GetDocShell()); + aChanger.apply(pTheme->getColorSet()); } break; diff --git a/svx/source/styles/ColorSets.cxx b/svx/source/styles/ColorSets.cxx index 61e2014a0d55..8eed74262340 100644 --- a/svx/source/styles/ColorSets.cxx +++ b/svx/source/styles/ColorSets.cxx @@ -24,6 +24,7 @@ #include <vcl/UserResourceScanner.hxx> #include <unotools/pathoptions.hxx> #include <o3tl/enumrange.hxx> +#include <o3tl/environment.hxx> #include <frozen/bits/defines.h> #include <frozen/bits/elsa_std.h> #include <frozen/unordered_map.h> @@ -142,16 +143,47 @@ ColorSets::ColorSets() init(); } +model::ColorSet const* ColorSets::getDefault() +{ + bool bForceDefault = !o3tl::getEnvironment(u"LO_FORCE_FALLBACK_DOCUMENT_THEME"_ustr).isEmpty(); + ColorSets& rSets = ColorSets::get(); + auto const* pColorSet = rSets.getColorSet(u"LibreOffice"); + if (pColorSet && !bForceDefault) + { + return pColorSet; + } + else + { + SAL_INFO("svx", "No theme found. Returning a fallback Color Set."); + static model::ColorSet aColorSet(u"Fallback Color Theme"_ustr); + aColorSet.add(model::ThemeColorType::Dark1, 0x000000); + aColorSet.add(model::ThemeColorType::Light1, 0xffffff); + aColorSet.add(model::ThemeColorType::Dark2, 0x000000); + aColorSet.add(model::ThemeColorType::Light2, 0xffffff); + aColorSet.add(model::ThemeColorType::Accent1, 0x729fcf); + aColorSet.add(model::ThemeColorType::Accent2, 0x729fcf); + aColorSet.add(model::ThemeColorType::Accent3, 0x729fcf); + aColorSet.add(model::ThemeColorType::Accent4, 0x3465a4); + aColorSet.add(model::ThemeColorType::Accent5, 0x3465a4); + aColorSet.add(model::ThemeColorType::Accent6, 0x3465a4); + aColorSet.add(model::ThemeColorType::Hyperlink, 0x0000ee); + aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x551a8b); + return &aColorSet; + } +} + ColorSets& ColorSets::get() { - static std::optional<ColorSets> sColorSet; - if (!sColorSet) - sColorSet = ColorSets(); - return *sColorSet; + static std::optional<ColorSets> sColorSets; + if (!sColorSets) + sColorSets = ColorSets(); + return *sColorSets; } void ColorSets::init() { + SAL_INFO("svx", "Initializing Color Sets."); + DocumentThemeScanner aScanner(maColorSets); if (!comphelper::IsFuzzing()) diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx index a40ad5909b46..418d1a71bea9 100644 --- a/svx/source/svdraw/svdmodel.cxx +++ b/svx/source/svdraw/svdmodel.cxx @@ -110,12 +110,10 @@ struct SdrModelImpl void initTheme() { - auto const* pColorSet = svx::ColorSets::get().getColorSet(u"LibreOffice"); - if (pColorSet) - { - std::shared_ptr<model::ColorSet> pDefaultColorSet(new model::ColorSet(*pColorSet)); - mpTheme->setColorSet(pDefaultColorSet); - } + auto const* pColorSet = svx::ColorSets::getDefault(); + assert(pColorSet); + std::shared_ptr<model::ColorSet> pDefaultColorSet(new model::ColorSet(*pColorSet)); + mpTheme->setColorSet(pDefaultColorSet); } }; diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx index e2b8ccda6eea..97cf50a4fb4a 100644 --- a/svx/source/svdraw/svdpage.cxx +++ b/svx/source/svdraw/svdpage.cxx @@ -1299,7 +1299,14 @@ void SdrPageProperties::setTheme(std::shared_ptr<model::Theme> const& pTheme) } else { - mrSdrPage.getSdrModelFromSdrPage().setTheme(pTheme); + if (mrSdrPage.TRG_HasMasterPage()) + { + mrSdrPage.TRG_GetMasterPage().getSdrPageProperties().setTheme(pTheme); + } + else + { + mrSdrPage.getSdrModelFromSdrPage().setTheme(pTheme); + } } } @@ -1308,6 +1315,9 @@ std::shared_ptr<model::Theme> const& SdrPageProperties::getTheme() const // If the page theme is available use that, else get the theme from the model if (mpTheme) return mpTheme; + + if (mrSdrPage.TRG_HasMasterPage()) + return mrSdrPage.TRG_GetMasterPage().getSdrPageProperties().getTheme(); else return mrSdrPage.getSdrModelFromSdrPage().getTheme(); } diff --git a/svx/source/theme/ThemeColorPaletteManager.cxx b/svx/source/theme/ThemeColorPaletteManager.cxx index deca9a3c54be..21c65024be35 100644 --- a/svx/source/theme/ThemeColorPaletteManager.cxx +++ b/svx/source/theme/ThemeColorPaletteManager.cxx @@ -19,26 +19,6 @@ #include <array> -namespace -{ -constexpr const std::array<const std::array<sal_Int16, 6>, 5> g_aLumMods = { - std::array<sal_Int16, 6>{ 10'000, 5'000, 6'500, 7'500, 8'500, 9'500 }, - std::array<sal_Int16, 6>{ 10'000, 1'000, 2'500, 5'000, 7'500, 9'000 }, - std::array<sal_Int16, 6>{ 10'000, 2'000, 4'000, 6'000, 7'500, 5'000 }, - std::array<sal_Int16, 6>{ 10'000, 9'000, 7'500, 5'000, 2'500, 1'000 }, - std::array<sal_Int16, 6>{ 10'000, 9'500, 8'500, 7'500, 6'500, 5'000 }, -}; - -constexpr const std::array<const std::array<sal_Int16, 6>, 5> g_aLumOffs = { - std::array<sal_Int16, 6>{ 0, 5'000, 3'500, 2'500, 1'500, 0'500 }, - std::array<sal_Int16, 6>{ 0, 9'000, 7'500, 5'000, 2'500, 1'000 }, - std::array<sal_Int16, 6>{ 0, 8'000, 6'000, 4'000, 0, 0 }, - std::array<sal_Int16, 6>{ 0, 0, 0, 0, 0, 0 }, - std::array<sal_Int16, 6>{ 0, 0, 0, 0, 0, 0 }, -}; - -} // end anonymous namespace - namespace svx { ThemeColorPaletteManager::ThemeColorPaletteManager( @@ -72,27 +52,14 @@ svx::ThemePaletteCollection ThemeColorPaletteManager::generate() Color aThemeColor = m_pColorSet->getColor(eThemeType); aThemeColorData.maBaseColor = aThemeColor; - basegfx::BColor aHSLColor = basegfx::utils::rgb2hsl(aThemeColor.getBColor()); - double aLuminanceValue = aHSLColor.getBlue() * 255.0; + size_t nIndex = model::ComplexColor::getIndexForLuminance(aThemeColor); for (size_t nEffect : { 0, 1, 2, 3, 4, 5 }) { auto& rEffect = aThemeColorData.maEffects[nEffect]; - size_t nIndex = 0; - - if (aLuminanceValue < 0.5) - nIndex = 0; // Black - else if (aLuminanceValue > 254.5) - nIndex = 4; // White - else if (aLuminanceValue < 50.5) - nIndex = 1; // Low - else if (aLuminanceValue > 203.5) - nIndex = 3; // High - else - nIndex = 2; // Middle - rEffect.mnLumOff = g_aLumOffs[nIndex][nEffect]; - rEffect.mnLumMod = g_aLumMods[nIndex][nEffect]; + rEffect.mnLumOff = model::ComplexColor::getLumOff(nIndex, nEffect); + rEffect.mnLumMod = model::ComplexColor::getLumMod(nIndex, nEffect); rEffect.maColor = aThemeColor; rEffect.maColor.ApplyLumModOff(rEffect.mnLumMod, rEffect.mnLumOff);
