diff options
-rw-r--r-- | include/oox/drawingml/color.hxx | 3 | ||||
-rw-r--r-- | oox/source/drawingml/color.cxx | 8 | ||||
-rw-r--r-- | oox/source/drawingml/fillproperties.cxx | 48 | ||||
-rw-r--r-- | sd/qa/unit/data/pptx/tdf94238.pptx | bin | 0 -> 33928 bytes | |||
-rw-r--r-- | sd/qa/unit/import-tests.cxx | 33 |
5 files changed, 86 insertions, 6 deletions
diff --git a/include/oox/drawingml/color.hxx b/include/oox/drawingml/color.hxx index 94d9050c5b42..2d33eb6e3136 100644 --- a/include/oox/drawingml/color.hxx +++ b/include/oox/drawingml/color.hxx @@ -103,6 +103,9 @@ public: /** Translates between color transformation token names and the corresponding token */ static sal_Int32 getColorTransformationToken( const OUString& sName ); + /// Compares this color with rOther. + bool equals(const Color& rOther, const GraphicHelper& rGraphicHelper, ::Color nPhClr) const; + private: /** Internal helper for getColor(). */ void setResolvedRgb( ::Color nRgb ) const; diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx index 53b77c6b01e6..b258e7c037de 100644 --- a/oox/source/drawingml/color.cxx +++ b/oox/source/drawingml/color.cxx @@ -431,6 +431,14 @@ sal_Int32 Color::getColorTransformationToken( const OUString& sName ) return XML_TOKEN_INVALID; } +bool Color::equals(const Color& rOther, const GraphicHelper& rGraphicHelper, ::Color nPhClr) const +{ + if (getColor(rGraphicHelper, nPhClr) != rOther.getColor(rGraphicHelper, nPhClr)) + return false; + + return getTransparency() == rOther.getTransparency(); +} + void Color::clearTransparence() { mnAlpha = MAX_PERCENT; diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx index b255116b4a7b..24e5e70d685d 100644 --- a/oox/source/drawingml/fillproperties.cxx +++ b/oox/source/drawingml/fillproperties.cxx @@ -154,6 +154,30 @@ const awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const R return aSizeHmm; } +/** + * Looks for a last gradient transition and possibly sets a gradient border + * based on that. + */ +void extractGradientBorderFromStops(const GradientFillProperties& rGradientProps, + const GraphicHelper& rGraphicHelper, ::Color nPhClr, + awt::Gradient& rGradient) +{ + if (rGradientProps.maGradientStops.size() <= 1) + return; + + auto it = rGradientProps.maGradientStops.rbegin(); + double fLastPos = it->first; + Color aLastColor = it->second; + ++it; + double fLastButOnePos = it->first; + Color aLastButOneColor = it->second; + if (!aLastColor.equals(aLastButOneColor, rGraphicHelper, nPhClr)) + return; + + // Last transition has the same color, we can map that to a border. + rGradient.Border = rtl::math::round((fLastPos - fLastButOnePos) * 100); +} + } // namespace void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps ) @@ -354,15 +378,28 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap, if( maGradientProps.moGradientPath.has() ) { - aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT; - // position of gradient center (limited to [30%;70%], otherwise gradient is too hidden) + // position of gradient center (limited to [30%;100%], otherwise gradient is too hidden) IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.get( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) ); sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2; - aGradient.XOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterX / PER_PERCENT, 30, 70 ); + aGradient.XOffset = getLimitedValue<sal_Int16, sal_Int32>( + nCenterX / PER_PERCENT, 30, 100); + + // Style should be radial at least when the horizontal center is at 50%. + awt::GradientStyle eCircle = aGradient.XOffset == 50 + ? awt::GradientStyle_RADIAL + : awt::GradientStyle_ELLIPTICAL; + aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) + ? eCircle + : awt::GradientStyle_RECT; + sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2; - aGradient.YOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterY / PER_PERCENT, 30, 70 ); + aGradient.YOffset = getLimitedValue<sal_Int16, sal_Int32>( + nCenterY / PER_PERCENT, 30, 100); ::std::swap( aGradient.StartColor, aGradient.EndColor ); ::std::swap( nStartTrans, nEndTrans ); + + extractGradientBorderFromStops(maGradientProps, rGraphicHelper, nPhClr, + aGradient); } else if (!maGradientProps.maGradientStops.empty()) { @@ -394,8 +431,7 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap, GradientFillProperties::GradientStopMap::const_iterator aItZ(std::prev(aGradientStops.end())); while( bSymmetric && aItA->first < aItZ->first ) { - if( aItA->second.getColor( rGraphicHelper, nPhClr ) != aItZ->second.getColor( rGraphicHelper, nPhClr ) || - aItA->second.getTransparency() != aItZ->second.getTransparency() ) + if (!aItA->second.equals(aItZ->second, rGraphicHelper, nPhClr)) bSymmetric = false; else { diff --git a/sd/qa/unit/data/pptx/tdf94238.pptx b/sd/qa/unit/data/pptx/tdf94238.pptx Binary files differnew file mode 100644 index 000000000000..cf35ecee8d12 --- /dev/null +++ b/sd/qa/unit/data/pptx/tdf94238.pptx diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index 0234733fe697..a068fad4481d 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -190,6 +190,7 @@ public: void testTdf119015(); void testTdf120028(); void testTdf120028b(); + void testTdf94238(); CPPUNIT_TEST_SUITE(SdImportTest); @@ -273,6 +274,7 @@ public: CPPUNIT_TEST(testTdf119015); CPPUNIT_TEST(testTdf120028); CPPUNIT_TEST(testTdf120028b); + CPPUNIT_TEST(testTdf94238); CPPUNIT_TEST_SUITE_END(); }; @@ -2592,6 +2594,37 @@ void SdImportTest::testTdf120028b() xDocShRef->DoClose(); } +void SdImportTest::testTdf94238() +{ + // Assert how the gradient fill of the only shape in the document is + // imported. + ::sd::DrawDocShellRef xDocShRef + = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf94238.pptx"), PPTX); + uno::Reference<drawing::XDrawPagesSupplier> xDoc(xDocShRef->GetDoc()->getUnoModel(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xDoc.is()); + + uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xPage.is()); + + uno::Reference<beans::XPropertySet> xShape(getShape(0, xPage)); + CPPUNIT_ASSERT(xShape.is()); + + awt::Gradient aGradient; + CPPUNIT_ASSERT(xShape->getPropertyValue("FillGradient") >>= aGradient); + + // Without the accompanying fix in place, this test would have failed with + // the following details: + // - aGradient.Style was awt::GradientStyle_ELLIPTICAL + // - aGradient.YOffset was 70 + // - aGradient.Border was 0 + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(100), aGradient.YOffset); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(39), aGradient.Border); + + xDocShRef->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest); CPPUNIT_PLUGIN_IMPLEMENT(); |