tdf#127806: RTF import: use shape dimensions for pib picture
If RTF shape contains pib (embedded picture) we should override
any picture sizes by values from shape. Values provided inside
\pict are ignored by MS Word; only shape values matter.
To achieve this we need to know shape dimensions so it's
calculation is moved to earlier step before internal picture
eval.
Change-Id: I99c1af7ba62c343b64b3db734b837ff101483ad8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139043
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/qa/extras/rtfexport/data/tdf127806.rtf b/sw/qa/extras/rtfexport/data/tdf127806.rtf
new file mode 100644
index 0000000..2cc165f
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf127806.rtf
@@ -0,0 +1,86 @@
{\rtf1\ansi\ansicpg1252
{\shpgrp{\*\shpinst
\shplid67
\shpleft0\shptop21\shpright11906\shpbottom16137\shpfhdr0
\shpbxpage\shpbypage\shpwr3\shpwrk0\shpfblwtxt1\shpz0
\shpwr3\shpfblwtxt1
{\sp{\sn groupLeft}{\sv 0}}
{\sp{\sn groupTop}{\sv 21}}
{\sp{\sn groupRight}{\sv 11906}}
{\sp{\sn groupBottom}{\sv 16137}}
{\sp{\sn fFlipH}{\sv 0}}
{\sp{\sn fFlipV}{\sv 0}}
{\sp{\sn posrelh}{\sv 1}}
{\sp{\sn posrelv}{\sv 1}}
{\sp{\sn fBehindDocument}{\sv 1}}
{\shp{\*\shpinst\shplid70
{\sp{\sn relLeft}{\sv 979}}
{\sp{\sn relTop}{\sv 14827}}
{\sp{\sn relRight}{\sv 10918}}
{\sp{\sn relBottom}{\sv 15176}}
{\sp{\sn fRelFlipH}{\sv 0}}
{\sp{\sn fRelFlipV}{\sv 0}}
{\sp{\sn shapeType}{\sv 0}}
{\sp{\sn rotation}{\sv 0}}
{\sp{\sn geoRight}{\sv 9939}}
{\sp{\sn geoBottom}{\sv 349}}
{\sp{\sn shapePath}{\sv 4}}
{\sp{\sn pVerticies}{\sv 8;5;(9938,0);(0,0);(0,348);(9938,348);(9938,0)}}
{\sp{\sn pSegmentInfo}{\sv 2;12;16384;45824;1;45824;1;45824;1;45824;1;45824;24577;32768}}
{\sp{\sn fFillOK}{\sv 1}}
{\sp{\sn fFilled}{\sv 1}}
{\sp{\sn fillColor}{\sv 5987168}}
{\sp{\sn fLine}{\sv 0}}{\sp{\sn lineType}{\sv 0}}
{\sp{\sn posrelh}{\sv 1}}
{\sp{\sn posrelv}{\sv 1}}
{\sp{\sn fArrowheadsOK}{\sv 1}}
{\sp{\sn fBehindDocument}{\sv 1}}
}}
{\shp{\*\shpinst\shplid72
{\sp{\sn relLeft}{\sv 830}}
{\sp{\sn relTop}{\sv 816}}
{\sp{\sn relRight}{\sv 1190}}
{\sp{\sn relBottom}{\sv 1156}}
{\sp{\sn pib}{\sv{\pict\picscalex500\picscaley9\piccropl0\piccropr0\piccropt0\piccropb0\picw1270\pich1243\picwgoal720\pichgoal705
\pngblip{\*\blipuid c0d486c26efd24459c14592d8249a32b}
89504e470d0a1a0a0000000d49484452000000300000002f0806000000a58249
c900000006624b474400ff00ff00ffa0bda793000000097048597300000ec400
000ec401952b0e1b0000041e494441546881cd984d6c1b4514c7ff33ebf5b7e3
943a6da2a290402528a5520f9168f9101c00b5a71e2ace9c7be28022242e1542
e28038708023070e1c901007041c8a904088b6082808921450212d4e9438561c
3bb1d7ebddd9791ce275b7eeaee38f59dbbfd3ee7b3b6fe6bff366e6ed322282
8bf5fb4b5764f9eb17110276310ae3a72c00a62c66e4686a87bb37246d5deefe
f0b4b2e81e9c3d0dc6af1350397800489fbbbc785740f5e7054823a9b40700d2
62307ec902821ffc700fe8c7260bb113af7cd88a2acbdf3da7b407002401e346
16d288a80e8df4f9b75f0580bb022adf3eafb20322a0be9481538aaa0c0b00d0
e7a6f2d1e3173f019a0288444475fe5bb713b0d7122a43b6489f7ff7927bbd2f
c0f8f33138d5b4aa0eecad28cc9bcac2dd83968bef461f3af7a57bbf2fa0b6f4
84aa0e9c5a383b8e4bfcd40b5f78ef3900c8da1fa754042702cc9534e0a8dd71
5a3042e2cc1b97bda6e60ca811200a3188624c45285ff4071fd8d4b28fdcf2da
94092001d457c2c97b97f8e98b1fb7db3889bd0c356ecf0d1abc712b0532b541
c304a311e20b8b6fb59b3999ff3e3c686ca7aaa1b1aafc10bf87c8e15499c726
2bed764ed6fab141021301f5e50c40e1ec3a2e9199f9bffdec9c1a8309b03762
70b6d59fb6ede8b367bff7b3730c300324586807563bd1e3173ef5b30f3403d6
5a1cd40871e1366131483eb5f0a39faf6f01448075279c5aa79d486eb2c83927
3f1f27bb38d54f50a7a443d6d497c97ef0c9231b813ec87a5fafb131a4b70f00
3c91dd09f4f523409a1ca2105ec9d00e4b1e2a05f938f521c0cac743dff7bdf0
646e2bd0d7eb0c9004acfcf0d2070078eae866a00f4e6f02c45634dc9ac7079e
9e590ff4811a3d25b37527dc9ac70f96c815837c1c2c6a751b886c06b1adab19
550f50a37c28c8c7c1e366b781444947589f8a9d90b5c274908f8327eadd0612
3bc37ffb004046f148908fb31e66208c7f3cdd20ebdb81d542d7294402702ac3
291deeebdb281d0ef27168a95a37419cb23ed4c3cb8b344ab9201f67d1e9c043
c28b1851fa008028aecd07f938d3bb1430a2050c004ea9d22185623381a5aa0b
49c019a10032c19dd2ca493f5f5733e05422801c4dfebb58ab5f5df0b377b506
a431dcdac70f91bff6ac9f9db3f8fcea418dc90ae95f670fd8ebcba7fdec9c25
1ffdeba0c6648f8380d2b4acdffff9cb9996ae2236fb5fa7c6648d36ff010092
c1bcf1deebed660e003c79e266c7b663904200602e7dfe72bb8d03003b40c038
ac0100b0f38559d92867bdb6a68093cb9d1a8e8b000806f3b7f75ff39af65368
e249dfbf5e2e63b1069ad4af7f74c97bdf9c81c757a065f6fc1a108dc72ee422
367673d63f9fb5d6c2be00a6393c73e6ba7f0b36b22a3488da376fbee35eb75e
2d9b387bcdef6112e3357800b05637e6c4e6d567008f003ef1d455dfa7c76ffc
003154af2c7e0000ff03fbe27bc1eb13f80b0000000049454e44ae426082}}}}}
}}
}
\ No newline at end of file
diff --git a/sw/qa/extras/rtfexport/rtfexport3.cxx b/sw/qa/extras/rtfexport/rtfexport3.cxx
index 055c789..2cb6b29 100644
--- a/sw/qa/extras/rtfexport/rtfexport3.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport3.cxx
@@ -491,6 +491,29 @@ CPPUNIT_TEST_FIXTURE(Test, testNegativePageBorder)
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-646), nTopBorderDistance);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf127806)
{
load(mpTestDocumentPath, "tdf127806.rtf");
CPPUNIT_ASSERT_EQUAL(2, getShapes());
CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.GroupShape"), getShape(1)->getShapeType());
auto xImage = getShape(2);
CPPUNIT_ASSERT_EQUAL(OUString("FrameShape"), xImage->getShapeType());
awt::Size aSize(xImage->getSize());
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(600), aSize.Height);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(635), aSize.Width);
reload(mpFilter, "tdf127806.rtf");
CPPUNIT_ASSERT_EQUAL(1, getShapes()); // FIXME: We lost one shape on export, that's sucks
xImage = getShape(1);
CPPUNIT_ASSERT_EQUAL(OUString("FrameShape"), xImage->getShapeType());
aSize = xImage->getSize();
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(600), aSize.Height);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(635), aSize.Width);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 5c8f058..02d5f7c 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -960,8 +960,23 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
m_aStates.top().getPicture().nHeight = aSize.Height();
}
// Wrap it in an XShape.
uno::Reference<drawing::XShape> xShape(rShape);
if (m_aStates.top().getInShape() && xShape.is())
{
awt::Size aSize = xShape->getSize();
if (aSize.Width || aSize.Height)
{
// resolvePict() is processing pib structure inside shape
// So if shape has dimensions we should use them instead of
// \picwN, \pichN, \picscalexN, \picscaleyN given with picture
m_aStates.top().getPicture().nGoalWidth = aSize.Width;
m_aStates.top().getPicture().nGoalHeight = aSize.Height;
m_aStates.top().getPicture().nScaleX = 100;
m_aStates.top().getPicture().nScaleY = 100;
}
}
// Wrap it in an XShape.
if (xShape.is())
{
uno::Reference<lang::XServiceInfo> xSI(xShape, uno::UNO_QUERY_THROW);
@@ -1061,12 +1076,6 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
* (nYExt
- (m_aStates.top().getPicture().nCropT + m_aStates.top().getPicture().nCropB)))
/ 100L;
if (m_aStates.top().getInShape())
{
// Picture in shape: it looks like pib picture, so we will stretch the picture to shape size (tdf#49893)
nXExt = m_aStates.top().getShape().getRight() - m_aStates.top().getShape().getLeft();
nYExt = m_aStates.top().getShape().getBottom() - m_aStates.top().getShape().getTop();
}
auto pXExtValue = new RTFValue(oox::drawingml::convertHmmToEmu(nXExt));
auto pYExtValue = new RTFValue(oox::drawingml::convertHmmToEmu(nYExt));
aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cx, pXExtValue);
diff --git a/writerfilter/source/rtftok/rtfsdrimport.cxx b/writerfilter/source/rtftok/rtfsdrimport.cxx
index 339ecc9..c4e0538 100644
--- a/writerfilter/source/rtftok/rtfsdrimport.cxx
+++ b/writerfilter/source/rtftok/rtfsdrimport.cxx
@@ -911,25 +911,6 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose, ShapeOrPict const shap
xPropertySet->setPropertyValue("GraphicColorMode", uno::Any(drawing::ColorMode_WATERMARK));
}
if (bPib)
{
m_rImport.resolvePict(false, xShape);
}
if (nType == ESCHER_ShpInst_PictureFrame) // picture frame
{
assert(!m_bTextFrame);
if (!bPib) // ??? not sure if the early return should be removed on else?
{
m_xShape = xShape; // store it for later resolvePict call
}
// Handle horizontal flip.
if (obFlipH && xPropertySet.is())
xPropertySet->setPropertyValue("IsMirrored", uno::Any(true));
return;
}
if (bCustom && xShape.is() && !bPib)
{
uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
@@ -1132,6 +1113,25 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose, ShapeOrPict const shap
}
}
if (bPib)
{
m_rImport.resolvePict(false, xShape);
}
if (nType == ESCHER_ShpInst_PictureFrame) // picture frame
{
assert(!m_bTextFrame);
if (!bPib) // ??? not sure if the early return should be removed on else?
{
m_xShape = xShape; // store it for later resolvePict call
}
// Handle horizontal flip.
if (obFlipH && xPropertySet.is())
xPropertySet->setPropertyValue("IsMirrored", uno::Any(true));
return;
}
if (m_rImport.isInBackground())
{
RTFSprms aAttributes;