Rebased ref, commits from common ancestor: commit 8a6a1827e046f28a1236168c30db060a16a813c4 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Aug 13 11:07:37 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:55:53 2020 +0200
sw: DOCX export: for soft-page-breaks, export continuous section breaks When a section break is produced based on layout information such as soft-page-break and follow page style, it's a bad idea to generate a page break because the break may be in a different position in Word, particularly if it was inside a fieldmark instruction. It wouldn't work that well to ignore such page breaks in MSWordExportBase::NeedTextNodeSplit() because then they would be created when reaching the next node anyway, via FindPageDesc() fall-back to layout. Unfortunately this breaks the test tdf113849_evenAndOddHeaders.odt which has a page style with follow-page-style on the first page; on re-import from DOCX, the continuous section is now no longer converted to a page break, so pages 2-3 have the wrong header/footers... this seems impossible to fix in general in the import because it doesn't know whether the continuous section break coincides with a layout page break. Arguably this worked before mostly by accident? tdf#113849 isn't about this afaics... Change the test file to have an explicit page break there, which round-trips as intended. The real fix would be adding continuous page style change to Writer i guess... Change-Id: I00ffe3971607c148a7d5c13b89afb936718611c0 diff --git a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt index d9aa0ae23541..ae9b2af14ee7 100644 Binary files a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt and b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt differ diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index a212f4e5c9b8..74f06116484a 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -619,7 +619,8 @@ sal_uLong DocxExport::ReplaceCr( sal_uInt8 ) void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) + const SwPageDesc* pNewPgDesc, + bool const bViaLayout) { // tell the attribute output that we are ready to write the section // break [has to be output inside paragraph properties] @@ -632,13 +633,12 @@ void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet, if ( pNewPgDescFormat ) { - m_pSections->AppendSection( *pNewPgDescFormat, rNd, pFormat, nLnNm ); + m_pSections->AppendSection(*pNewPgDescFormat, rNd, pFormat, nLnNm, bViaLayout); } else if ( pNewPgDesc ) { - m_pSections->AppendSection( pNewPgDesc, rNd, pFormat, nLnNm ); + m_pSections->AppendSection(pNewPgDesc, rNd, pFormat, nLnNm, bViaLayout); } - } void DocxExport::InitStyles() diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 00b908dc7efa..35e37a98ae39 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -218,7 +218,8 @@ protected: virtual void PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) override; + const SwPageDesc* pNewPgDesc, + bool bViaLayout ) override; private: /// Setup pStyles and write styles.xml diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx index 366cc18b3b0c..0e8733b48d63 100644 --- a/sw/source/filter/ww8/rtfexport.cxx +++ b/sw/source/filter/ww8/rtfexport.cxx @@ -948,7 +948,7 @@ ErrCode RtfExport::ExportDocument_Impl() void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc) + const SwPageDesc* pNewPgDesc, bool const) { const SwSectionFormat* pFormat = GetSectionFormat(rNd); const sal_uLong nLnNm = GetSectionLineNo(pSet, rNd); diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx index 055aa50ff04e..527574ad701e 100644 --- a/sw/source/filter/ww8/rtfexport.hxx +++ b/sw/source/filter/ww8/rtfexport.hxx @@ -125,8 +125,8 @@ protected: /// Get ready for a new section. void PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd, - const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc) override; + const SwFormatPageDesc* pNewPgDescFormat, const SwPageDesc* pNewPgDesc, + bool bViaLayout) override; /// Return value indicates if an inherited outline numbering is suppressed. bool DisallowInheritingOutlineNumbering(const SwFormat& rFormat) override; diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index 36026312a332..b97c6f7950d0 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -2742,7 +2742,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode ) // too. const SwPageDesc* pNextPageDesc = m_pCurrentPageDesc->GetFollow(); assert(pNextPageDesc); - PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc); + PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc, true); } } else if (!bNeedParaSplit) diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx index eb06b97195bb..e264d51a1ff2 100644 --- a/sw/source/filter/ww8/wrtw8sty.cxx +++ b/sw/source/filter/ww8/wrtw8sty.cxx @@ -1092,12 +1092,13 @@ const WW8_SepInfo* MSWordSections::CurrentSectionInfo() } void MSWordSections::AppendSection( const SwPageDesc* pPd, - const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo, bool bIsFirstParagraph ) + const SwSectionFormat*const pSectionFormat, sal_uLong const nLnNumRestartNo, + bool const bIsFirstParagraph, bool const bIsContinuous) { if (HeaderFooterWritten()) { return; // #i117955# prevent new sections in endnotes } - aSects.emplace_back( pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph ); + aSects.emplace_back(pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph, bIsContinuous); NeedsDocumentProtected( aSects.back() ); } @@ -1112,13 +1113,14 @@ void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd, } void MSWordSections::AppendSection( const SwFormatPageDesc& rPD, - const SwNode& rNd, const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo ) + const SwNode& rNd, const SwSectionFormat*const pSectionFormat, + sal_uLong const nLnNumRestartNo, bool const bIsContinuous) { if (HeaderFooterWritten()) { return; // #i117955# prevent new sections in endnotes } - WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd ); + WW8_SepInfo aI(rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd, false, bIsContinuous); aSects.push_back( aI ); NeedsDocumentProtected( aI ); @@ -1548,9 +1550,9 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt /* sprmSBkc, break code: 0 No break, 1 New column 2 New page, 3 Even page, 4 Odd page */ - sal_uInt8 nBreakCode = 2; // default start new page + sal_uInt8 nBreakCode = rSepInfo.isContinuous ? 0 : 2; // default start new page bool bOutPgDscSet = true, bLeftRightPgChain = false, bOutputStyleItemSet = false; - bool bEnsureHeaderFooterWritten = rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph; + bool bEnsureHeaderFooterWritten = (rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph) || rSepInfo.isContinuous; const SwFrameFormat* pPdFormat = &pPd->GetMaster(); if ( rSepInfo.pSectionFormat ) { diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 3f64071e2120..0e36006b9794 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -181,13 +181,16 @@ struct WW8_SepInfo sal_uLong const nLnNumRestartNo; ::boost::optional<sal_uInt16> const oPgRestartNo; bool const bIsFirstParagraph; + bool isContinuous; WW8_SepInfo( const SwPageDesc* pPD, const SwSectionFormat* pFormat, sal_uLong nLnRestart, ::boost::optional<sal_uInt16> oPgRestart = boost::none, - const SwNode* pNd = nullptr, bool bIsFirstPara = false ) + const SwNode* pNd = nullptr, bool bIsFirstPara = false, + bool bIsContinuous = false) : pPageDesc( pPD ), pSectionFormat( pFormat ), pPDNd( pNd ), nLnNumRestartNo( nLnRestart ), oPgRestartNo( oPgRestart ), bIsFirstParagraph( bIsFirstPara ) + , isContinuous(bIsContinuous) {} bool IsProtected() const; @@ -216,11 +219,13 @@ public: void AppendSection( const SwPageDesc* pPd, const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo, - bool bIsFirstParagraph = false ); + bool bIsFirstParagraph = false, + bool bIsContinuous = false); void AppendSection( const SwFormatPageDesc& rPd, const SwNode& rNd, const SwSectionFormat* pSectionFormat, - sal_uLong nLnNumRestartNo ); + sal_uLong nLnNumRestartNo, + bool bIsContinuous = false); /// Number of columns based on the most recent WW8_SepInfo. sal_uInt16 CurrentNumberOfColumns( const SwDoc &rDoc ) const; @@ -857,7 +862,8 @@ protected: virtual void PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) = 0; + const SwPageDesc* pNewPgDesc, + bool bViaLayout ) = 0; /// Return value indicates if an inherited outline numbering is suppressed. virtual bool DisallowInheritingOutlineNumbering(const SwFormat &rFormat) = 0; @@ -1124,7 +1130,8 @@ public: virtual void PrepareNewPageDesc( const SfxItemSet* pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) override; + const SwPageDesc* pNewPgDesc, + bool bViaLayout ) override; static void Out_BorderLine(ww::bytes& rO, const ::editeng::SvxBorderLine* pLine, sal_uInt16 nDist, sal_uInt16 nSprmNo, sal_uInt16 nSprmNoVer9, diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index 80efe524b472..952f6ab140db 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -457,7 +457,9 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode //section. bool bBreakSet = false; - const SwPageDesc * pPageDesc = rNd.FindPageDesc(); + size_t idx(0); + const SwPageDesc * pPageDesc = rNd.FindPageDesc(&idx); + bool isViaLayout(idx == rNd.GetIndex()); // Even if pAktPageDesc != pPageDesc ,it might be because of the different header & footer types. if (m_pCurrentPageDesc != pPageDesc) @@ -524,6 +526,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode static_cast<const SwFormatPageDesc*>(pItem)->GetRegisteredIn() != nullptr) { bBreakSet = true; + assert(!isViaLayout); bNewPageDesc = true; pPgDesc = static_cast<const SwFormatPageDesc*>(pItem); m_pCurrentPageDesc = pPgDesc->GetPageDesc(); @@ -551,6 +554,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode } } bBreakSet = true; + isViaLayout = false; if ( !bRemoveHardBreakInsideTable ) { @@ -617,7 +621,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode if ( bNewPageDesc && m_pCurrentPageDesc ) { - PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc ); + PrepareNewPageDesc(pSet, rNd, pPgDesc, m_pCurrentPageDesc, isViaLayout); } m_bBreakBefore = false; m_bPrevTextNodeIsEmpty = isTextNodeEmpty ; @@ -632,7 +636,7 @@ bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTex m_pCurrentPageDesc && m_pCurrentPageDesc != m_pCurrentPageDesc->GetFollow() ) { - PrepareNewPageDesc( pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow() ); + PrepareNewPageDesc(pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow(), true); bRet = true; } @@ -670,7 +674,8 @@ sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNo void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet, const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, - const SwPageDesc* pNewPgDesc ) + const SwPageDesc* pNewPgDesc, + bool const ) { // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding // position by the occurrences of PageDesc attributes. The construction and commit 0d28b0c9f858ab26a0f194920d5196123eb6f106 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 12 17:07:18 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:54:22 2020 +0200 sw: MS Word export: don't insert section breaks in field instructions MSWordExportBase::NeedTextNodeSplit() simply uses the soft-page-break positions to potentially insert section breaks - but now that Writer can display field instructions, it's quite silly to insert section breaks inside them. Change-Id: Ie57e6281a0287aac36984e5467920852db19a8ad diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index f7dc3e2207d2..36026312a332 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -2165,7 +2165,29 @@ bool MSWordExportBase::NeedSectionBreak( const SwNode& rNd ) const bool MSWordExportBase::NeedTextNodeSplit( const SwTextNode& rNd, SwSoftPageBreakList& pList ) const { - rNd.fillSoftPageBreakList( pList ); + SwSoftPageBreakList tmp; + rNd.fillSoftPageBreakList(tmp); + // hack: move the break behind any field marks; currently we can't hide the + // field mark instruction so the layout position is quite meaningless + IDocumentMarkAccess const& rIDMA(*rNd.GetDoc()->getIDocumentMarkAccess()); + sal_Int32 pos(-1); + for (auto const& it : tmp) + { + if (pos < it) // previous one might have skipped over it + { + pos = it; + while (auto const*const pMark = rIDMA.getFieldmarkFor(SwPosition(const_cast<SwTextNode&>(rNd), pos))) + { + if (pMark->GetMarkEnd().nNode != rNd) + { + pos = rNd.Len(); // skip everything + break; + } + pos = pMark->GetMarkEnd().nContent.GetIndex(); // no +1, it's behind the char + } + pList.insert(pos); + } + } pList.insert(0); pList.insert( rNd.GetText().getLength() ); return pList.size() > 2 && NeedSectionBreak( rNd ); commit 16d93e92085a47614f251d084f03fba517cae045 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 12 16:32:07 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:53:04 2020 +0200 sw: avoid assert when deletion starts at fieldmark end This hit assert(bSavePos && bSaveOtherPos); Tweak SwUndoSaveContent::DelContentIndex() for fieldmarks to only accept an equal end position if the start position was in range as well. (regression from 24fd14b387dca458a1b6e9415e936d26562ddb1e) Change-Id: If6c9b049193bb7f1bc39ec66d1c965512f9d6ec1 diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx index c37cffbaf9f8..bfea81a886b6 100644 --- a/sw/source/core/undo/undobj.cxx +++ b/sw/source/core/undo/undobj.cxx @@ -1097,12 +1097,14 @@ void SwUndoSaveContent::DelContentIndex( const SwPosition& rMark, if( pBkmk->IsExpanded() && *pStt <= pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() <= *pEnd ) { - if ( bSavePos || bSaveOtherPos + assert(!bSaveOtherPos); + if ( bSavePos || (*pStt < pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() < *pEnd) - || type == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK - || type == IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK - || type == IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK - || type == IDocumentMarkAccess::MarkType::DATE_FIELDMARK) + || (bMaybe + && ( type == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK + || type == IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK + || type == IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK + || type == IDocumentMarkAccess::MarkType::DATE_FIELDMARK))) { if( bMaybe ) bSavePos = true; commit 5ef139dc303d38d719f35efdedaf38b8e2e150bc Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Aug 6 14:12:04 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:51:01 2020 +0200 sw: HACK to disble DrawingML export for rotated text shapes Change-Id: I7542d0dd000b974ce490b9b81f3d85412e2409f2 diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 9a771a5f81b7..70b63e251495 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -444,9 +444,11 @@ DECLARE_OOXMLEXPORT_TEST(testRot90Fliph, "rot90-fliph.docx") // The problem was that a shape rotation of 90° got turned into 270° after roundtrip. if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) { +#if 0 assertXPath(pXmlDoc, "//a:xfrm", "flipH", "1"); // This was 16200000 (270 * 60000). assertXPath(pXmlDoc, "//a:xfrm", "rot", "5400000"); +#endif } } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx index 3218ca060469..09ff67d0fb58 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx @@ -42,6 +42,7 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt") if (!pXmlDocument) return; +#if 0 assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor" "/wp:positionH/wp:posOffset", "-480060"); assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor" @@ -60,13 +61,14 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt") "/wp:positionV/wp:posOffset", "1080135"); assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor" "/wp:positionV", "relativeFrom", "page"); +#endif // now test text rotation -> VML writing direction - assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top"); // text wrap -> VML - assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/w10:wrap", "type", "none"); // vertical alignment -> VML - OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style"); + OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape", "style"); CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1); } diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx index 7cacc4eb3173..b86c64daeb24 100644 --- a/sw/source/filter/ww8/docxsdrexport.cxx +++ b/sw/source/filter/ww8/docxsdrexport.cxx @@ -16,6 +16,7 @@ #include <editeng/opaqitem.hxx> #include <editeng/boxitem.hxx> #include <svx/svdogrp.hxx> +#include <svx/svdotext.hxx> #include <oox/token/namespaces.hxx> #include <textboxhelper.hxx> #include <fmtanchr.hxx> @@ -983,6 +984,24 @@ bool DocxSdrExport::Impl::isSupportedDMLShape(const uno::Reference<drawing::XSha return true; } +bool lcl_isRotatedText(SdrObject const& rShape, uno::Reference<drawing::XShape> const& xShape) +{ + uno::Reference<beans::XPropertySet> const xProps(xShape, uno::UNO_QUERY); + sal_Int32 nRotateAngle = sal_Int32(); + if (!dynamic_cast<SdrTextObj const*>(&rShape) + || !xProps->getPropertySetInfo()->hasPropertyByName("RotateAngle") + || !(xProps->getPropertyValue("RotateAngle") >>= nRotateAngle)) + { + return false; + } + if (nRotateAngle == 9000) // is it enough, or should it be any angle != 0? + { + SAL_INFO("sw.ww8", "HACK: forcing rotated shape to VML only"); + return true; + } + return false; +} + void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat& rFrameFormat, int nAnchorId) { @@ -1001,6 +1020,7 @@ void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do. // A common service created in util to check for VML shapes which are allowed to have textbox in content if ((msfilter::util::HasTextBoxContent(eShapeType)) && Impl::isSupportedDMLShape(xShape) + && !lcl_isRotatedText(*sdrObj, xShape) && (!bDMLAndVMLDrawingOpen || lcl_isLockedCanvas(xShape))) // Locked canvas is OK inside DML { m_pImpl->getSerializer()->startElementNS(XML_mc, XML_AlternateContent); commit e6e8d7cdef5d3d1448f13a9dc68340bd92afc37a Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Aug 7 15:50:12 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:51:00 2020 +0200 oox: VML export: convert ESCHER_Prop_AnchorText to v-text-anchor Change-Id: I903cac8d7b02138680613b5a1b6dab4b1c448158 diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index 555796c47a9c..ee93cf32bd27 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -430,6 +430,47 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle& bAlreadyWritten[ ESCHER_Prop_WrapText ] = true; break; + case ESCHER_Prop_AnchorText: // 135 + { + char const* pValue(nullptr); + switch (opt.nPropValue) + { + case ESCHER_AnchorTop: + pValue = "top"; + break; + case ESCHER_AnchorMiddle: + pValue = "middle"; + break; + case ESCHER_AnchorBottom: + pValue = "bottom"; + break; + case ESCHER_AnchorTopCentered: + pValue = "top-center"; + break; + case ESCHER_AnchorMiddleCentered: + pValue = "middle-center"; + break; + case ESCHER_AnchorBottomCentered: + pValue = "bottom-center"; + break; + case ESCHER_AnchorTopBaseline: + pValue = "top-baseline"; + break; + case ESCHER_AnchorBottomBaseline: + pValue = "bottom-baseline"; + break; + case ESCHER_AnchorTopCenteredBaseline: + pValue = "top-center-baseline"; + break; + case ESCHER_AnchorBottomCenteredBaseline: + pValue = "bottom-center-baseline"; + break; + } + m_ShapeStyle.append(";v-text-anchor:"); + m_ShapeStyle.append(pValue); + } + break; + case ESCHER_Prop_txflTextFlow: // 136 { // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx index 6bc298fa559a..3218ca060469 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx @@ -65,7 +65,9 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt") assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top"); // text wrap -> VML assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none"); - + // vertical alignment -> VML + OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style"); + CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1); } CPPUNIT_PLUGIN_IMPLEMENT(); commit bca79d0e57a9c9bb3474668147310f7d642465ec Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Aug 7 15:45:25 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:51:00 2020 +0200 oox: VML export: produce bottom-to-top in a better way Replace code added in 090c61eb93db4302d4565d5f11f7673190835fdb with something that uses the already generated ESCHER property; this lets a warning about the unhandled property disappear too. Change-Id: Ieed83dd8e17e92eea9901124fce5e6da2a17196a diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx index 83b5b91c0d41..7c2d3a62da6f 100644 --- a/include/oox/export/vmlexport.hxx +++ b/include/oox/export/vmlexport.hxx @@ -99,6 +99,9 @@ class OOX_DLLPUBLIC VMLExport : public EscherEx /// Remember style, the most important shape attribute ;-) OStringBuffer m_ShapeStyle; + /// style for textbox + OStringBuffer m_TextboxStyle; + /// Remember the generated shape id. OString m_sShapeId; diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index 6fcc83a66da6..555796c47a9c 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -430,6 +430,28 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle& bAlreadyWritten[ ESCHER_Prop_WrapText ] = true; break; + case ESCHER_Prop_txflTextFlow: // 136 + { + // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape + assert(m_TextboxStyle.isEmpty()); + switch (opt.nPropValue) + { + case ESCHER_txflHorzN: + m_TextboxStyle.append("layout-flow:horizontal"); + break; + case ESCHER_txflTtoBA: + m_TextboxStyle.append("layout-flow:vertical"); + break; + case ESCHER_txflBtoT: + m_TextboxStyle.append("mso-layout-flow-alt:bottom-to-top"); + break; + default: + assert(false); // unimplemented in escher export + break; + } + } + break; + // coordorigin case ESCHER_Prop_geoLeft: // 320 case ESCHER_Prop_geoTop: // 321 @@ -1345,6 +1367,8 @@ sal_Int32 VMLExport::StartShape() // start of the shape m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) ); + OString const textboxStyle(m_TextboxStyle.makeStringAndClear()); + // now check if we have some editeng text (not associated textbox) and we have a text exporter registered const SdrTextObj* pTxtObj = dynamic_cast<const SdrTextObj*>( m_pSdrObject ); if (pTxtObj && m_pTextExport && msfilter::util::HasTextBoxContent(m_nShapeType) && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject)) @@ -1369,19 +1393,11 @@ sal_Int32 VMLExport::StartShape() if( pParaObj ) { - uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY); sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList(); sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList); - if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle")) + if (!textboxStyle.isEmpty()) { - sal_Int32 nTextRotateAngle = sal_Int32(); - if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle) - { - if (nTextRotateAngle == 9000) - { - pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top"); - } - } + pTextboxAttrList->add(XML_style, textboxStyle); } // this is reached only in case some text is attached to the shape commit 86282cea5003579a82585a8e7e7dc5fe783db5c0 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Aug 7 15:26:48 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:51:00 2020 +0200 filter: MSO export: convert TextWrap property to Escher_Wrap* There's a paucity of working wrapping modes in Escher unfortunately. Change-Id: Ibaf99c3249a6492dc129f9c9b5707778038f9a4c diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx index f04043e9156a..a2071237deb7 100644 --- a/filter/source/msfilter/escherex.cxx +++ b/filter/source/msfilter/escherex.cxx @@ -66,6 +66,7 @@ #include <com/sun/star/drawing/FlagSequence.hpp> #include <com/sun/star/drawing/PolygonFlags.hpp> #include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/text/WrapTextMode.hpp> #include <com/sun/star/drawing/TextVerticalAdjust.hpp> #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> @@ -699,6 +700,10 @@ void EscherPropertyContainer::CreateTextProperties( bool bWordWrap ( false ); bool bAutoGrowSize ( false ); + uno::Any aTextWrap; + + EscherPropertyValueHelper::GetPropertyValue(aTextWrap, rXPropSet, "TextWrap", true); + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) ) aAny >>= eWM; if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) ) @@ -837,6 +842,21 @@ void EscherPropertyContainer::CreateTextProperties( nTextAttr |= 0x20002; } } + + if (aTextWrap.hasValue()) + { // explicit text wrap overrides whatever was inferred previously + switch (aTextWrap.get<text::WrapTextMode>()) + { + case text::WrapTextMode_THROUGH: + eWrapMode = ESCHER_WrapNone; + break; + // in theory there are 3 more Escher_Wrap, but [MS-ODRAW] says they are useless + default: + eWrapMode = ESCHER_WrapSquare; + break; + } + } + AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 ); AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 ); AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 ); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx index 51e4c6b63b96..6bc298fa559a 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx @@ -63,6 +63,8 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt") // now test text rotation -> VML writing direction assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top"); + // text wrap -> VML + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none"); } commit 08301ac462a200ab89124f1d2e36f220f88c4661 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Aug 7 16:41:18 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:51:00 2020 +0200 sw: register w10 prefix Change-Id: I1ca9c3c7c4f36b666ee7d17967b80fdaa7004874 diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx index 38f8e95a4a40..d62b92b58fc0 100644 --- a/sw/qa/inc/swmodeltestbase.hxx +++ b/sw/qa/inc/swmodeltestbase.hxx @@ -962,6 +962,7 @@ protected: xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main")); xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart")); xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("o"), BAD_CAST("urn:schemas-microsoft-com:office:office")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w10"), BAD_CAST("urn:schemas-microsoft-com:office:word")); // odt xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0")); xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("style"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:style:1.0")); commit 086e0e4a211a564122f527e329fede2a8e315cdc Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Aug 6 14:11:38 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:50:59 2020 +0200 oox: VML export: for rotated text shape, produce bottom-to-top This is for shapes that fail the lcl_isTextBox() check in VMLExport::StartShape(), they can be rotated too but with a different property than the "TextPreRotateAngle" that is used in VMLExport::EndShape(). Change-Id: I530aae8b7138f47bae8434e205632f5f4adbb231 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100249 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> (cherry picked from commit 090c61eb93db4302d4565d5f11f7673190835fdb) diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index 98f3243e5461..6fcc83a66da6 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -1369,8 +1369,23 @@ sal_Int32 VMLExport::StartShape() if( pParaObj ) { + uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY); + sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList(); + sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList); + if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle")) + { + sal_Int32 nTextRotateAngle = sal_Int32(); + if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle) + { + if (nTextRotateAngle == 9000) + { + pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top"); + } + } + } + // this is reached only in case some text is attached to the shape - m_pSerializer->startElementNS(XML_v, XML_textbox); + m_pSerializer->startElementNS(XML_v, XML_textbox, xTextboxAttrList); m_pTextExport->WriteOutliner(*pParaObj); m_pSerializer->endElementNS(XML_v, XML_textbox); if( bOwnParaObj ) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx index 634215adab08..51e4c6b63b96 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx @@ -60,6 +60,10 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt") "/wp:positionV/wp:posOffset", "1080135"); assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor" "/wp:positionV", "relativeFrom", "page"); + + // now test text rotation -> VML writing direction + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top"); + } CPPUNIT_PLUGIN_IMPLEMENT(); commit c405fd0c1ba2358bc55b7ee5ec7c8b7df49de2a8 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Aug 4 19:09:38 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:50:59 2020 +0200 tdf#135464 sw: avoid invalid combinations of HoriOrientRelation and FLY_AT_PAGE ... when using Anchor->To Page context menu. For shapes, in SwDoc::ChgAnchor() and for sw flys in SwDoc::SetFlyFrameAnchor(). Change-Id: I7d747b2558ef69df99636ea0fb0409deb461a79a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100131 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> (cherry picked from commit 1de2b0d3234462b488db54d36ebc17e2b579b0f0) diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx index 4451115905a8..cc3b858028c2 100644 --- a/sw/source/core/doc/docfly.cxx +++ b/sw/source/core/doc/docfly.cxx @@ -372,6 +372,7 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo pItem = nullptr; SwFormatHoriOrient aOldH( rFormat.GetHoriOrient() ); + bool bPutOldH(false); if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem || aOldH.GetPos() == static_cast<const SwFormatHoriOrient*>(pItem)->GetPos() )) @@ -386,6 +387,22 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo aOldH.SetRelationOrient( pH->GetRelationOrient() ); } aOldH.SetPos( nPos ); + bPutOldH = true; + } + if (nNew == RndStdIds::FLY_AT_PAGE) + { + sal_Int16 nRelOrient(pItem + ? static_cast<const SwFormatHoriOrient*>(pItem)->GetRelationOrient() + : aOldH.GetRelationOrient()); + if (sw::GetAtPageRelOrientation(nRelOrient, false)) + { + SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor"); + aOldH.SetRelationOrient(nRelOrient); + bPutOldH = true; + } + } + if (bPutOldH) + { rSet.Put( aOldH ); } @@ -915,6 +932,17 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList, // of attributes (method call <SetAttr(..)>) takes care of the // invalidation of the object position. SetAttr( aNewAnch, *pContact->GetFormat() ); + if (aNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE) + { + SwFormatHoriOrient item(pContact->GetFormat()->GetHoriOrient()); + sal_Int16 nRelOrient(item.GetRelationOrient()); + if (sw::GetAtPageRelOrientation(nRelOrient, false)) + { + SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor"); + item.SetRelationOrient(text::RelOrientation::PAGE_FRAME); + SetAttr(item, *pContact->GetFormat()); + } + } if ( _bPosCorr ) { // #i33313# - consider not connected 'virtual' drawing diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx index 079468fdf062..f3813192c928 100644 --- a/sw/source/core/layout/anchoreddrawobject.cxx +++ b/sw/source/core/layout/anchoreddrawobject.cxx @@ -719,7 +719,10 @@ void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrame* _pNewAnchorFram nVertRelPos = aObjRect.Top() - aAnchorPos.Y(); } - GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) ); + GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, + GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE + ? text::RelOrientation::PAGE_FRAME + : text::RelOrientation::FRAME ) ); GetFrameFormat().SetFormatAttr( SwFormatVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) ); } commit b8c028f8a471ed30f409b51c5765fbb91b5ef22c Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Aug 4 18:56:08 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:50:59 2020 +0200 tdf#135464 sw: ODT->DOCX: fix positioning of at-page shapes and frames Exporting at-page anchored flys to DOCX can result in wrong positions, because DocxSdrExport::startDMLAnchorInline() converts text::RelOrientation::FRAME to relativeFrom="column", i.e. the margin, but sw displays it as relative to the page. In fact at-page and FRAME is an invalid combination according to the table in ODF 1.3, 20.298 style:horizontal-pos, the paragraph and character relations are not valid for page-anchored flys. Since there are lots of ODT files with this invalid combination, try to fix it on import, in SwXFrame and SwXShape. Funnily, SwXShape is attached before the properties are set, while SwXFrame is attached after the properties are set. The anchor frame for at-page is always a SwPageFrame. Unfortunately there is a case where PRINT_AREA and PAGE_PRINT_AREA differ, namely the CalcClipRect() only handles PRINT_AREA so it will crop to the right margin with that but not with PAGE_PRINT_AREA, so don't map this value. Change-Id: I4d5f7f87d045ac4539b9170e55c34d4afe801f4d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100130 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> (cherry picked from commit 12645900dece0a9aa0661fee796c27f672217977) diff --git a/sw/inc/fmtornt.hxx b/sw/inc/fmtornt.hxx index 24ffdc907e26..d0bea643f980 100644 --- a/sw/inc/fmtornt.hxx +++ b/sw/inc/fmtornt.hxx @@ -108,6 +108,12 @@ inline const SwFormatVertOrient &SwFormat::GetVertOrient(bool bInP) const inline const SwFormatHoriOrient &SwFormat::GetHoriOrient(bool bInP) const { return m_aSet.GetHoriOrient(bInP); } +namespace sw { + + bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintArea); + +} + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt new file mode 100644 index 000000000000..fce84f93e945 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns :config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="ur n:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:font-face-decls> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"/> + <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + </style:style> + <style:style style:name="P2" style:family="paragraph"> + <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/> + <style:paragraph-properties style:writing-mode="lr-tb"/> + <style:text-properties fo:font-size="11pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Arial" fo:font-size="7pt" fo:language="de" fo:country="DE" style:font-name-asian="Times New Roman" style:font-size-asian="7pt" style:font-name-complex="Arial" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="gr1" style:family="graphic"> + <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" draw:auto-grow-width="false" fo:padding-top="0.254cm" fo:padding-bottom="0.254cm" fo:padding-left="0.127cm" fo:padding-right="0.127cm" fo:wrap-option="wrap" draw:shadow="hidden" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="page" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" style:flow-with-text="false"/> + <style:paragraph-properties style:writing-mode="lr-tb"/> + </style:style> + <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics"> + <style:graphic-properties style:horizontal-pos="from-left" style:horizontal-rel="paragraph" style:vertical-pos="from-top" style:vertical-rel="page" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text> + <draw:frame text:anchor-type="page" text:anchor-page-number="1" draw:z-index="0" draw:name="Shape1" draw:style-name="gr1" draw:text-style-name="P2" svg:width="5.896cm" svg:height="0.957cm" draw:transform="rotate (1.5707963267949) translate (1.13418055555556cm 26.0579305555556cm)"> + <draw:text-box> + <text:p text:style-name="P1"><text:span text:style-name="T1"><text:s/></text:span><text:span text:style-name="T1">Foo</text:span></text:p> + </draw:text-box> + </draw:frame><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="page" text:anchor-page-number="1" svg:width="0.67cm" svg:height="0.67cm" draw:z-index="0"><draw:image draw:mime-type="image/png" svg:x="2cm" svg:y="3cm"> + <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAAXNSR0IArs4c6QAAAAZiS0dE + AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJBhI0A6HXrrIAAABl + SURBVDjLY/z//z8DtQATMYokl7D8p4phMIOIMZCJFBcRMpCJVK/hM5CJnDDCJc9EbmBjU8dE + jkG41DPhM+h5zB9GfHx0fTgjAJtGfOIMDAwMLMQoItZAJgYqglHDhpNhjNQsaQHF4y3hS/bS + HgAAAABJRU5ErkJggg== + </office:binary-data> + </draw:image> + </draw:frame> + <text:p text:style-name="Standard"/> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx index dedad4d00eab..634215adab08 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx @@ -33,6 +33,35 @@ DECLARE_OOXMLEXPORT_TEST(testTdf133334_followPgStyle, "tdf133334_followPgStyle.o CPPUNIT_ASSERT_EQUAL(2, getPages()); } +DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt") +{ + // invalid combination of at-page anchor and horizontal-rel="paragraph" + // caused relativeFrom="column" instead of relativeFrom="page" + + xmlDocPtr pXmlDocument = parseExport("word/document.xml"); + if (!pXmlDocument) + return; + + assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor" + "/wp:positionH/wp:posOffset", "-480060"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor" + "/wp:positionH", "relativeFrom", "page"); + assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor" + "/wp:positionV/wp:posOffset", "8147685"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor" + "/wp:positionV", "relativeFrom", "page"); + + // same for sw + assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor" + "/wp:positionH/wp:posOffset", "720090"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor" + "/wp:positionH", "relativeFrom", "page"); + assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor" + "/wp:positionV/wp:posOffset", "1080135"); + assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor" + "/wp:positionV", "relativeFrom", "page"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx index 79235781896d..18700e9b2eb4 100644 --- a/sw/source/core/layout/atrfrm.cxx +++ b/sw/source/core/layout/atrfrm.cxx @@ -98,6 +98,39 @@ using namespace ::com::sun::star; +namespace sw { + +bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintArea) +{ + switch (rOrientation) + { + case text::RelOrientation::CHAR: + case text::RelOrientation::FRAME: + rOrientation = text::RelOrientation::PAGE_FRAME; + return true; + case text::RelOrientation::PRINT_AREA: + if (isIgnorePrintArea) + { + return false; + } + else + { + rOrientation = text::RelOrientation::PAGE_PRINT_AREA; + return true; + } + case text::RelOrientation::FRAME_LEFT: + rOrientation = text::RelOrientation::PAGE_LEFT; + return true; + case text::RelOrientation::FRAME_RIGHT: + rOrientation = text::RelOrientation::PAGE_RIGHT; + return true; + default: + return false; + } +} + +} // namespace sw + SfxPoolItem* SwFormatLineNumber::CreateDefault() { return new SwFormatLineNumber; } static sal_Int16 lcl_IntToRelation(const uno::Any& rVal) diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx index a94255c55408..d1b058fa49a2 100644 --- a/sw/source/core/unocore/unodraw.cxx +++ b/sw/source/core/unocore/unodraw.cxx @@ -1227,6 +1227,21 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a } } } + else if (pEntry->nWID == RES_HORI_ORIENT + && pEntry->nMemberId == MID_HORIORIENT_RELATION + && aSet.Get(RES_ANCHOR).GetAnchorId() == RndStdIds::FLY_AT_PAGE) + { + uno::Any value(aValue); + sal_Int16 nRelOrient(text::RelOrientation::PAGE_FRAME); + aValue >>= nRelOrient; + if (sw::GetAtPageRelOrientation(nRelOrient, true)) + { + SAL_WARN("sw.core", "SwXShape: fixing invalid horizontal RelOrientation for at-page anchor"); + value <<= nRelOrient; + } + m_pPropSet->setPropertyValue( *pEntry, value, aSet ); + pFormat->SetFormatAttr(aSet); + } else { m_pPropSet->setPropertyValue( *pEntry, aValue, aSet ); diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index e2e5c9411715..0636d530662c 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -2749,6 +2749,19 @@ void SwXFrame::attachToRange(uno::Reference<text::XTextRange> const& xTextRange, aAnchor.SetAnchor( aPam.GetPoint() ); aFrameSet.Put(aAnchor); } + + if (eAnchorId == RndStdIds::FLY_AT_PAGE) + { + sal_Int16 nRelOrient(aFrameSet.Get(RES_HORI_ORIENT).GetRelationOrient()); + if (sw::GetAtPageRelOrientation(nRelOrient, true)) + { + SAL_WARN("sw.core", "SwXFrame: fixing invalid horizontal RelOrientation for at-page anchor"); + + SwFormatHoriOrient item(aFrameSet.Get(RES_HORI_ORIENT)); + item.SetRelationOrient(nRelOrient); + aFrameSet.Put(item); + } + } } const ::uno::Any* pStyle; commit 393151fac4563d95056016a60260d30656e2b988 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Apr 14 17:42:06 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:50:58 2020 +0200 sw: DOCX export: export AddExternalLeading as w:noLeading For 11pt Arial, can fit 59 paragraphs on a page vs. 57... This is annoyingly complicated by the fact that Word 2013 ignores w:noLeading element if compatibilityMode is 15. Change-Id: Ie3093eabba45cdf6e7903ed860f5bad24dcc0323 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92208 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> (cherry picked from commit 968a7e3247169489d29cc7de0079eea12a663870) For the backport, don't care about compatibilityMode, it won't be in grab-bag on ODF import so rely on the default of 12. Change-Id: Ia41d6a4c99ebcc364997d0bb565addf7dc546ced diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index c368e6682833..c03d971e8fdc 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3695,6 +3695,7 @@ sal_Int32 lcl_getWordCompatibilityMode( const SwDoc& rDoc ) uno::Reference< beans::XPropertySet > xPropSet( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); + sal_Int32 nWordCompatibilityMode = -1; if ( xPropSetInfo->hasPropertyByName( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) ) { uno::Sequence< beans::PropertyValue > propList; @@ -3725,14 +3726,14 @@ sal_Int32 lcl_getWordCompatibilityMode( const SwDoc& rDoc ) if ( sName == "compatibilityMode" && sUri == "http://schemas.microsoft.com/office/word" ) { - return sVal.toInt32(); + nWordCompatibilityMode = sVal.toInt32(); } } } } } - return -1; // Word compatibility mode not found + return nWordCompatibilityMode; } } diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 7fed578100d1..a212f4e5c9b8 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -895,6 +895,21 @@ void DocxExport::WriteProperties( ) m_pFilter->exportDocumentProperties( xDocProps, bSecurityOptOpenReadOnly ); } +static auto +WriteCompat(SwDoc const& rDoc, ::sax_fastparser::FSHelperPtr const& rpFS + ) -> void +{ + if (!rDoc.getIDocumentSettingAccess().get(DocumentSettingId::ADD_EXT_LEADING)) + { + rpFS->singleElementNS(XML_w, XML_noLeading); + } + // Do not justify lines with manual break + if (rDoc.getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK)) + { + rpFS->singleElementNS(XML_w, XML_doNotExpandShiftReturn); + } +} + void DocxExport::WriteSettings() { SwViewShell *pViewShell(m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()); @@ -978,14 +993,6 @@ void DocxExport::WriteSettings() pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ), OString::number(m_aSettings.defaultTabStop) ); - // Do not justify lines with manual break - if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK )) - { - pFS->startElementNS(XML_w, XML_compat); - pFS->singleElementNS(XML_w, XML_doNotExpandShiftReturn); - pFS->endElementNS( XML_w, XML_compat ); - } - // export current mail merge database and table names SwDBData aData = m_pDoc->GetDBData(); if ( !aData.sDataSource.isEmpty() && aData.nCommandType == css::sdb::CommandType::TABLE && !aData.sCommand.isEmpty() ) @@ -1046,6 +1053,7 @@ void DocxExport::WriteSettings() bHasDummyRedlineProtectionKey = aKey.getLength() == 1 && aKey[0] == 1; } const OUString aGrabBagName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; + bool bHasCompat = false; if ( xPropSetInfo->hasPropertyByName( aGrabBagName ) ) { uno::Sequence< beans::PropertyValue > propList; @@ -1076,6 +1084,10 @@ void DocxExport::WriteSettings() { pFS->startElementNS(XML_w, XML_compat); + WriteCompat(*m_pDoc, pFS); + + bHasCompat = true; + uno::Sequence< beans::PropertyValue > aCompatSettingsSequence; rProp.Value >>= aCompatSettingsSequence; @@ -1161,6 +1173,14 @@ void DocxExport::WriteSettings() } } } + if (!bHasCompat) + { + pFS->startElementNS(XML_w, XML_compat); + + WriteCompat(*m_pDoc, pFS); + + pFS->endElementNS( XML_w, XML_compat ); + } if (! hasProtectionProperties) { commit 1f085e4c9bc7d6c269bde06bfef33b2e314dd9d2 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Apr 14 18:10:53 2020 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Aug 13 15:50:58 2020 +0200 writerfilter: DOCX import: import w:noLeading as AddExternalLeading Change-Id: I3d7fa2984975205d284575c60c6c47284b00c4a0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92209 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> (cherry picked from commit 3cd3ae30217a80449799d7d9426c3756c572712e) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 3b95e006ffad..288c18b83fd4 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -6610,6 +6610,10 @@ void DomainMapper_Impl::ApplySettingsTable() if( m_pSettingsTable->GetEmbedSystemFonts()) xSettings->setPropertyValue( getPropertyName( PROP_EMBED_SYSTEM_FONTS ), uno::makeAny(true) ); xSettings->setPropertyValue("AddParaTableSpacing", uno::makeAny(m_pSettingsTable->GetDoNotUseHTMLParagraphAutoSpacing())); + if (m_pSettingsTable->GetNoLeading()) + { + xSettings->setPropertyValue("AddExternalLeading", uno::makeAny(!m_pSettingsTable->GetNoLeading())); + } if( m_pSettingsTable->GetProtectForm() ) xSettings->setPropertyValue("ProtectForm", uno::makeAny( true )); } diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx index 90fb9c98752d..87b4871ca9b6 100644 --- a/writerfilter/source/dmapper/SettingsTable.cxx +++ b/writerfilter/source/dmapper/SettingsTable.cxx @@ -256,6 +256,7 @@ struct SettingsTable_Impl bool m_bRedlineProtection; OUString m_sRedlineProtectionKey; bool m_bDisplayBackgroundShape; + bool m_bNoLeading = false; uno::Sequence<beans::PropertyValue> m_pThemeFontLangProps; @@ -571,6 +572,9 @@ void SettingsTable::lcl_sprm(Sprm& rSprm) case NS_ooxml::LN_CT_Settings_displayBackgroundShape: m_pImpl->m_bDisplayBackgroundShape = nIntValue; break; + case NS_ooxml::LN_CT_Compat_noLeading: + m_pImpl->m_bNoLeading = nIntValue != 0; + break; default: { #ifdef DBG_UTIL @@ -795,6 +799,11 @@ bool SettingsTable::GetLongerSpaceSequence() const return m_pImpl->m_bLongerSpaceSequence; } +bool SettingsTable::GetNoLeading() const +{ + return m_pImpl->m_bNoLeading; +} + }//namespace dmapper } //namespace writerfilter diff --git a/writerfilter/source/dmapper/SettingsTable.hxx b/writerfilter/source/dmapper/SettingsTable.hxx index 26c69d907b35..7f8cc8ba9bc4 100644 --- a/writerfilter/source/dmapper/SettingsTable.hxx +++ b/writerfilter/source/dmapper/SettingsTable.hxx @@ -78,6 +78,7 @@ class SettingsTable : public LoggedProperties, public LoggedTable bool GetNoColumnBalance() const; bool GetProtectForm() const; bool GetLongerSpaceSequence() const; + bool GetNoLeading() const; bool GetNoHyphenateCaps() const; sal_Int16 GetHypenationZone() const; commit ed79b0f274c913ce8206a68a2ca9296b84ac0751 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Thu Jun 11 09:45:03 2020 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Thu Aug 13 11:13:49 2020 +0200 tdf#128197: sw: different line height for DOCX with compat=14 Lines containing just a shape inline without any other text are treated in DOCX with compatibility option 15 and 14 in a different way: while compat=15 is layouting line exatly as LO does, in compat=14 mode minimal line height takes into account just shape height and not current font. Change-Id: Id2bdab941a0bbaa9080567d736435d9e0babd490 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96080 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100542 diff --git a/sw/inc/IDocumentSettingAccess.hxx b/sw/inc/IDocumentSettingAccess.hxx index f182027ded95..814f139b64fc 100644 --- a/sw/inc/IDocumentSettingAccess.hxx +++ b/sw/inc/IDocumentSettingAccess.hxx @@ -63,7 +63,8 @@ enum class DocumentSettingId // tdf#104349 tdf#104668 MS_WORD_COMP_TRAILING_BLANKS, - + // tdf#128197 MS Word in some modes can have line height based on shape height, not on font + MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, UNIX_FORCE_ZERO_EXT_LEADING, TABS_RELATIVE_TO_INDENT, PROTECT_FORM, diff --git a/sw/qa/extras/ooxmlexport/data/128197_compat14.docx b/sw/qa/extras/ooxmlexport/data/128197_compat14.docx new file mode 100644 index 000000000000..507e28396019 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/128197_compat14.docx differ diff --git a/sw/qa/extras/ooxmlexport/data/128197_compat15.docx b/sw/qa/extras/ooxmlexport/data/128197_compat15.docx new file mode 100644 index 000000000000..d618b117cfec Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/128197_compat15.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index 237e19092d1a..18a22bbdd30c 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -35,6 +35,21 @@ protected: } }; +CPPUNIT_TEST_FIXTURE(Test, testTdf128197) +{ + load(mpTestDocumentPath, "128197_compat14.docx"); + xmlDocPtr pLayout14 = parseLayoutDump(); + sal_Int32 nHeight14 = getXPath(pLayout14, "//page[1]/body/txt[1]/infos/bounds", "height").toInt32(); + + load(mpTestDocumentPath, "128197_compat15.docx"); + xmlDocPtr pLayout15 = parseLayoutDump(); + sal_Int32 nHeight15 = getXPath(pLayout15, "//page[1]/body/txt[1]/infos/bounds", "height").toInt32(); + + // In compat mode=14 second line has size of the shape thus entire paragraph height is smaller + // So nHeight14 < nHeight15 + CPPUNIT_ASSERT_LESS(nHeight15, nHeight14); +} + DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf78749, "tdf78749.docx") { //Shape lost the background image before, now check if it still has... diff --git a/sw/source/core/doc/DocumentSettingManager.cxx b/sw/source/core/doc/DocumentSettingManager.cxx index 11210614c56f..b7f3af73d2af 100644 --- a/sw/source/core/doc/DocumentSettingManager.cxx +++ b/sw/source/core/doc/DocumentSettingManager.cxx @@ -76,6 +76,7 @@ sw::DocumentSettingManager::DocumentSettingManager(SwDoc &rDoc) mbTabRelativeToIndent(true), mbProtectForm(false), // i#78591# mbMsWordCompTrailingBlanks(false), // tdf#104349 tdf#104668 + mbMsWordCompMinLineHeightByFly(false), mbInvertBorderSpacing (false), mbCollapseEmptyCellPara(true), mbTabAtLeftIndentForParagraphsInList(false), //#i89181# @@ -181,6 +182,7 @@ bool sw::DocumentSettingManager::get(/*[in]*/ DocumentSettingId id) const case DocumentSettingId::PROTECT_FORM: return mbProtectForm; // tdf#104349 tdf#104668 case DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS: return mbMsWordCompTrailingBlanks; + case DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: return mbMsWordCompMinLineHeightByFly; // #i89181# case DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: return mbTabAtLeftIndentForParagraphsInList; case DocumentSettingId::INVERT_BORDER_SPACING: return mbInvertBorderSpacing; @@ -327,6 +329,10 @@ void sw::DocumentSettingManager::set(/*[in]*/ DocumentSettingId id, /*[in]*/ boo mbMsWordCompTrailingBlanks = value; break; + case DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: + mbMsWordCompMinLineHeightByFly = value; + break; + case DocumentSettingId::TABS_RELATIVE_TO_INDENT: mbTabRelativeToIndent = value; break; @@ -597,6 +603,7 @@ void sw::DocumentSettingManager::ReplaceCompatibilityOptions(const DocumentSetti mbClipAsCharacterAnchoredWriterFlyFrames = rSource.mbClipAsCharacterAnchoredWriterFlyFrames; mbUnixForceZeroExtLeading = rSource.mbUnixForceZeroExtLeading; mbTabRelativeToIndent = rSource.mbTabRelativeToIndent; + mbMsWordCompMinLineHeightByFly = rSource.mbMsWordCompMinLineHeightByFly; mbTabAtLeftIndentForParagraphsInList = rSource.mbTabAtLeftIndentForParagraphsInList; mbSubtractFlys = rSource.mbSubtractFlys; mbMsWordCompTrailingBlanks = rSource.mbMsWordCompTrailingBlanks; diff --git a/sw/source/core/inc/DocumentSettingManager.hxx b/sw/source/core/inc/DocumentSettingManager.hxx index fe87b339307c..e548c55a26b2 100644 --- a/sw/source/core/inc/DocumentSettingManager.hxx +++ b/sw/source/core/inc/DocumentSettingManager.hxx @@ -142,6 +142,7 @@ class DocumentSettingManager : bool mbTabRelativeToIndent : 1; // #i24363# tab stops relative to indent bool mbProtectForm : 1; bool mbMsWordCompTrailingBlanks : 1; // tdf#104349 tdf#104668 + bool mbMsWordCompMinLineHeightByFly : 1; bool mbInvertBorderSpacing : 1; bool mbCollapseEmptyCellPara : 1; bool mbTabAtLeftIndentForParagraphsInList; // #i89181# - see above diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 89c7641df414..4e57a0b64d90 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -333,6 +333,16 @@ void SwTextFormatter::InsertPortion( SwTextFormatInfo &rInf, m_pCurr->Height( pPor->Height() ); if( m_pCurr->GetAscent() < pPor->GetAscent() ) m_pCurr->SetAscent( pPor->GetAscent() ); + + if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY)) + { + // For DOCX with compat=14 the only shape in line defines height of the line inspite of used font + if (pLast->IsFlyCntPortion() && pPor->IsTextPortion() && pPor->GetLen() == TextFrameIndex(0)) + { + m_pCurr->SetAscent(pLast->GetAscent()); + m_pCurr->Height(pLast->Height()); + } + } } // Sometimes chains are constructed (e.g. by hyphenate) diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx b/sw/source/uibase/uno/SwXDocumentSettings.cxx index 9887cdc11dc8..51124bfe4071 100644 --- a/sw/source/uibase/uno/SwXDocumentSettings.cxx +++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx @@ -114,6 +114,7 @@ enum SwDocumentSettingsPropertyHandles HANDLE_USE_OLD_PRINTER_METRICS, HANDLE_PROTECT_FORM, HANDLE_MS_WORD_COMP_TRAILING_BLANKS, + HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, HANDLE_TABS_RELATIVE_TO_INDENT, HANDLE_RSID, HANDLE_RSID_ROOT, @@ -203,6 +204,7 @@ static MasterPropertySetInfo * lcl_createSettingsInfo() { OUString("RsidRoot"), HANDLE_RSID_ROOT, cppu::UnoType<sal_Int32>::get(), 0}, { OUString("ProtectForm"), HANDLE_PROTECT_FORM, cppu::UnoType<bool>::get(), 0}, { OUString("MsWordCompTrailingBlanks"), HANDLE_MS_WORD_COMP_TRAILING_BLANKS, cppu::UnoType<bool>::get(), 0 }, + { OUString("MsWordCompMinLineHeightByFly"), HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, cppu::UnoType<bool>::get(), 0 }, { OUString("TabAtLeftIndentForParagraphsInList"), HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, cppu::UnoType<bool>::get(), 0}, { OUString("ModifyPasswordInfo"), HANDLE_MODIFYPASSWORDINFO, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), 0}, { OUString("MathBaselineAlignment"), HANDLE_MATH_BASELINE_ALIGNMENT, cppu::UnoType<bool>::get(), 0}, @@ -749,6 +751,12 @@ void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInf mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS, bTmp); } break; + case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, bTmp); + } + break; case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: { bool bTmp = *o3tl::doAccess<bool>(rValue); @@ -1275,6 +1283,11 @@ void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInf rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS); } break; + case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY); + } + break; case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: { rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST); diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx index 58399cf0a151..90fb9c98752d 100644 --- a/writerfilter/source/dmapper/SettingsTable.cxx +++ b/writerfilter/source/dmapper/SettingsTable.cxx @@ -23,6 +23,7 @@ #include <rtl/ustring.hxx> #include <sfx2/zoomitem.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/XPropertyState.hpp> #include <com/sun/star/container/XNameContainer.hpp> @@ -701,6 +702,13 @@ void SettingsTable::ApplyProperties(uno::Reference<text::XTextDocument> const& x { uno::Reference< beans::XPropertySet> xDocProps( xDoc, uno::UNO_QUERY ); + if (GetWordCompatibilityMode() <= 14) + { + uno::Reference<lang::XMultiServiceFactory> xTextFactory(xDoc, uno::UNO_QUERY_THROW); + uno::Reference<beans::XPropertySet> xDocumentSettings(xTextFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY_THROW); + xDocumentSettings->setPropertyValue("MsWordCompMinLineHeightByFly", uno::makeAny(true)); + } + // Show changes value if (xDocProps.is()) { commit f27fd86d2dc424cee2d28fe77d881eacc4795eaf Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Aug 11 15:29:38 2020 +0100 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Wed Aug 12 11:36:23 2020 +0200 tdf#135442 min supported version of gtk3 is 3.18 not 3.20 Change-Id: Iaa2eefbe08fad3a7dd6eff98bf5fb513053a263d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100541 Tested-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sd/uiconfig/simpress/ui/clientboxfragment.ui b/sd/uiconfig/simpress/ui/clientboxfragment.ui index 361caeeb4823..e5811360878d 100644 --- a/sd/uiconfig/simpress/ui/clientboxfragment.ui +++ b/sd/uiconfig/simpress/ui/clientboxfragment.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.22.1 --> <interface domain="sd"> - <requires lib="gtk+" version="3.20"/> + <requires lib="gtk+" version="3.18"/> <object class="GtkGrid" id="ClientboxFragment"> <property name="visible">True</property> <property name="can_focus">False</property> diff --git a/vcl/uiconfig/ui/wizard.ui b/vcl/uiconfig/ui/wizard.ui index e1f68da9e66a..76f92607f1ce 100644 --- a/vcl/uiconfig/ui/wizard.ui +++ b/vcl/uiconfig/ui/wizard.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.22.1 --> <interface domain="vcl"> - <requires lib="gtk+" version="3.20"/> + <requires lib="gtk+" version="3.18"/> <object class="GtkAssistant" id="Wizard"> <property name="can_focus">True</property> <property name="border_width">6</property> commit b6e41d97fa8ee9e265970325348a6be111978c2c Author: Thorsten Behrens <thorsten.behr...@cib.de> AuthorDate: Wed Jul 22 10:44:46 2020 +0200 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Aug 12 09:19:43 2020 +0200 tdf#134043 DOCX import: new unit tests: ComboBox to DropDown Change-Id: I034b0cd9c6f66c531460d1bb69d9ede5ff46f7d7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97531 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99994 tdf#134572 DOCX: Incorrect default value in dropdown text fields Change-Id: I3169e817c2f033d1525adc3b02ac3680ad220d70 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99074 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100306 diff --git a/sw/CppunitTest_sw_ooxmlexport4.mk b/sw/CppunitTest_sw_ooxmlexport4.mk index e3285932e004..0f026bc8384e 100644 --- a/sw/CppunitTest_sw_ooxmlexport4.mk +++ b/sw/CppunitTest_sw_ooxmlexport4.mk @@ -11,4 +11,8 @@ $(eval $(call sw_ooxmlexport_test,4)) +$(eval $(call gb_CppunitTest_use_custom_headers,sw_ooxmlexport4,\ + officecfg/registry \ +)) + # vim: set noet sw=4 ts=4: diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index abb55384f68f..5ad0a4ece74c 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -900,7 +900,7 @@ DECLARE_OOXMLEXPORT_TEST(tdf119809, "tdf119809.docx") CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown")); uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items"); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aItems.getLength()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aItems.getLength()); } } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx index c80c8f6655bb..c39c7d747b83 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -23,6 +23,9 @@ #include <com/sun/star/util/Date.hpp> #include <unotools/tempfile.hxx> #include <config_features.h> +#include <comphelper/configuration.hxx> +#include <officecfg/Office/Writer.hxx> + class Test : public SwModelTestBase { @@ -43,6 +46,19 @@ protected: // If the testcase is stored in some other format, it's pointless to test. return (OString(filename).endsWith(".docx") && std::find(vBlacklist.begin(), vBlacklist.end(), filename) == vBlacklist.end()); } + + virtual std::unique_ptr<Resetter> preTest(const char* filename) override + { + if (OString(filename) == "combobox-control.docx" ) + { + std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create()); + officecfg::Office::Writer::Filter::Import::DOCX::ImportComboBoxAsDropDown::set(true, batch); + batch->commit(); + } + return nullptr; + } + + void verifyComboBoxExport(bool aComboBoxAsDropDown); }; DECLARE_OOXMLEXPORT_TEST(testRelorientation, "relorientation.docx") @@ -765,12 +781,48 @@ DECLARE_OOXMLEXPORT_TEST(testFDO76312, "FDO76312.docx") assertXPath(pXmlDoc, "/w:document/w:body/w:tbl[1]/w:tr[1]/w:tc[1]"); } -DECLARE_OOXMLEXPORT_TEST(testComboBoxControl, "combobox-control.docx") +void Test::verifyComboBoxExport(bool aComboBoxAsDropDown) +{ + if (aComboBoxAsDropDown) + { + // ComboBox was imported as DropDown text field + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); + CPPUNIT_ASSERT(xFields->hasMoreElements()); + uno::Any aField = xFields->nextElement(); + uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY); + CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown")); + + uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aItems.getLength()); + CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]); + CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]); + CPPUNIT_ASSERT_EQUAL(OUString("Manolo"), aItems[2]); + } + else + { + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<drawing::XControlShape> xControl(xShape, uno::UNO_QUERY); + + CPPUNIT_ASSERT_EQUAL(OUString("Manolo"), getProperty<OUString>(xControl->getControl(), "Text")); + + uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(xControl->getControl(), "StringItemList"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength()); + CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]); + CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]); + } +} + +DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testComboBoxControl, "combobox-control.docx") { // check XML xmlDocPtr pXmlDoc = parseExport("word/document.xml"); if (!pXmlDoc) return; + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dropDownList/w:listItem[1]", "value", "manolo"); assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dropDownList/w:listItem[2]", "value", "pepito"); assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r/w:t", "Manolo"); @@ -779,35 +831,27 @@ DECLARE_OOXMLEXPORT_TEST(testComboBoxControl, "combobox-control.docx") uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); // check imported control - if (xDrawPage->getCount() > 0) - { - uno::Reference<drawing::XControlShape> xControl(getShape(1), uno::UNO_QUERY); + verifyComboBoxExport(xDrawPage->getCount() == 0); +} - CPPUNIT_ASSERT_EQUAL(OUString("Manolo"), getProperty<OUString>(xControl->getControl(), "Text")); +CPPUNIT_TEST_FIXTURE(Test, tdf134043_ImportComboBoxAsDropDown_true) +{ + std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create()); + officecfg::Office::Writer::Filter::Import::DOCX::ImportComboBoxAsDropDown::set(true, batch); + batch->commit(); - uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(xControl->getControl(), "StringItemList"); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength()); - CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]); - CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]); - } - else - { - // ComboBox was imported as DropDown text field - uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); - uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); - CPPUNIT_ASSERT(xFields->hasMoreElements()); - uno::Any aField = xFields->nextElement(); - uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY); - CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown")); + load(mpTestDocumentPath, "combobox-control.docx"); + verifyComboBoxExport(true); +} - CPPUNIT_ASSERT_EQUAL(OUString("manolo"), getProperty<OUString>(aField, "SelectedItem")); +CPPUNIT_TEST_FIXTURE(Test, tdf134043_ImportComboBoxAsDropDown_false) +{ + std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create()); + officecfg::Office::Writer::Filter::Import::DOCX::ImportComboBoxAsDropDown::set(false, batch); + batch->commit(); - uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items"); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength()); - CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]); - CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]); - } + load(mpTestDocumentPath, "combobox-control.docx"); + verifyComboBoxExport(false); } DECLARE_OOXMLEXPORT_TEST(testCheckBoxControl, "checkbox-control.docx") diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx index 0e1416b7ee00..fbe8d9d01421 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx @@ -959,9 +959,10 @@ DECLARE_OOXMLEXPORT_TEST(testN779630, "n779630.docx") CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown")); uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items"); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aItems.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("Yes"), aItems[0]); CPPUNIT_ASSERT_EQUAL(OUString("No"), aItems[1]); + CPPUNIT_ASSERT_EQUAL(OUString("dropdown default text"), aItems[2]); } } diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 3685e92cf942..154e7660d842 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -93,6 +93,15 @@ void SdtHelper::createDropDownControl() m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.text.TextField.DropDown"), uno::UNO_QUERY); + const auto it = std::find_if( + m_aDropDownItems.begin(), m_aDropDownItems.end(), + [aDefaultText](const OUString& item) -> bool { return !item.compareTo(aDefaultText); }); + + if (m_aDropDownItems.end() == it) + { + m_aDropDownItems.push_back(aDefaultText); + } + // set properties uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY); xPropertySet->setPropertyValue("SelectedItem", uno::makeAny(aDefaultText)); commit a99de4981f2e0a652d964c8c688f73485494102e Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Mon Aug 10 19:14:54 2020 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Aug 11 17:38:00 2020 +0200 tdf#128198 sw: text formatting: only consider upper margin for first line The non-first lines start below the first one so the margin is already included in the previous line's Y position. Also move the testTdf116486 to layout.cxx. (regression from d07fc485d46f431405a3f6a002f951a08c559677) Change-Id: I574516ea5f9600e2d861e43162b1a69488c68819 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100440 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> (cherry picked from commit 99ef50f97b6d8461b8953c2555298c7bbeb3405b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100499 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/extras/ooxmlimport/data/tdf116486.docx b/sw/qa/extras/layout/data/tdf116486.docx similarity index 100% rename from sw/qa/extras/ooxmlimport/data/tdf116486.docx rename to sw/qa/extras/layout/data/tdf116486.docx diff --git a/sw/qa/extras/layout/data/tdf128198-1.docx b/sw/qa/extras/layout/data/tdf128198-1.docx new file mode 100644 index 000000000000..7c9974d562b9 Binary files /dev/null and b/sw/qa/extras/layout/data/tdf128198-1.docx differ diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 6ce67106162d..c94811b4d5e7 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -1139,6 +1139,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testRedlineFlysInFootnote) } } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf116486) +{ + SwDoc* pDoc = createDoc("tdf116486.docx"); + CPPUNIT_ASSERT(pDoc); + OUString aTop = parseDump("/root/page/body/txt/Special", "nHeight"); + CPPUNIT_ASSERT_EQUAL(OUString("4006"), aTop); +} + +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf128198) +{ + SwDoc* pDoc = createDoc("tdf128198-1.docx"); + CPPUNIT_ASSERT(pDoc); + xmlDocPtr pLayout = parseLayoutDump(); + // the problem was that line 5 was truncated at "this " + // due to the fly anchored in previous paragraph + assertXPath(pLayout, "/root/page/body/txt[2]/LineBreak[5]", "Line", + "to access any service, any time, anywhere. From this perspective, satellite " + "boasts some "); + assertXPath(pLayout, "/root/page/body/txt[2]/LineBreak[6]", "Line", "significant advantages. "); +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testNoLineBreakAtSlash) { load(DATA_DIRECTORY, "no-line-break-at-slash.fodt"); diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx index a14b97aec66a..4b69a62859c6 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx @@ -411,12 +411,6 @@ DECLARE_OOXMLIMPORT_TEST(testTdf114217, "tdf114217.docx") CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), xDrawPage->getCount()); } -DECLARE_OOXMLIMPORT_TEST(testTdf116486, "tdf116486.docx") -{ - OUString aTop = parseDump("/root/page/body/txt/Special", "nHeight"); - CPPUNIT_ASSERT_EQUAL(OUString("4006"), aTop); -} - DECLARE_OOXMLIMPORT_TEST(testTdf119200, "tdf119200.docx") { auto xPara = getParagraph(1); diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 043f522687de..89c7641df414 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -2296,7 +2296,8 @@ void SwTextFormatter::CalcFlyWidth( SwTextFormatInfo &rInf ) // tdf#116486: consider also the upper margin from getFramePrintArea because intersections // with this additional space should lead to repositioning of paragraphs // For compatibility we grab a related compat flag: - if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS)) + if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS) + && IsFirstTextLine()) { const long nUpper = m_pFrame->getFramePrintArea().Top(); // Increase the rectangle commit 0d5affd7a25396dbff866adae524a4c01329801f Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Aug 5 21:08:04 2020 +0100 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Mon Aug 10 11:56:32 2020 +0200 tdf#135098 update SwTableCursor m_SelectedBoxes before merge so it does not contain the soon to-be-deleted SwTableBox so if the rPam is queried via a11y it doesn't claim the deleted cell still exists. tdf#122844 may be the same issue Change-Id: I1ac3752676162ba5a29c0916039b2b467e2ac41a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100214 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx index 00e249b9e0fb..15a49729ce51 100644 --- a/sw/source/core/docnode/ndtbl.cxx +++ b/sw/source/core/docnode/ndtbl.cxx @@ -2280,6 +2280,15 @@ TableMergeErr SwDoc::MergeTable( SwPaM& rPam ) while( &rPam != ( pTmp = pTmp->GetNext() )) for( int i = 0; i < 2; ++i ) pTmp->GetBound( static_cast<bool>(i) ) = *rPam.GetPoint(); + + if (SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(&rPam)) + { + // tdf#135098 update selection so rPam's m_SelectedBoxes is updated + // to not contain the soon to-be-deleted SwTableBox so if the rPam + // is queried via a11y it doesn't claim the deleted cell still + // exists + pTableCursor->NewTableSelection(); + } } // Merge them commit 9b5832cd149e199d61a63801fecb7e3baa8c3662 Author: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> AuthorDate: Thu Aug 6 15:32:09 2020 +0200 Commit: Gerrit Code Review <ger...@gerrit.libreoffice.org> CommitDate: Thu Aug 6 15:32:09 2020 +0200 Update git submodules * Update translations from branch 'libreoffice-6-4' to d03e92fd5d821662dc0ed7d9a0a2b45da09de8a4 - update translations for 6.4.6 rc2 and force-fix errors using pocheck Change-Id: Id908ccd8e13508c60a4a0cd1fbede491bb0bf2bb diff --git a/translations b/translations index a86baa6cd143..d03e92fd5d82 160000 --- a/translations +++ b/translations @@ -1 +1 @@ -Subproject commit a86baa6cd1436f8de43a415d8b38e3ecce44e647 +Subproject commit d03e92fd5d821662dc0ed7d9a0a2b45da09de8a4 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits