summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/export/chartexport.hxx1
-rw-r--r--oox/source/drawingml/chart/objectformatter.cxx2
-rw-r--r--oox/source/export/chartexport.cxx103
-rw-r--r--sd/qa/unit/data/odp/tdf128345_ChartArea_CG_TS.odpbin0 -> 19486 bytes
-rw-r--r--sd/qa/unit/data/odp/tdf128345_Chart_CS_TG.odpbin0 -> 16551 bytes
-rw-r--r--sd/qa/unit/data/odp/tdf128345_Legend_CS_TG_axial.odpbin0 -> 15174 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml1.cxx120
7 files changed, 220 insertions, 6 deletions
diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx
index 194e15628aef..5faaf42cb1d1 100644
--- a/include/oox/export/chartexport.hxx
+++ b/include/oox/export/chartexport.hxx
@@ -141,6 +141,7 @@ private:
void exportPlotArea( const css::uno::Reference<
css::chart::XChartDocument >& rChartDoc );
void exportFill( const css::uno::Reference< css::beans::XPropertySet >& xPropSet );
+ void exportSolidFill(const css::uno::Reference<css::beans::XPropertySet>& xPropSet);
void exportGradientFill( const css::uno::Reference< css::beans::XPropertySet >& xPropSet );
void exportBitmapFill( const css::uno::Reference< css::beans::XPropertySet >& xPropSet );
void exportHatch(const css::uno::Reference<css::beans::XPropertySet>& xPropSet);
diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx
index 326f632e84b3..fd580742c97a 100644
--- a/oox/source/drawingml/chart/objectformatter.cxx
+++ b/oox/source/drawingml/chart/objectformatter.cxx
@@ -447,7 +447,7 @@ const ShapePropertyIds spnCommonPropIds =
{
PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDashName,
PROP_LineCap, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
- PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_INVALID, PROP_FillGradientName,
+ PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillTransparenceGradientName, PROP_FillGradientName,
PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY,
PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint,
PROP_FillHatchName, PROP_FillBackground
diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx
index 5f8ea80f8c9b..db4af798c867 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -429,6 +429,14 @@ static sal_Int32 lcl_generateRandomValue()
return comphelper::rng::uniform_int_distribution(0, 100000000-1);
}
+static sal_Int32 lcl_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;
+}
+
ChartExport::ChartExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, Reference< frame::XModel > const & xModel, XmlFilterBase* pFB, DocumentType eDocumentType )
: DrawingML( std::move(pFS), pFB, eDocumentType )
, mnXmlNamespace( nXmlNamespace )
@@ -1560,12 +1568,38 @@ void ChartExport::exportManualLayout(const css::chart2::RelativePosition& rPos,
void ChartExport::exportFill( const Reference< XPropertySet >& xPropSet )
{
- if ( !GetProperty( xPropSet, "FillStyle" ) )
+ // Similar to DrawingML::WriteFill, but gradient access via name
+ if (!GetProperty( xPropSet, "FillStyle" ))
return;
- FillStyle aFillStyle( FillStyle_NONE );
- xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
+ FillStyle aFillStyle(FillStyle_NONE);
+ xPropSet->getPropertyValue("FillStyle") >>= aFillStyle;
+
+ // map full transparent background to no fill
+ if (aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, "FillTransparence" ))
+ {
+ sal_Int16 nVal = 0;
+ xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
+ if ( nVal == 100 )
+ aFillStyle = FillStyle_NONE;
+ }
+ OUString sFillTransparenceGradientName;
+ if (aFillStyle == FillStyle_SOLID
+ && (xPropSet->getPropertyValue("FillTransparenceGradientName") >>= sFillTransparenceGradientName)
+ && !sFillTransparenceGradientName.isEmpty())
+ {
+ awt::Gradient aTransparenceGradient;
+ uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
+ uno::Reference< container::XNameAccess > xTransparenceGradient(xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"), uno::UNO_QUERY);
+ uno::Any rTransparenceValue = xTransparenceGradient->getByName(sFillTransparenceGradientName);
+ rTransparenceValue >>= aTransparenceGradient;
+ if (aTransparenceGradient.StartColor == 0xffffff && aTransparenceGradient.EndColor == 0xffffff)
+ aFillStyle = FillStyle_NONE;
+ }
switch( aFillStyle )
{
+ case FillStyle_SOLID:
+ exportSolidFill(xPropSet);
+ break;
case FillStyle_GRADIENT :
exportGradientFill( xPropSet );
break;
@@ -1574,12 +1608,71 @@ void ChartExport::exportFill( const Reference< XPropertySet >& xPropSet )
break;
case FillStyle_HATCH:
exportHatch(xPropSet);
- break;
+ break;
+ case FillStyle_NONE:
+ mpFS->singleElementNS(XML_a, XML_noFill);
+ break;
default:
- WriteFill( xPropSet );
+ ;
}
}
+void ChartExport::exportSolidFill(const Reference< XPropertySet >& xPropSet)
+{
+ // Similar to DrawingML::WriteSolidFill, but gradient access via name
+ // and currently no InteropGrabBag
+ // get fill color
+ if (!GetProperty( xPropSet, "FillColor" ))
+ return;
+ sal_uInt32 nFillColor = mAny.get<sal_uInt32>();
+
+ sal_Int32 nAlpha = MAX_PERCENT;
+ if (GetProperty( xPropSet, "FillTransparence" ))
+ {
+ sal_Int32 nTransparency = 0;
+ mAny >>= nTransparency;
+ // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
+ nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
+ }
+ // OOXML has no separate transparence gradient but uses transparency in the gradient stops.
+ // So we merge transparency and color and use gradient fill in such case.
+ awt::Gradient aTransparenceGradient;
+ bool bNeedGradientFill(false);
+ OUString sFillTransparenceGradientName;
+ if ((xPropSet->getPropertyValue("FillTransparenceGradientName") >>= sFillTransparenceGradientName)
+ && !sFillTransparenceGradientName.isEmpty())
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
+ uno::Reference< container::XNameAccess > xTransparenceGradient(xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"), uno::UNO_QUERY);
+ uno::Any rTransparenceValue = xTransparenceGradient->getByName(sFillTransparenceGradientName);
+ rTransparenceValue >>= aTransparenceGradient;
+ if (aTransparenceGradient.StartColor != aTransparenceGradient.EndColor)
+ bNeedGradientFill = true;
+ else if (aTransparenceGradient.StartColor != 0)
+ nAlpha = lcl_getAlphaFromTransparenceGradient(aTransparenceGradient, true);
+ }
+ // write XML
+ if (bNeedGradientFill)
+ {
+ awt::Gradient aPseudoColorGradient;
+ aPseudoColorGradient.XOffset = aTransparenceGradient.XOffset;
+ aPseudoColorGradient.YOffset = aTransparenceGradient.YOffset;
+ aPseudoColorGradient.StartIntensity = 100;
+ aPseudoColorGradient.EndIntensity = 100;
+ aPseudoColorGradient.Angle = aTransparenceGradient.Angle;
+ aPseudoColorGradient.Border = aTransparenceGradient.Border;
+ aPseudoColorGradient.Style = aTransparenceGradient.Style;
+ aPseudoColorGradient.StartColor = nFillColor;
+ aPseudoColorGradient.EndColor = nFillColor;
+ aPseudoColorGradient.StepCount = aTransparenceGradient.StepCount;
+ mpFS->startElementNS(XML_a, XML_gradFill, XML_rotWithShape, "0");
+ WriteGradientFill(aPseudoColorGradient, aTransparenceGradient);
+ mpFS->endElementNS(XML_a, XML_gradFill);
+ }
+ else
+ WriteSolidFill(::Color(nFillColor & 0xffffff), nAlpha);
+}
+
void ChartExport::exportHatch( const Reference< XPropertySet >& xPropSet )
{
if (!xPropSet.is())
diff --git a/sd/qa/unit/data/odp/tdf128345_ChartArea_CG_TS.odp b/sd/qa/unit/data/odp/tdf128345_ChartArea_CG_TS.odp
new file mode 100644
index 000000000000..754e71d51222
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf128345_ChartArea_CG_TS.odp
Binary files differ
diff --git a/sd/qa/unit/data/odp/tdf128345_Chart_CS_TG.odp b/sd/qa/unit/data/odp/tdf128345_Chart_CS_TG.odp
new file mode 100644
index 000000000000..4c09ebb7bb34
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf128345_Chart_CS_TG.odp
Binary files differ
diff --git a/sd/qa/unit/data/odp/tdf128345_Legend_CS_TG_axial.odp b/sd/qa/unit/data/odp/tdf128345_Legend_CS_TG_axial.odp
new file mode 100644
index 000000000000..bfcd8a5dd5c9
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf128345_Legend_CS_TG_axial.odp
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx
index f1b8bcca5b6d..210337794ce9 100644
--- a/sd/qa/unit/export-tests-ooxml1.cxx
+++ b/sd/qa/unit/export-tests-ooxml1.cxx
@@ -98,6 +98,9 @@ public:
void testTdf128345GradientRadial();
void testTdf128345GradientAxial();
void testTdf134969TransparencyOnColorGradient();
+ void testTdf128345ChartArea_CG_TS();
+ void testTdf128345Chart_CS_TG();
+ void testTdf128345Legend_CS_TG_axial();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest1);
@@ -145,6 +148,9 @@ public:
CPPUNIT_TEST(testTdf128345GradientRadial);
CPPUNIT_TEST(testTdf128345GradientAxial);
CPPUNIT_TEST(testTdf134969TransparencyOnColorGradient);
+ CPPUNIT_TEST(testTdf128345ChartArea_CG_TS);
+ CPPUNIT_TEST(testTdf128345Chart_CS_TG);
+ CPPUNIT_TEST(testTdf128345Legend_CS_TG_axial);
CPPUNIT_TEST_SUITE_END();
@@ -167,6 +173,11 @@ public:
{ "a14", "http://schemas.microsoft.com/office/drawing/2010/main" },
{ "wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" },
{ "wpg", "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" },
+ // ODF
+ { "office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" },
+ { "draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"},
+ { "style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0" },
+ { "chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" },
};
for (size_t i = 0; i < SAL_N_ELEMENTS(namespaces); ++i)
{
@@ -1230,6 +1241,115 @@ void SdOOXMLExportTest1::testTdf134969TransparencyOnColorGradient()
assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", "val", "60000");
}
+void SdOOXMLExportTest1::testTdf128345ChartArea_CG_TS()
+{
+ // chart area with color gradient and solid transparency
+ // Without the patch the transparency was lost.
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_ChartArea_CG_TS.odp"), ODP);
+ utl::TempFile tempFile;
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+ // Make sure the chart area has a transparency in gradient stops in saved file.
+ xmlDocUniquePtr pXmlDoc = parseExport(tempFile, "ppt/charts/chart1.xml"); // <-- does not exists, is chart2.xml ??
+ OString sPathStart("//c:chartSpace/c:spPr/a:gradFill");
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs",2);
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", "val", "30000");
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", "val", "30000");
+
+ // Make sure chart area has transparency in the reloaded document. Currently transparency is
+ // always imported as gradient. Change test, when import creates solid transparency.
+ // I use the saved odp file for testing, because I don't know how to access the chart
+ // from the active document in a unit test.
+ utl::TempFile tempFile2;
+ xDocShRef = saveAndReload(xDocShRef.get(), ODP, &tempFile2);
+ xmlDocUniquePtr pXmlDoc2 = parseExport(tempFile2, "Object 1/styles.xml");
+ sPathStart = "//office:document-styles/office:styles";
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:start='30%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:end='30%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:border='20%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:name='msTransGradient_20_1']");
+
+ xmlDocUniquePtr pXmlDoc3 = parseExport(tempFile2, "Object 1/content.xml");
+ sPathStart = "//office:document-content/office:automatic-styles/style:style[@style:name='ch1']";
+ assertXPath(pXmlDoc3, sPathStart + "/style:graphic-properties[@draw:opacity-name='msTransGradient_20_1']");
+ sPathStart = "//office:document-content/office:body/office:chart";
+ assertXPath(pXmlDoc3, sPathStart + "/chart:chart[@chart:style-name='ch1']");
+
+ xDocShRef->DoClose();
+}
+
+void SdOOXMLExportTest1::testTdf128345Chart_CS_TG()
+{
+ // chart with solid color and transparency gradient
+ // Without the patch the transparency was lost.
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_Chart_CS_TG.odp"), ODP);
+ utl::TempFile tempFile;
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+ // Make sure the chart area has a transparency in gradient stops in saved file.
+ xmlDocUniquePtr pXmlDoc = parseExport(tempFile, "ppt/charts/chart2.xml"); // <-- why not chart1.xml ??
+ OString sPathStart("//c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill");
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs",2); //linear
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", "val", "0"); // 100% transparent
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", 0); // no element for 0% transparent
+
+ // Make sure chart has transparency in the reloaded document.
+ // I use the saved odp file for testing, because I don't know how to access the chart
+ // from the active document in a unit test.
+ utl::TempFile tempFile2;
+ xDocShRef = saveAndReload(xDocShRef.get(), ODP, &tempFile2);
+ xmlDocUniquePtr pXmlDoc2 = parseExport(tempFile2, "Object 1/styles.xml");
+ sPathStart = "//office:document-styles/office:styles";
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:style='linear']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:start='0%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:end='100%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:name='msTransGradient_20_1']");
+
+ xmlDocUniquePtr pXmlDoc3 = parseExport(tempFile2, "Object 1/content.xml");
+ sPathStart = "//office:document-content/office:automatic-styles/style:style[@style:name='ch8']";
+ assertXPath(pXmlDoc3, sPathStart + "/style:graphic-properties[@draw:opacity-name='msTransGradient_20_1']");
+ sPathStart = "//office:document-content/office:body/office:chart/chart:chart/chart:plot-area";
+ assertXPath(pXmlDoc3, sPathStart + "/chart:wall[@chart:style-name='ch8']");
+
+ xDocShRef->DoClose();
+}
+
+void SdOOXMLExportTest1::testTdf128345Legend_CS_TG_axial()
+{
+ // legend with solid color and transparency gradient
+ // Without the patch the transparency was lost.
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_Legend_CS_TG_axial.odp"), ODP);
+ utl::TempFile tempFile;
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+ // Make sure the legend has a transparency in gradient stops in saved file.
+ xmlDocUniquePtr pXmlDoc = parseExport(tempFile, "ppt/charts/chart3.xml");
+ OString sPathStart("//c:chartSpace/c:chart/c:legend/c:spPr/a:gradFill");
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs",3); // axial
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", 0); // no element for 0% transparent
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", "val", "0"); // 100% transparent
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[3]/a:srgbClr/a:alpha", 0); // no element for 0% transparent
+
+ // Make sure legend has axial transparency in the reloaded document.
+ // I use the saved odp file for testing, because I don't know how to access the chart
+ // from the active document in a unit test.
+ utl::TempFile tempFile2;
+ xDocShRef = saveAndReload(xDocShRef.get(), ODP, &tempFile2);
+ xmlDocUniquePtr pXmlDoc2 = parseExport(tempFile2, "Object 1/styles.xml");
+ sPathStart = "//office:document-styles/office:styles";
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:style='axial']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:start='0%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:end='100%']");
+ assertXPath(pXmlDoc2, sPathStart + "/draw:opacity[@draw:name='msTransGradient_20_1']");
+
+ xmlDocUniquePtr pXmlDoc3 = parseExport(tempFile2, "Object 1/content.xml");
+ sPathStart = "//office:document-content/office:automatic-styles/style:style[@style:name='ch2']";
+ assertXPath(pXmlDoc3, sPathStart + "/style:graphic-properties[@draw:opacity-name='msTransGradient_20_1']");
+ sPathStart = "//office:document-content/office:body/office:chart/chart:chart";
+ assertXPath(pXmlDoc3, sPathStart + "/chart:legend[@chart:style-name='ch2']");
+ xDocShRef->DoClose();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest1);
CPPUNIT_PLUGIN_IMPLEMENT();