oox/source/vml/vmlformatting.cxx | 27 +++--- sw/qa/extras/ooxmlexport/data/tdf126533_negativeAxialAngle.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport7.cxx | 45 ++++++++++ 3 files changed, 61 insertions(+), 11 deletions(-)
New commits: commit 396ece804b3a31e4eddf56de4e557f3755331d8c Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Wed Feb 14 18:16:29 2024 -0500 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Feb 23 10:53:40 2024 +0100 related tdf#126533 vml import: fix gradient color swapping tdf#65295 already fixed one case by removing the test for degrees > 180 for the linear-equivalent gradients. Unfortunately the comment wasn't also removed, so that was confusing: removed comment. The test for degrees > 180 is not needed for the axial-equivalent case either: removed. The reason for that degrees > 180 case is likely due to negative degrees, which is a documented reason for swapping the colors: added swap if negative degrees. All the affected, existing unit tests are improved now: -tdf81345.docx: famous MS example: improved header gradient -fdo78300.docx: fontworks: hard to tell without MCGR... make CppunitTest_sw_ooxmlexport7 \ CPPUNIT_TEST_NAME=testTdf126533_negativeAxialAngle make CppunitTest_sw_ooxmlexport7 \ CPPUNIT_TEST_NAME=testTdf77219_backgroundShape Change-Id: I9f4d56375bb2cec28ffbd93df419d586da465b78 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163417 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx index 6182950973ee..f4022d0639d6 100644 --- a/oox/source/vml/vmlformatting.cxx +++ b/oox/source/vml/vmlformatting.cxx @@ -777,15 +777,18 @@ void FillModel::pushToPropMap( ShapePropertyMap& rPropMap, const GraphicHelper& sal_Int32 nVmlAngle = getIntervalValue< sal_Int32, sal_Int32 >( moAngle.value_or( 0 ), 0, 360 ); // focus of -50% or 50% is axial gradient + // so approximate anything with a similar focus by using LO's axial gradient, + // (otherwise drop the radial aspect; linear gradient becomes the closest match) if( ((-0.75 <= fFocus) && (fFocus <= -0.25)) || ((0.25 <= fFocus) && (fFocus <= 0.75)) ) { - /* According to spec, focus of 50% is outer-to-inner, + /* According to spec, a focus of positive 50% is outer-to-inner, and -50% is inner-to-outer (color to color2). - BUT: For angles >= 180 deg., the behaviour is - reversed... that's not spec'ed of course. So, - [0;180) deg. and 50%, or [180;360) deg. and -50% is - outer-to-inner in fact. */ - bool bOuterToInner = (fFocus > 0.0) == (nVmlAngle < 180); + If the angle was provided as a negative, + then the colors are also (again) reversed. */ + bool bOuterToInner = fFocus > 0.0; + if (moAngle.value_or(0) < 0) + bOuterToInner = !bOuterToInner; + // simulate axial gradient by 3-step DrawingML gradient const Color& rOuterColor = bOuterToInner ? aColor1 : aColor2; const Color& rInnerColor = bOuterToInner ? aColor2 : aColor1; @@ -797,13 +800,15 @@ void FillModel::pushToPropMap( ShapePropertyMap& rPropMap, const GraphicHelper& } else // focus of -100%, 0%, and 100% is linear gradient { - /* According to spec, focus of -100% or 100% swaps the - start and stop colors, effectively reversing the - gradient. BUT: For angles >= 180 deg., the - behaviour is reversed. This means that in this case - a focus of 0% swaps the gradient. */ + /* According to spec, a focus of -100% or 100% swaps the + start and stop colors, effectively reversing the gradient. + If the angle was provided as a negative, + then the colors are also (again) reversed. */ if( fFocus < -0.5 || fFocus > 0.5 ) nVmlAngle = (nVmlAngle + 180) % 360; + if (moAngle.value_or(0) < 0) + nVmlAngle = (nVmlAngle + 180) % 360; + // set the start and stop colors lcl_setGradientStop( aFillProps.maGradientProps.maGradientStops, 0.0, aColor1 ); lcl_setGradientStop( aFillProps.maGradientProps.maGradientStops, 1.0, aColor2 ); diff --git a/sw/qa/extras/ooxmlexport/data/tdf126533_negativeAxialAngle.docx b/sw/qa/extras/ooxmlexport/data/tdf126533_negativeAxialAngle.docx new file mode 100644 index 000000000000..98077b51a372 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf126533_negativeAxialAngle.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx index 85c4396cba0a..ef4bcb2d0000 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx @@ -9,14 +9,18 @@ #include <swmodeltestbase.hxx> +#include <com/sun/star/awt/Gradient2.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/Hatch.hpp> #include <com/sun/star/drawing/PointSequenceSequence.hpp> #include <com/sun/star/packages/zip/ZipFileAccess.hpp> #include <com/sun/star/text/XTextTable.hpp> +#include <basegfx/utils/gradienttools.hxx> #include <config_fonts.h> #include <comphelper/sequenceashashmap.hxx> #include <comphelper/processfactory.hxx> +#include <docmodel/uno/UnoGradientTools.hxx> #include <unotxdoc.hxx> #include <docsh.hxx> @@ -618,6 +622,47 @@ CPPUNIT_TEST_FIXTURE(Test, test77219) DECLARE_OOXMLEXPORT_TEST(testTdf77219_backgroundShape, "tdf77219_backgroundShape.docx") { CPPUNIT_ASSERT_EQUAL_MESSAGE("Shape is in front of the paragraph", false, getProperty<bool>(getShape(1), "Opaque")); + + // tdf#126533: gradient is purple foreground to white background (top-right to bottom-left) + uno::Reference<beans::XPropertySet> xRectangle(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xRectangle, "FillStyle")); + awt::Gradient2 aGradient = getProperty<awt::Gradient2>(xRectangle, "FillGradient"); + + basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x5f497a), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, Color(aColorStops[1].getStopColor())); + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style); + // without the fix, this was 1350 (visually the colors were reversed) + CPPUNIT_ASSERT_EQUAL(sal_Int16(3150), aGradient.Angle); +} + +DECLARE_OOXMLEXPORT_TEST(testTdf126533_negativeAxialAngle, "tdf126533_negativeAxialAngle.docx") +{ + if (isExported()) + return; + + // axiel gradient is purple foreground/lime background in the middle (top-left to bottom-right) + uno::Reference<beans::XPropertySet> xPageStyle(getStyles("PageStyles")->getByName("Standard"), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xPageStyle, "FillStyle")); + awt::Gradient2 aGradient = getProperty<awt::Gradient2>(xPageStyle, "FillGradient"); + + basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(3), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTMAGENTA, Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 0.5)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, Color(aColorStops[1].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[2].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTMAGENTA, Color(aColorStops[2].getStopColor())); + // without the fix, this was 1350 (visually the colors were reversed) + CPPUNIT_ASSERT_EQUAL(sal_Int16(450), aGradient.Angle); + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style); } DECLARE_OOXMLEXPORT_TEST(testTdf77219_foregroundShape, "tdf77219_foregroundShape.docx")