diff options
author | Justin Luth <justin.luth@collabora.com> | 2023-04-11 11:19:56 -0400 |
---|---|---|
committer | Justin Luth <jluth@mail.com> | 2023-04-14 03:13:23 +0200 |
commit | 02c902bde09984a87f19ac0eb63942724056c982 (patch) | |
tree | c72c2522ffd8922b3bd154f2e3e6d7e9b31ed044 /sw | |
parent | 996d264dd4ca37c869e5109296de6ae306f740d9 (diff) |
tdf#154703 docx export framePr: merge para/frame FormatBox
Now that export knows about both frame and para border spacing,
we can remove an import hack.
When exporting the paragraph properties, not only do the direct
border settings and the paragraph styles settings apply,
but also (uniquely for framePr) do the frame properties.
The most significant property is the border spacing.
On import only the paragraph keeps the spacing
(with the purpose of keeping paragraph shading looking right)
and the frames itself has no border spacing.
[That is also good, because the frame size
is specified as the size without border spacing,
and LO does not expand the frame when borders spacing is added.]
One exception of course is if the user adds spacing during editing.
Another (theoretical) situation comes during an ODT->DOCX export.
Fortunately, both of these situations should be handled by just
adding the frame and paragraph properties together.
It is emulation, but it seems to work pretty good.
I modified the unit test from
7.1 commit 49e2bd6103669ca94d4e308fc08beed57f85c7e2
Author: Tibor Nagy on Mon Aug 10 10:51:20 2020 +0200
tdf#131420 DOCX export: fix missing border of frame
because we should _not_ have two pBdr entries,
just one, non-empty entry.
Table import and export are already a mess.
See ooxmpexort5's fdo 60957-2.docx for a great example,
and tdf104394_lostTextbox.docx is also fascinatingly complex.
Change-Id: I011100ee2790de6b8573d6a8bc99b9455f65e76d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150242
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport10.cxx | 2 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport12.cxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 59 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 8 |
4 files changed, 62 insertions, 9 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx index 4ed28d57f88d..3b9e420119a5 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx @@ -520,7 +520,7 @@ DECLARE_OOXMLEXPORT_TEST(testLibreOfficeHang, "frame-wrap-auto.docx") sal_Int32 nFrame = getProperty<sal_Int32>(getShape(1), "TopBorderDistance"); sal_Int32 nPara = getProperty<sal_Int32>(getParagraphOfText(1, xText), "TopBorderDistance"); - CPPUNIT_ASSERT_EQUAL(sal_Int32(143), nFrame + nPara); + CPPUNIT_ASSERT_EQUAL(sal_Int32(141), nFrame + nPara); // NOTE: left/right are different because of compat flag INVERT_BORDER_SPACING] nFrame = getProperty<sal_Int32>(getShape(1), "LeftBorderDistance"); nPara = getProperty<sal_Int32>(getParagraphOfText(1, xText), "LeftBorderDistance"); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx index d5ca8435b82b..d7b24692d2a7 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx @@ -1138,7 +1138,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf131420) { loadAndSave("tdf131420.docx"); xmlDocUniquePtr pXmlDocument = parseExport("word/document.xml"); - assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:pPr/w:pBdr[2]"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:pPr/w:pBdr/w:top"); } DECLARE_OOXMLEXPORT_TEST(testTdf80526_word_wrap, "tdf80526_word_wrap.docx") diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 1d9bde3f2ba4..0f34bc7b645b 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -575,16 +575,26 @@ OString DocxAttributeOutput::convertToOOXMLHoriOrientRel(sal_Int16 nOrientRel) } } -void FramePrHelper::SetFrame(ww8::Frame* pFrame) +void FramePrHelper::SetFrame(ww8::Frame* pFrame, sal_Int32 nTableDepth) { assert(!pFrame || !m_pFrame); m_pFrame = pFrame; + m_nTableDepth = nTableDepth; if (m_pFrame) { + m_bUseFrameBorders = true; m_bUseFrameBackground = true; } } +bool FramePrHelper::UseFrameBorders(sal_Int32 nTableDepth) +{ + if (!m_pFrame || m_nTableDepth < nTableDepth) + return false; + + return m_bUseFrameBorders; +} + bool FramePrHelper::UseFrameBackground() { if (!m_pFrame) @@ -1117,7 +1127,7 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT for ( const auto & pFrame : aFramePrTextbox ) { DocxTableExportContext aTableExportContext(*this); - m_aFramePr.SetFrame(pFrame.get()); + m_aFramePr.SetFrame(pFrame.get(), !m_xTableWrt ? -1 : m_tableReference.m_nTableDepth); m_rExport.SdrExporter().writeOnlyTextOfFrame(pFrame.get()); m_aFramePr.SetFrame(nullptr); } @@ -1503,7 +1513,10 @@ void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMar const Size aSize = m_aFramePr.Frame()->GetSize(); PopulateFrameProperties(&rFrameFormat, aSize); - FormatBox(rFrameFormat.GetBox()); + + // if the paragraph itself never called FormatBox, do so now + if (m_aFramePr.UseFrameBorders(!m_xTableWrt ? -1 : m_tableReference.m_nTableDepth)) + FormatBox(rFrameFormat.GetBox()); if (m_aFramePr.UseFrameBackground()) { @@ -1522,7 +1535,9 @@ void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMar } } } + // reset to true in preparation for the next paragraph in the frame + m_aFramePr.SetUseFrameBorders(true); m_aFramePr.SetUseFrameBackground(true); } @@ -4163,7 +4178,8 @@ static void impl_borders( FSHelperPtr const & pSerializer, const SvxBoxItem& rBox, const OutputBorderOptions& rOptions, std::map<SvxBoxItemLine, - css::table::BorderLine2> &rTableStyleConf ) + css::table::BorderLine2> &rTableStyleConf, + ww8::Frame* pFramePr = nullptr) { static const SvxBoxItemLine aBorders[] = { @@ -4243,6 +4259,34 @@ static void impl_borders( FSHelperPtr const & pSerializer, } } + if (pFramePr) + { + assert(rOptions.bWriteDistance && !rOptions.pDistances); + + // In addition to direct properties, and paragraph styles, + // for framePr-floated paragraphs the frame borders also affect the exported values. + + // For border spacing, there is a special situation to consider + // because a compat setting ignores left/right paragraph spacing on layout. + const SwFrameFormat& rFormat = pFramePr->GetFrameFormat(); + const SvxBoxItem& rFramePrBox = rFormat.GetBox(); + const IDocumentSettingAccess& rIDSA = rFormat.GetDoc()->getIDocumentSettingAccess(); + if (rIDSA.get(DocumentSettingId::INVERT_BORDER_SPACING) + && (*pBrd == SvxBoxItemLine::LEFT || *pBrd == SvxBoxItemLine::RIGHT)) + { + // only the frame's border spacing affects layout - so use that value instead. + nDist = rFramePrBox.GetDistance(*pBrd); + } + else + { + nDist += rFramePrBox.GetDistance(*pBrd); + } + + // Unless the user added a paragraph border, the border normally comes from the frame. + if (!pLn) + pLn = rFramePrBox.GetLine(*pBrd); + } + impl_borderLine( pSerializer, aXmlElements[i], pLn, nDist, bWriteShadow, aStyleProps ); } if (tagWritten && rOptions.bWriteTag) { @@ -9518,11 +9562,14 @@ void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox ) aStyleBorders[ SvxBoxItemLine::LEFT ] = SvxBoxItem::SvxLineToLine(pInherited->GetLeft(), false); aStyleBorders[ SvxBoxItemLine::RIGHT ] = SvxBoxItem::SvxLineToLine(pInherited->GetRight(), false); } - - impl_borders( m_pSerializer, rBox, aOutputBorderOptions, aStyleBorders ); + bool bUseFrame = m_aFramePr.UseFrameBorders(!m_xTableWrt ? -1 : m_tableReference.m_nTableDepth); + impl_borders(m_pSerializer, rBox, aOutputBorderOptions, aStyleBorders, + bUseFrame ? m_aFramePr.Frame() : nullptr); // Close the paragraph's borders tag m_pSerializer->endElementNS( XML_w, XML_pBdr ); + + m_aFramePr.SetUseFrameBorders(false); } void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFormatCol& rCol, bool bEven, SwTwips nPageSize ) diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 1e536bd11965..bf2af19a410e 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -130,16 +130,22 @@ struct TableReference class FramePrHelper { ww8::Frame* m_pFrame; + sal_Int32 m_nTableDepth; + bool m_bUseFrameBorders; bool m_bUseFrameBackground; public: FramePrHelper() : m_pFrame(nullptr) + , m_nTableDepth(0) + , m_bUseFrameBorders(true) , m_bUseFrameBackground(true) {} ww8::Frame* Frame() { return m_pFrame; } - void SetFrame(ww8::Frame* pSet); + void SetFrame(ww8::Frame* pSet, sal_Int32 nTableDepth = -1); + bool UseFrameBorders(sal_Int32 nTableDepth); + void SetUseFrameBorders(bool bSet) { m_bUseFrameBorders = bSet; } bool UseFrameBackground(); void SetUseFrameBackground(bool bSet) { m_bUseFrameBackground = bSet; } }; |