summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-07-01 21:10:01 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-07-02 09:06:37 +0200
commit599ae1151bf893491db7ad983d64c77521c3ae9d (patch)
treea3d67407d93b694c48a6660991bfc9d387a996d8
parent7d32994ad9dc45c7846664ec5ccb03bb796bb071 (diff)
tdf#125554 PPTX export: handle gradient transparency for gradient fill
Regression from commit cfc1f4ea4889f768d689a0df71519e9bcb707bc0 (oox: disable gradient fill grab-bag for PPTX, 2019-02-05), the problem was that in the past grab-bag roundtrip worked (in some cases) for this shape fill case, but true roundtrip did not. So when the commit disabled grab-bags (since their color pointers in the theme don't work in the PPTX case), a previously not implemented feature now started causing a real problem. Fix the bug by adding support for transparent linear gradients on the exports side. This means that in case the import creates both a fill gradient and a transparency gradient, then now the export creates markup based on both, not only based on the fill gradient. Change-Id: I99fa3caba2b2884c2acb7e0704bbeb0b6cffd4a4 Reviewed-on: https://gerrit.libreoffice.org/74968 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--include/oox/export/drawingml.hxx9
-rw-r--r--oox/source/export/drawingml.cxx43
-rw-r--r--sd/qa/unit/data/pptx/tdf125554.pptxbin0 -> 32967 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml1.cxx19
4 files changed, 63 insertions, 8 deletions
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index d74c82ff8b28..55279e2de69f 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -183,7 +183,7 @@ public:
void WriteColor( ::Color nColor, sal_Int32 nAlpha = MAX_PERCENT );
void WriteColor( const OUString& sColorSchemeName, const css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT );
void WriteColorTransformations( const css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT );
- void WriteGradientStop( sal_uInt16 nStop, ::Color nColor );
+ void WriteGradientStop(sal_uInt16 nStop, ::Color nColor, sal_Int32 nAlpha = MAX_PERCENT);
void WriteLineArrow( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, bool bLineStart );
void WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID );
@@ -191,7 +191,12 @@ public:
void WriteSolidFill( const OUString& sSchemeName, const css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT );
void WriteSolidFill( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet );
void WriteGradientFill( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet );
- void WriteGradientFill( css::awt::Gradient rGradient );
+
+ /// In case rXPropSet is set, it may serve as a source of gradient transparency information.
+ void WriteGradientFill(css::awt::Gradient rGradient,
+ const css::uno::Reference<css::beans::XPropertySet>& rXPropSet
+ = css::uno::Reference<css::beans::XPropertySet>());
+
void WriteGrabBagGradientFill( const css::uno::Sequence< css::beans::PropertyValue >& aGradientStops, css::awt::Gradient rGradient);
void WriteBlipOrNormalFill( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet,
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 11d900e28794..08cbf8b796fd 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -132,6 +132,17 @@ using ::css::io::XOutputStream;
using ::sax_fastparser::FSHelperPtr;
using ::sax_fastparser::FastSerializerHelper;
+namespace
+{
+/// Extracts start or end alpha information from a transparency gradient.
+sal_Int32 GetAlphaFromTransparenceGradient(const awt::Gradient& rGradient, bool bStart)
+{
+ // Our alpha is a gray color value.
+ sal_uInt8 nRed = ::Color(bStart ? rGradient.StartColor : rGradient.EndColor).GetRed();
+ // drawingML alpha is a percentage on a 0..100000 scale.
+ return (255 - nRed) * oox::drawingml::MAX_PERCENT / 255;
+}
+}
namespace oox {
namespace drawingml {
@@ -415,10 +426,10 @@ void DrawingML::WriteSolidFill( const Reference< XPropertySet >& rXPropSet )
}
}
-void DrawingML::WriteGradientStop( sal_uInt16 nStop, ::Color nColor )
+void DrawingML::WriteGradientStop(sal_uInt16 nStop, ::Color nColor, sal_Int32 nAlpha)
{
mpFS->startElementNS(XML_a, XML_gs, XML_pos, OString::number(nStop * 1000));
- WriteColor( nColor );
+ WriteColor(nColor, nAlpha);
mpFS->endElementNS( XML_a, XML_gs );
}
@@ -480,7 +491,7 @@ void DrawingML::WriteGradientFill( const Reference< XPropertySet >& rXPropSet )
else
{
mpFS->startElementNS(XML_a, XML_gradFill, XML_rotWithShape, "0");
- WriteGradientFill(aGradient);
+ WriteGradientFill(aGradient, rXPropSet);
mpFS->endElementNS( XML_a, XML_gradFill );
}
}
@@ -545,20 +556,40 @@ void DrawingML::WriteGrabBagGradientFill( const Sequence< PropertyValue >& aGrad
}
}
-void DrawingML::WriteGradientFill( awt::Gradient rGradient )
+void DrawingML::WriteGradientFill(awt::Gradient rGradient,
+ const uno::Reference<beans::XPropertySet>& rXPropSet)
{
switch( rGradient.Style )
{
default:
case awt::GradientStyle_LINEAR:
+ {
+ awt::Gradient aTransparenceGradient;
+ bool bTransparent = false;
+ if (rXPropSet.is() && GetProperty(rXPropSet, "FillTransparenceGradient"))
+ {
+ aTransparenceGradient = *o3tl::doAccess<awt::Gradient>(mAny);
+ bTransparent = true;
+ }
+
mpFS->startElementNS(XML_a, XML_gsLst);
- WriteGradientStop( 0, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
- WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
+ sal_Int32 nStartAlpha = MAX_PERCENT;
+ sal_Int32 nEndAlpha = MAX_PERCENT;
+ if (bTransparent)
+ {
+ nStartAlpha = GetAlphaFromTransparenceGradient(aTransparenceGradient, true);
+ nEndAlpha = GetAlphaFromTransparenceGradient(aTransparenceGradient, false);
+ }
+ WriteGradientStop(0, ColorWithIntensity(rGradient.StartColor, rGradient.StartIntensity),
+ nStartAlpha);
+ WriteGradientStop(100, ColorWithIntensity(rGradient.EndColor, rGradient.EndIntensity),
+ nEndAlpha);
mpFS->endElementNS( XML_a, XML_gsLst );
mpFS->singleElementNS(
XML_a, XML_lin, XML_ang,
OString::number((((3600 - rGradient.Angle + 900) * 6000) % 21600000)));
break;
+ }
case awt::GradientStyle_AXIAL:
mpFS->startElementNS(XML_a, XML_gsLst);
diff --git a/sd/qa/unit/data/pptx/tdf125554.pptx b/sd/qa/unit/data/pptx/tdf125554.pptx
new file mode 100644
index 000000000000..b78bc43fa98b
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf125554.pptx
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx
index d45b58b89504..a3df821e1bf0 100644
--- a/sd/qa/unit/export-tests-ooxml1.cxx
+++ b/sd/qa/unit/export-tests-ooxml1.cxx
@@ -109,6 +109,7 @@ public:
void testCustomXml();
void testTdf94238();
void testPictureTransparency();
+ void testTdf125554();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest1);
@@ -140,6 +141,7 @@ public:
CPPUNIT_TEST(testTdf112633);
CPPUNIT_TEST(testCustomXml);
CPPUNIT_TEST(testTdf94238);
+ CPPUNIT_TEST(testTdf125554);
CPPUNIT_TEST(testPictureTransparency);
CPPUNIT_TEST_SUITE_END();
@@ -913,6 +915,23 @@ void SdOOXMLExportTest1::testPictureTransparency()
xDocShRef->DoClose();
}
+void SdOOXMLExportTest1::testTdf125554()
+{
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/tdf125554.pptx"), PPTX);
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX);
+
+ uno::Reference<beans::XPropertySet> xShape = getShapeFromPage(0, 0, xDocShRef);
+ uno::Any aFillTransparenceGradientName
+ = xShape->getPropertyValue("FillTransparenceGradientName");
+ CPPUNIT_ASSERT(aFillTransparenceGradientName.has<OUString>());
+ // Without the accompanying fix in place, this test would have failed, i.e. the transparency of
+ // the shape has no gradient, so it looked like a solid fill instead of a gradient fill.
+ CPPUNIT_ASSERT(!aFillTransparenceGradientName.get<OUString>().isEmpty());
+
+ xDocShRef->DoClose();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest1);
CPPUNIT_PLUGIN_IMPLEMENT();