tdf#153105 PPTX export: fix "Custom position/size" background image
Map size and the 9 preset positions of the ODF background image
style "Custom position/size" to the OOXML a:stretch/a:fillRect
with the appropriate left/top/right/bottom arguments.
Note: it seems, applying a:stretch or a:tile was not mandatory,
but missing a:stretch resulted non-editable document in Office 365.
Note: the import of the PPTX mapping hasn't been implemented, yet.
Follow-up to commit e8335bac5690b6beccb5ca9b36281c89fb2f28f5
"tdf#153107 OOXML export: fix scale of tile of shape background".
Change-Id: Ie940ebc2610c5b75126da05678a04ed1552cacb3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147337
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 3613eb4..21914fb 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -281,6 +281,10 @@ public:
css::uno::Reference<css::graphic::XGraphic> const& rxGraphic,
css::awt::Size const& rSize);
void WriteXGraphicCustomPosition(css::uno::Reference<css::beans::XPropertySet> const& rXPropSet,
css::uno::Reference<css::graphic::XGraphic> const& rxGraphic,
css::awt::Size const& rSize);
void WriteLinespacing(const css::style::LineSpacing& rLineSpacing, float fFirstCharHeight);
OUString WriteXGraphicBlip(css::uno::Reference<css::beans::XPropertySet> const & rXPropSet,
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 24463a2a..d3fb8a3 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -1584,6 +1584,9 @@ void DrawingML::WriteXGraphicBlipMode(uno::Reference<beans::XPropertySet> const
case BitmapMode_STRETCH:
WriteXGraphicStretch(rXPropSet, rxGraphic);
break;
case BitmapMode_NO_REPEAT:
WriteXGraphicCustomPosition(rXPropSet, rxGraphic, rSize);
break;
default:
break;
}
@@ -1923,6 +1926,81 @@ void DrawingML::WriteXGraphicTile(uno::Reference<beans::XPropertySet> const& rXP
OUString::number(nSizeY), XML_algn, sRectanglePoint);
}
void DrawingML::WriteXGraphicCustomPosition(uno::Reference<beans::XPropertySet> const& rXPropSet,
uno::Reference<graphic::XGraphic> const& rxGraphic,
css::awt::Size const& rSize)
{
Graphic aGraphic(rxGraphic);
Size aOriginalSize(aGraphic.GetPrefSize());
const MapMode& rMapMode = aGraphic.GetPrefMapMode();
// if the original size is in pixel, convert it to mm100
if (rMapMode.GetMapUnit() == MapUnit::MapPixel)
aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize,
MapMode(MapUnit::Map100thMM));
double nSizeX = 0;
if (GetProperty(rXPropSet, "FillBitmapSizeX"))
{
mAny >>= nSizeX;
if (nSizeX <= 0)
{
if (nSizeX == 0)
nSizeX = aOriginalSize.Width();
else
nSizeX /= 100; // percentage
}
}
double nSizeY = 0;
if (GetProperty(rXPropSet, "FillBitmapSizeY"))
{
mAny >>= nSizeY;
if (nSizeY <= 0)
{
if (nSizeY == 0)
nSizeY = aOriginalSize.Height();
else
nSizeY /= 100; // percentage
}
}
if (nSizeX < 0 && nSizeY < 0 && rSize.Width != 0 && rSize.Height != 0)
{
nSizeX = rSize.Width * std::abs(nSizeX);
nSizeY = rSize.Height * std::abs(nSizeY);
}
sal_Int32 nL = 0, nT = 0, nR = 0, nB = 0;
if (GetProperty(rXPropSet, "FillBitmapRectanglePoint"))
{
sal_Int32 nWidth = (1 - (nSizeX / rSize.Width)) * 100000;
sal_Int32 nHeight = (1 - (nSizeY / rSize.Height)) * 100000;
switch (*o3tl::doAccess<RectanglePoint>(mAny))
{
case RectanglePoint_LEFT_TOP: nR = nWidth; nB = nHeight; break;
case RectanglePoint_RIGHT_TOP: nL = nWidth; nB = nHeight; break;
case RectanglePoint_LEFT_BOTTOM: nR = nWidth; nT = nHeight; break;
case RectanglePoint_RIGHT_BOTTOM: nL = nWidth; nT = nHeight; break;
case RectanglePoint_LEFT_MIDDLE: nR = nWidth; nT = nB = nHeight / 2; break;
case RectanglePoint_RIGHT_MIDDLE: nL = nWidth; nT = nB = nHeight / 2; break;
case RectanglePoint_MIDDLE_TOP: nB = nHeight; nL = nR = nWidth / 2; break;
case RectanglePoint_MIDDLE_BOTTOM: nT = nHeight; nL = nR = nWidth / 2; break;
case RectanglePoint_MIDDLE_MIDDLE: nL = nR = nWidth / 2; nT = nB = nHeight / 2; break;
default: break;
}
}
mpFS->startElementNS(XML_a, XML_stretch);
mpFS->singleElementNS(XML_a, XML_fillRect, XML_l,
sax_fastparser::UseIf(OString::number(nL), nL != 0), XML_t,
sax_fastparser::UseIf(OString::number(nT), nT != 0), XML_r,
sax_fastparser::UseIf(OString::number(nR), nR != 0), XML_b,
sax_fastparser::UseIf(OString::number(nB), nB != 0));
mpFS->endElementNS(XML_a, XML_stretch);
}
namespace
{
bool IsTopGroupObj(const uno::Reference<drawing::XShape>& xShape)
diff --git a/sd/qa/unit/data/odp/tdf153105.odp b/sd/qa/unit/data/odp/tdf153105.odp
new file mode 100644
index 0000000..a5f765f
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf153105.odp
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx
index 9616720..405170ff 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -49,6 +49,22 @@ public:
int testTdf115005_FallBack_Images(bool bAddReplacementImages);
};
CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf153105)
{
createSdImpressDoc("odp/tdf153105.odp");
save("Impress Office Open XML");
xmlDocUniquePtr pXmlDoc1 = parseExport("ppt/slides/slide1.xml");
assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:stretch/a:fillRect", "l",
"20000");
assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:stretch/a:fillRect", "t",
"30000");
assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:stretch/a:fillRect", "r",
"20000");
assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:bg/p:bgPr/a:blipFill/a:stretch/a:fillRect", "b",
"30000");
}
CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf92222)
{
createSdImpressDoc("pptx/tdf92222.pptx");