include/svx/framelink.hxx | 7 svx/source/dialog/framelink.cxx | 117 ++++++++++ sw/CppunitTest_sw_core_layout.mk | 72 ++++++ sw/Module_sw.mk | 1 sw/qa/core/layout/data/border-collapse-compat.docx |binary sw/qa/core/layout/data/table-fly-overlap.docx |binary sw/qa/core/layout/layout.cxx | 68 +++++ sw/qa/extras/ooxmlexport/ooxmlexport10.cxx | 4 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 4 sw/qa/extras/ooxmlexport/ooxmlexport4.cxx | 4 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 2 sw/source/core/layout/paintfrm.cxx | 12 + sw/source/core/layout/tabfrm.cxx | 30 ++ writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx | 34 ++ writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx |binary writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx |binary writerfilter/source/dmapper/DomainMapper.cxx | 2 writerfilter/source/dmapper/DomainMapper.hxx | 1 writerfilter/source/dmapper/GraphicImport.cxx | 12 - 19 files changed, 357 insertions(+), 13 deletions(-)
New commits: commit fa77419c66544e050a612baf027a9f927c4fe0a4 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Feb 19 18:03:59 2020 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu May 7 10:14:24 2020 +0200 sw table cell borders: add optional Word-compatible border collapsing We always compared border width and other aspects only after that, Word works with border weight according to their implementer notes. So extend svx::frame::Style to be able to collapse borders using weights and opt in for that from sw/ in case a compat mode (which is related to tables, off by default and is set by the DOC/DOCX import) is set. (cherry picked from commit e6fa52c2c371c7adc9c2c2cb18c3a8cf782cfa4b) Change-Id: I1f682789302c88a0d326c6c0263ad3007441cb24 diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx index 4c662700bec6..ee84176ce9fc 100644 --- a/include/svx/framelink.hxx +++ b/include/svx/framelink.hxx @@ -116,6 +116,7 @@ private: double mfSecn; /// Width of secondary (right or bottom) line. double mfPatternScale; /// Scale used for line pattern spacing. SvxBorderLineStyle mnType; + bool mbWordTableCell; public: /** Constructs an invisible frame style. */ @@ -129,7 +130,8 @@ private: mfDist(0.0), mfSecn(0.0), mfPatternScale(1.0), - mnType(SvxBorderLineStyle::SOLID) + mnType(SvxBorderLineStyle::SOLID), + mbWordTableCell(false) {} }; @@ -187,6 +189,9 @@ public: /** Mirrors this style (exchanges primary and secondary), if it is a double frame style. */ Style& MirrorSelf(); + /** Enables the Word-compatible Style comparison code. */ + void SetWordTableCell(bool bWordTableCell); + bool operator==( const Style& rOther) const; bool operator<( const Style& rOther) const; }; diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx index b4548c6ebed9..c8696b063e0b 100644 --- a/svx/source/dialog/framelink.cxx +++ b/svx/source/dialog/framelink.cxx @@ -267,6 +267,16 @@ Style& Style::MirrorSelf() return *this; } +void Style::SetWordTableCell(bool bWordTableCell) +{ + if (!maImplStyle) + { + implEnsureImplStyle(); + } + + maImplStyle->mbWordTableCell = bWordTableCell; +} + bool Style::operator==( const Style& rOther) const { if(!maImplStyle && !rOther.maImplStyle) @@ -290,6 +300,101 @@ bool Style::operator==( const Style& rOther) const && Type() == rOther.Type()); } +namespace +{ +/** + * Gets the weight of rStyle, according to [MS-OI29500] v20171130, 2.1.168 Part 1 Section 17.4.66, + * tcBorders (Table Cell Borders). + */ +double GetWordTableCellBorderWeight(const Style& rStyle) +{ + double fWidth = rStyle.GetWidth(); + int nBorderNumber = 0; + + // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in + // editeng/, this is the opposite of the combination of those functions. + switch (rStyle.Type()) + { + case SvxBorderLineStyle::NONE: + return 0.0; + case SvxBorderLineStyle::DOTTED: + case SvxBorderLineStyle::DASHED: + return 1.0; + case SvxBorderLineStyle::SOLID: + // single = 1 + // thick = 2 + // wave = 20 + nBorderNumber = 1; + break; + case SvxBorderLineStyle::DOUBLE: + case SvxBorderLineStyle::DOUBLE_THIN: + // double = 3 + // triple = 10 + // doubleWave = 21 + // dashDotStroked = 23 + nBorderNumber = 3; + break; + case SvxBorderLineStyle::DASH_DOT: + // dotDash = 8 + nBorderNumber = 8; + break; + case SvxBorderLineStyle::DASH_DOT_DOT: + // dotDotDash = 9 + nBorderNumber = 9; + break; + case SvxBorderLineStyle::THINTHICK_SMALLGAP: + // thinThickSmallGap = 11 + nBorderNumber = 11; + break; + case SvxBorderLineStyle::THICKTHIN_SMALLGAP: + // thickThinSmallGap = 12 + // thinThickThinSmallGap = 13 + nBorderNumber = 12; + break; + case SvxBorderLineStyle::THINTHICK_MEDIUMGAP: + // thinThickMediumGap = 14 + nBorderNumber = 14; + break; + case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP: + // thickThinMediumGap = 15 + // thinThickThinMediumGap = 16 + nBorderNumber = 15; + break; + case SvxBorderLineStyle::THINTHICK_LARGEGAP: + // thinThickLargeGap = 17 + nBorderNumber = 17; + break; + case SvxBorderLineStyle::THICKTHIN_LARGEGAP: + // thickThinLargeGap = 18 + // thinThickThinLargeGap = 19 + nBorderNumber = 18; + break; + case SvxBorderLineStyle::FINE_DASHED: + // dashSmallGap = 22 + nBorderNumber = 22; + break; + case SvxBorderLineStyle::EMBOSSED: + // threeDEmboss = 24 + nBorderNumber = 24; + break; + case SvxBorderLineStyle::ENGRAVED: + // threeDEngrave = 25 + nBorderNumber = 25; + break; + case SvxBorderLineStyle::OUTSET: + // outset = 26 + nBorderNumber = 25; + break; + case SvxBorderLineStyle::INSET: + // inset = 27 + nBorderNumber = 27; + break; + } + + return nBorderNumber * fWidth; +} +} + bool Style::operator<( const Style& rOther) const { if(!maImplStyle && !rOther.maImplStyle) @@ -298,6 +403,18 @@ bool Style::operator<( const Style& rOther) const return false; } + if (maImplStyle && maImplStyle->mbWordTableCell) + { + // The below code would first compare based on the border width, Word compares based on its + // calculated weight, do that in the compat case. + double fLW = GetWordTableCellBorderWeight(*this); + double fRW = GetWordTableCellBorderWeight(rOther); + if (!rtl::math::approxEqual(fLW, fRW)) + { + return fLW < fRW; + } + } + // different total widths -> this<rOther, if this is thinner double nLW = GetWidth(); double nRW = rOther.GetWidth(); diff --git a/sw/qa/core/layout/data/border-collapse-compat.docx b/sw/qa/core/layout/data/border-collapse-compat.docx new file mode 100644 index 000000000000..a3f29cbe8d1c Binary files /dev/null and b/sw/qa/core/layout/data/border-collapse-compat.docx differ diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx index cbea578be4cc..4c16a3bbcd97 100644 --- a/sw/qa/core/layout/layout.cxx +++ b/sw/qa/core/layout/layout.cxx @@ -43,6 +43,26 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testTableFlyOverlap) CPPUNIT_ASSERT_GREATEREQUAL(nFlyBottom, nTableTop); } +CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testBorderCollapseCompat) +{ + // Load a document with a border conflict: top cell has a dotted bottom border, bottom cell has + // a solid upper border. + load(DATA_DIRECTORY, "border-collapse-compat.docx"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDocShell* pShell = pTextDoc->GetDocShell(); + std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile(); + MetafileXmlDump aDumper; + xmlDocPtr pXmlDoc = dumpAndParse(aDumper, *xMetaFile); + + // Make sure the solid border has priority. + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 48 + // i.e. there was no single cell border with width=20, rather there were 48 border parts + // (forming a dotted border), all with width=40. + assertXPath(pXmlDoc, "//polyline[@style='solid']", "width", "20"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 60b25866d073..a53e7b249dba 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -2717,11 +2717,23 @@ void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem bool const bVert = mrTabFrame.IsVertical(); bool const bR2L = mrTabFrame.IsRightToLeft(); + bool bWordTableCell = false; + SwViewShell* pShell = rFrame.getRootFrame()->GetCurrShell(); + if (pShell) + { + const IDocumentSettingAccess& rIDSA = pShell->GetDoc()->getIDocumentSettingAccess(); + bWordTableCell = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP); + } + // no scaling needed, it's all in the primitives and the target device svx::frame::Style aL(rBoxItem.GetLeft(), 1.0); + aL.SetWordTableCell(bWordTableCell); svx::frame::Style aR(rBoxItem.GetRight(), 1.0); + aR.SetWordTableCell(bWordTableCell); svx::frame::Style aT(rBoxItem.GetTop(), 1.0); + aT.SetWordTableCell(bWordTableCell); svx::frame::Style aB(rBoxItem.GetBottom(), 1.0); + aB.SetWordTableCell(bWordTableCell); aR.MirrorSelf(); aB.MirrorSelf(); commit 50d93ff6ea05bd49d68c34664529ec66262b14b0 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Feb 17 14:35:54 2020 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu May 7 10:12:53 2020 +0200 DOCX import: don't touch the ZOrder of inline, in-shape objects 1) This is not needed: Word only supports inline "anchoring" in textboxes. 2) If the textbox has a certain ZOrder, we don't want the inline shapes to be behind the textbox. 3) This allows restoring the old assert in sw_ooxmlexport7 that was changed in commit 99847d6b3005c5444ed5a46ca578c0e40149d77c (DOCX import: fix ZOrder of inline vs anchored shapes, 2020-02-12). (cherry picked from commit 70ae12fe0b9e33633fc62cf805c261ef51fb4b59) Conflicts: sw/qa/extras/ooxmlexport/ooxmlexport7.cxx Change-Id: I817e4fb70cb789e8eb116219050fc1aeaec76667 diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx index 860d6927e505..b673c06a3d2a 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx @@ -586,7 +586,7 @@ DECLARE_OOXMLEXPORT_TEST(fdo76591, "fdo76591.docx") xmlDocPtr pXmlDoc = parseExport("word/document.xml"); if (!pXmlDoc) return; - assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "4"); + assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "3"); } DECLARE_OOXMLEXPORT_TEST(test76317_2K10, "test76317_2K10.docx") diff --git a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx index d5140f134cb3..01dd3d6ca602 100644 --- a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx +++ b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx @@ -124,6 +124,23 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineAnchoredZOrder) // i.e. the rectangle (with no name) was on top of the oval one, not the other way around. CPPUNIT_ASSERT_EQUAL(OUString("Oval 2"), xOval->getName()); } + +CPPUNIT_TEST_FIXTURE(Test, testInlineInShapeAnchoredZOrder) +{ + // This document has a textbox shape and then an inline shape inside that. + // The ZOrder of the inline shape is larger than the hosting textbox, so the image is visible. + OUString aURL + = m_directories.getURLFromSrc(DATA_DIRECTORY) + "inline-inshape-anchored-zorder.docx"; + getComponent() = loadFromDesktop(aURL); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<container::XNamed> xOval(xDrawPage->getByIndex(1), uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: Picture 1 + // - Actual : Text Box 2 + // i.e. the image was behind the textbox that was hosting it. + CPPUNIT_ASSERT_EQUAL(OUString("Picture 1"), xOval->getName()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx b/writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx new file mode 100644 index 000000000000..3792285f4849 Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx differ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 938cc59be726..97e34afb7926 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -3867,6 +3867,8 @@ bool DomainMapper::IsInHeaderFooter() const return m_pImpl->IsInHeaderFooter(); } +bool DomainMapper::IsInShape() const { return m_pImpl->IsInShape(); } + bool DomainMapper::IsInTable() const { return m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInCell(); diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx index 0913dd125814..55f9a20e0373 100644 --- a/writerfilter/source/dmapper/DomainMapper.hxx +++ b/writerfilter/source/dmapper/DomainMapper.hxx @@ -112,6 +112,7 @@ public: bool IsInHeaderFooter() const; bool IsInTable() const; bool IsStyleSheetImport() const; + bool IsInShape() const; void hasControls( const bool bSet ) { mbHasControls = bSet; } diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx index df5f644e34ba..33540be2ff72 100644 --- a/writerfilter/source/dmapper/GraphicImport.cxx +++ b/writerfilter/source/dmapper/GraphicImport.cxx @@ -288,7 +288,8 @@ public: ,m_rAligns(rAligns) ,m_rPositivePercentages(rPositivePercentages) { - if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE) + if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE + && !rDMapper.IsInShape()) { zOrder = 0; } commit 506ef593207a4ce7a463df4a7f4600b542c5cdda Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Feb 14 16:29:44 2020 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu May 7 10:10:55 2020 +0200 sw: fix handling of table vs fly overlaps in the AddVerticalFlyOffsets case When a table overlaps with a fly frame, Writer creates a fly portion inside the relevant cell frame (increasing its height), and Word shifts the table down. Both are valid approaches, but the rendering result is different in case the table has a border. So keep the default unchanged, but in case the AddVerticalFlyOffsets compat flag (set by the Word importers) is set, avoid the overlap the Word way. Note that the table frame uses the full width (available in the body) even for e.g. 50% width tables, so check for the overlap using the print area, which does not always overlap. Finally, don't always require a valid frame area definition from the fly frame: - the mentioned i#46807 bugdoc currently doesn't need that check - the fly frame area definition becomes valid only after already positioning the table, leading to an overlap Keep that check for the non-compat case, though. (cherry picked from commit fd7749fddc5a767461dfced55369af48e5a6d561) Conflicts: sw/Module_sw.mk Change-Id: I9202050befebf2efdbb5395ded6fcb52b378d8e7 diff --git a/sw/CppunitTest_sw_core_layout.mk b/sw/CppunitTest_sw_core_layout.mk new file mode 100644 index 000000000000..1801e66a713d --- /dev/null +++ b/sw/CppunitTest_sw_core_layout.mk @@ -0,0 +1,72 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,sw_core_layout)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sw_core_layout)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sw_core_layout, \ + sw/qa/core/layout/layout \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sw_core_layout, \ + comphelper \ + cppu \ + cppuhelper \ + sal \ + sfx \ + sw \ + test \ + unotest \ + utl \ + vcl \ + svt \ + tl \ + svl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sw_core_layout,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_set_include,sw_core_layout,\ + -I$(SRCDIR)/sw/inc \ + -I$(SRCDIR)/sw/source/core/inc \ + -I$(SRCDIR)/sw/source/uibase/inc \ + -I$(SRCDIR)/sw/qa/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_api,sw_core_layout,\ + udkapi \ + offapi \ + oovbaapi \ +)) + +$(eval $(call gb_CppunitTest_use_ure,sw_core_layout)) +$(eval $(call gb_CppunitTest_use_vcl,sw_core_layout)) + +$(eval $(call gb_CppunitTest_use_rdb,sw_core_layout,services)) + +$(eval $(call gb_CppunitTest_use_custom_headers,sw_core_layout,\ + officecfg/registry \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,sw_core_layout)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,sw_core_layout, \ + modules/swriter \ +)) + +$(eval $(call gb_CppunitTest_use_more_fonts,sw_core_layout)) + +# vim: set noet sw=4 ts=4: diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk index dc4f303d7a3b..ae5459d8bf89 100644 --- a/sw/Module_sw.mk +++ b/sw/Module_sw.mk @@ -110,6 +110,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\ CppunitTest_sw_core_frmedt \ CppunitTest_sw_core_txtnode \ CppunitTest_sw_core_objectpositioning \ + CppunitTest_sw_core_layout \ )) ifneq ($(DISABLE_GUI),TRUE) diff --git a/sw/qa/core/layout/data/table-fly-overlap.docx b/sw/qa/core/layout/data/table-fly-overlap.docx new file mode 100644 index 000000000000..a819e855b2eb Binary files /dev/null and b/sw/qa/core/layout/data/table-fly-overlap.docx differ diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx new file mode 100644 index 000000000000..cbea578be4cc --- /dev/null +++ b/sw/qa/core/layout/layout.cxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <swmodeltestbase.hxx> + +#include <vcl/gdimtf.hxx> +#include <comphelper/classids.hxx> +#include <tools/globname.hxx> +#include <svtools/embedhlp.hxx> + +#include <wrtsh.hxx> +#include <fmtanchr.hxx> + +static char const DATA_DIRECTORY[] = "/sw/qa/core/layout/data/"; + +/// Covers sw/source/core/layout/ fixes. +class SwCoreLayoutTest : public SwModelTestBase +{ +}; + +CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testTableFlyOverlap) +{ + // Load a document that has an image anchored in the header. + // It also has a table which has the wrap around the image. + load(DATA_DIRECTORY, "table-fly-overlap.docx"); + SwTwips nFlyTop = parseDump("//header/txt/anchored/fly/infos/bounds", "top").toInt32(); + SwTwips nFlyHeight = parseDump("//header/txt/anchored/fly/infos/bounds", "height").toInt32(); + SwTwips nFlyBottom = nFlyTop + nFlyHeight; + SwTwips nTableFrameTop = parseDump("//tab/infos/bounds", "top").toInt32(); + SwTwips nTablePrintTop = parseDump("//tab/infos/prtBounds", "top").toInt32(); + SwTwips nTableTop = nTableFrameTop + nTablePrintTop; + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater or equal than: 3579 + // - Actual : 2210 + // i.e. the table's top border overlapped with the image, even if the image's wrap mode was set + // to parallel. + CPPUNIT_ASSERT_GREATEREQUAL(nFlyBottom, nTableTop); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 42150626aa10..1674ed1a08ba 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -35,6 +35,7 @@ #include <editeng/ulspitem.hxx> #include <editeng/brushitem.hxx> #include <editeng/boxitem.hxx> +#include <basegfx/range/b1drange.hxx> #include <fmtlsplt.hxx> #include <fmtrowsplt.hxx> #include <fmtsrnd.hxx> @@ -2695,6 +2696,9 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper ); if( nYDiff > 0 ) aRectFnSet.AddBottom( aRect, -nYDiff ); + + bool bAddVerticalFlyOffsets = rIDSA.get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS); + for ( size_t i = 0; i < pPage->GetSortedObjs()->size(); ++i ) { SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i]; @@ -2722,7 +2726,7 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, bool bConsiderFly = // #i46807# - do not consider invalid // Writer fly frames. - pFly->isFrameAreaDefinitionValid() && + (pFly->isFrameAreaDefinitionValid() || bAddVerticalFlyOffsets) && // fly anchored at character pFly->IsFlyAtContentFrame() && // fly overlaps with corresponding table rectangle @@ -2766,7 +2770,29 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, { const SwFormatSurround &rSur = pFly->GetFormat()->GetSurround(); const SwFormatHoriOrient &rHori= pFly->GetFormat()->GetHoriOrient(); - if ( css::text::WrapTextMode_NONE == rSur.GetSurround() ) + bool bShiftDown = css::text::WrapTextMode_NONE == rSur.GetSurround(); + if (!bShiftDown && bAddVerticalFlyOffsets) + { + if (rSur.GetSurround() == text::WrapTextMode_PARALLEL + && rHori.GetHoriOrient() == text::HoriOrientation::NONE) + { + // We know that wrapping was requested and the table frame overlaps with + // the fly frame. Check if the print area overlaps with the fly frame as + // well (in case the table does not use all the available width). + basegfx::B1DRange aTabRange( + aRectFnSet.GetLeft(aRect) + aRectFnSet.GetLeft(getFramePrintArea()), + aRectFnSet.GetLeft(aRect) + aRectFnSet.GetLeft(getFramePrintArea()) + + aRectFnSet.GetWidth(getFramePrintArea())); + basegfx::B1DRange aFlyRange(aRectFnSet.GetLeft(aFlyRect), + aRectFnSet.GetRight(aFlyRect)); + // If it does, shift the table down. Do this only in the compat case, + // normally an SwFlyPortion is created instead that increases the height + // of the first table row. + bShiftDown = aTabRange.overlaps(aFlyRange); + } + } + + if (bShiftDown) { long nBottom = aRectFnSet.GetBottom(aFlyRect); if( aRectFnSet.YDiff( nPrtPos, nBottom ) < 0 ) commit 32750c8a1121177ea48d3e7b237a9ddc834fde38 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Feb 12 15:02:18 2020 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu May 7 09:38:21 2020 +0200 DOCX import: fix ZOrder of inline vs anchored shapes Shapes which are anchored but are not in the background should be always on top of as-char anchored shapes in OOXML terms. Writer supports a custom ZOrder even for as-char shapes, so make sure that they are always behind anchored shapes. To avoid unnecessary work, make sure that when there are multiple inline shapes, we don't pointlessly reorder them (the old vs new style of the sorting controls exactly this, what happens when two shapes have the same ZOrder, and all inline shapes have a 0 ZOrder). Adapt a few tests that used ZOrder indexes to access shapes, but the intention was to just refer to a shape: fix the index and migrate to shape names where possible. (cherry picked from commit 99847d6b3005c5444ed5a46ca578c0e40149d77c) Conflicts: sw/qa/extras/ooxmlexport/ooxmlexport7.cxx writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx Change-Id: I670e4dc2acbd2a0c6d47fe964cb5e3f2300e6848 diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx index 92d7d63aa80d..9b086540f9dd 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx @@ -487,11 +487,11 @@ DECLARE_OOXMLEXPORT_TEST(testStrict, "strict.docx") getParagraphOfText(1, xHeaderText, "This is a header."); // Picture was missing. - uno::Reference<lang::XServiceInfo> xServiceInfo(getShape(1), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo(getShapeByName("Picture 2"), uno::UNO_QUERY); CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject")); // SmartArt was missing. - xServiceInfo.set(getShape(2), uno::UNO_QUERY); + xServiceInfo.set(getShape(1), uno::UNO_QUERY); CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.drawing.GroupShape")); // Chart was missing. diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index e586a666dff4..d2765488b797 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -556,10 +556,10 @@ DECLARE_OOXMLEXPORT_TEST(testTdf119201, "tdf119201.docx") auto xShape(getShape(1)); CPPUNIT_ASSERT_MESSAGE("First shape should be visible.", getProperty<bool>(xShape, "Visible")); CPPUNIT_ASSERT_MESSAGE("First shape should be printable.", getProperty<bool>(xShape, "Printable")); - xShape = getShape(2); + xShape = getShapeByName("Rectangle 1"); CPPUNIT_ASSERT_MESSAGE("Second shape should not be visible.", !getProperty<bool>(xShape, "Visible")); CPPUNIT_ASSERT_MESSAGE("Second shape should not be printable.", !getProperty<bool>(xShape, "Printable")); - xShape = getShape(3); + xShape = getShapeByName("Oval 2"); CPPUNIT_ASSERT_MESSAGE("Third shape should be visible.", getProperty<bool>(xShape, "Visible")); CPPUNIT_ASSERT_MESSAGE("Third shape should be printable.", getProperty<bool>(xShape, "Printable")); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx index a7a1336dd480..f9c5997a42b1 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -1084,9 +1084,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf102466, "tdf102466.docx") // check content of the first page { - uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xIndexAccess = xDrawPageSupplier->getDrawPage(); - uno::Reference<beans::XPropertySet> xFrame(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xFrame(getShapeByName("Marco1"), uno::UNO_QUERY); // no border CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xFrame, "LineWidth")); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx index b673c06a3d2a..860d6927e505 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx @@ -586,7 +586,7 @@ DECLARE_OOXMLEXPORT_TEST(fdo76591, "fdo76591.docx") xmlDocPtr pXmlDoc = parseExport("word/document.xml"); if (!pXmlDoc) return; - assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "3"); + assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "4"); } DECLARE_OOXMLEXPORT_TEST(test76317_2K10, "test76317_2K10.docx") diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index ece282f437aa..f9959d21886a 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -569,7 +569,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103573, "tdf103573.docx") DECLARE_OOXMLEXPORT_TEST(testTdf106132, "tdf106132.docx") { - uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(getShapeByName("Frame1"), uno::UNO_QUERY); // This was 250, <wps:bodyPr ... rIns="0" ...> was ignored for an outer shape. CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(xShape, "TextRightDistance")); } diff --git a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx index f20694b828cc..d5140f134cb3 100644 --- a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx +++ b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx @@ -17,6 +17,7 @@ #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/XTextTablesSupplier.hpp> #include <com/sun/star/text/RelOrientation.hpp> +#include <com/sun/star/container/XNamed.hpp> #include <comphelper/processfactory.hxx> @@ -107,6 +108,22 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawShapeInlineEffect) // i.e. the layout result had less pages than expected (compared to Word). CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(273), nBottomMargin); } + +CPPUNIT_TEST_FIXTURE(Test, testInlineAnchoredZOrder) +{ + // Load a document which has two shapes: an inline one and an anchored one. The inline has no + // explicit ZOrder, the anchored one has, and it's set to a value so it's visible. + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "inline-anchored-zorder.docx"; + getComponent() = loadFromDesktop(aURL); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<container::XNamed> xOval(xDrawPage->getByIndex(1), uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: Oval 2 + // - Actual : + // i.e. the rectangle (with no name) was on top of the oval one, not the other way around. + CPPUNIT_ASSERT_EQUAL(OUString("Oval 2"), xOval->getName()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx b/writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx new file mode 100644 index 000000000000..93932c4703b7 Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx differ diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx index b69f4565fb13..df5f644e34ba 100644 --- a/writerfilter/source/dmapper/GraphicImport.cxx +++ b/writerfilter/source/dmapper/GraphicImport.cxx @@ -287,7 +287,12 @@ public: ,m_rPositionOffsets(rPositionOffsets) ,m_rAligns(rAligns) ,m_rPositivePercentages(rPositivePercentages) - {} + { + if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE) + { + zOrder = 0; + } + } void setXSize(sal_Int32 _nXSize) { @@ -358,7 +363,8 @@ public: if (zOrder >= 0) { GraphicZOrderHelper* pZOrderHelper = rDomainMapper.graphicZOrderHelper(); - xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER), uno::makeAny(pZOrderHelper->findZOrder(zOrder))); + bool bOldStyle = eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE; + xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER), uno::makeAny(pZOrderHelper->findZOrder(zOrder, bOldStyle))); pZOrderHelper->addItem(xGraphicObjectProperties, zOrder); } } @@ -898,6 +904,7 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue) { uno::Reference< beans::XPropertySet > xShapeProps(m_xShape, uno::UNO_QUERY_THROW); m_pImpl->applyMargins(xShapeProps); + m_pImpl->applyZOrder(xShapeProps); comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag")); aInteropGrabBag.update(m_pImpl->getInteropGrabBag()); xShapeProps->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag.getAsConstPropertyValueList())); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits