diff options
author | Rohit Deshmukh <rohit.deshmukh@synerzip.com> | 2014-06-13 11:39:56 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-06-19 11:01:17 +0000 |
commit | 1c876f5616522ab695de8c0316cdb0c601081815 (patch) | |
tree | cca50a93dbf02fe9e9e6b8935a2a4496b051f642 | |
parent | ee9e8f677103f3b93faaef55832fb704f95e0a4b (diff) |
fdo#78590: Fix for Corruption of para with framePr & drawing object into para
Issue:
- File contains paragraph with framePr have graphic object in it.
- So Libreoffice converts framePr into textbox.
- So after saving file textbox gets exported with drawing object.
- MS office does not allowed drawing object inside tetxbox.
Change-Id: I673e0e9f6681a189bde1c63a8cb7aea2cac0ab41
Fix: - Export framePr into paragraph and igonre exporting of
dummy textbox added by LO for framePr.
Reviewed-on: https://gerrit.libreoffice.org/9389
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/FDO78590.docx | bin | 0 -> 59732 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 13 | ||||
-rw-r--r-- | sw/source/core/unocore/unoframe.cxx | 7 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 206 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 3 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxsdrexport.cxx | 20 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxsdrexport.hxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 10 |
8 files changed, 214 insertions, 47 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/FDO78590.docx b/sw/qa/extras/ooxmlexport/data/FDO78590.docx Binary files differnew file mode 100644 index 000000000000..c32b0276b9f2 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/FDO78590.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index d97be6f9b21c..5b0244e22209 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -3635,6 +3635,19 @@ DECLARE_OOXMLEXPORT_TEST(testfdo79817,"fdo79817.docx") assertXPath ( pXmlDoc, "/w:document/w:body/w:p[3]/w:sdt/w:sdtPr/w:dataBinding", "xpath","/ns0:properties[1]/documentManagement[1]/ns2:Responsible_x0020_Officer_x0020_Title[1]"); } + +DECLARE_OOXMLEXPORT_TEST(testFDO78590, "FDO78590.docx") +{ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + + if (!pXmlDoc) + return; + + // This is to ensure that the fld starts and ends inside a hyperlink... + assertXPath ( pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:framePr", "w", "9851" ); + assertXPath ( pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:framePr", "h", "1669" ); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index e02024cf7d98..55c50d4aca26 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -3052,6 +3052,13 @@ void SwXFrame::attachToRange(const uno::Reference< text::XTextRange > & xTextRan { setPropertyValue(UNO_NAME_DESCRIPTION, *pDescription); } + + // For grabbag + const uno::Any* pFrameIntropgrabbagItem; + if( pProps->GetProperty(RES_FRMATR_GRABBAG, 0, pFrameIntropgrabbagItem) ) + { + setPropertyValue(UNO_NAME_FRAME_INTEROP_GRAB_BAG, *pFrameIntropgrabbagItem); + } } else throw lang::IllegalArgumentException(); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 1ca7ee3d4816..e7144c715b28 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -305,6 +305,96 @@ static void lcl_deleteAndResetTheLists( ::sax_fastparser::FastAttributeList* &pS } } +void DocxAttributeOutput::PopulateFrameProperties(const SwFrmFmt* pFrmFmt, const Size& rSize) +{ + + sax_fastparser::FastAttributeList* attrList = m_pSerializer->createAttrList(); + + awt::Point aPos(pFrmFmt->GetHoriOrient().GetPos(), pFrmFmt->GetVertOrient().GetPos()); + + attrList->add( FSNS( XML_w, XML_w), OString::number(rSize.Width())); + attrList->add( FSNS( XML_w, XML_h), OString::number(rSize.Height())); + + attrList->add( FSNS( XML_w, XML_x), OString::number(aPos.X)); + attrList->add( FSNS( XML_w, XML_y), OString::number(aPos.Y)); + + const char* relativeFromH; + const char* relativeFromV; + switch (pFrmFmt->GetVertOrient().GetRelationOrient()) + { + case text::RelOrientation::PAGE_PRINT_AREA: + relativeFromV = "margin"; + break; + case text::RelOrientation::PAGE_FRAME: + relativeFromV = "page"; + break; + case text::RelOrientation::FRAME: + relativeFromV = "paragraph"; + break; + case text::RelOrientation::TEXT_LINE: + default: + relativeFromV = "line"; + break; + } + + switch (pFrmFmt->GetHoriOrient().GetRelationOrient()) + { + case text::RelOrientation::PAGE_PRINT_AREA: + relativeFromH = "margin"; + break; + case text::RelOrientation::PAGE_FRAME: + relativeFromH = "page"; + break; + case text::RelOrientation::CHAR: + relativeFromH = "character"; + break; + case text::RelOrientation::PAGE_RIGHT: + relativeFromH = "page"; + break; + case text::RelOrientation::FRAME: + default: + relativeFromH = "column"; + break; + } + attrList->add( FSNS( XML_w, XML_vAnchor), relativeFromV); + attrList->add( FSNS( XML_w, XML_hAnchor), relativeFromH); + attrList->add( FSNS( XML_w, XML_wrap), "notBeside"); + attrList->add( FSNS( XML_w, XML_hRule), "exact"); + + sax_fastparser::XFastAttributeListRef xAttrList(attrList); + m_pSerializer->singleElementNS( XML_w, XML_framePr, xAttrList ); +} + +bool DocxAttributeOutput::TextBoxIsFramePr(const SwFrmFmt& rFrmFmt) +{ + uno::Reference< drawing::XShape > xShape; + const SdrObject* pSdrObj = rFrmFmt.FindRealSdrObject(); + if (pSdrObj) + xShape = uno::Reference< drawing::XShape >(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY); + uno::Reference< beans::XPropertySet > xPropertySet(xShape, uno::UNO_QUERY); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo; + if (xPropertySet.is()) + xPropSetInfo = xPropertySet->getPropertySetInfo(); + uno::Any aFrameProperties ; + bool bFrameProperties = 0; + if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag")) + { + uno::Sequence< beans::PropertyValue > propList; + xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList; + for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp) + { + OUString propName = propList[nProp].Name; + if (propName == "ParaFrameProperties") + { + aFrameProperties = propList[nProp].Value ; + break; + } + } + } + aFrameProperties >>= bFrameProperties; + return bFrameProperties; +} + void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) { // write the paragraph properties + the run, already in the correct order @@ -323,59 +413,71 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT sw::Frame aFrame = m_aFramesOfParagraph[nIndex]; m_pSerializer->startElementNS( XML_w, XML_r, FSEND ); - m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND); - m_pSerializer->startElementNS(XML_mc, XML_Choice, - XML_Requires, "wps", - FSEND); - /** - This is to avoid AltenateContent within another AlternateContent. - So when Choice is Open, only write the DML Drawing instead of both DML - and VML Drawing in another AlternateContent. - **/ - SetAlternateContentChoiceOpen( true ); - /** FDO#71834 : - We should probably be renaming the function - switchHeaderFooter to something like SaveRetrieveTableReference. - Save the table reference attributes before calling WriteDMLTextFrame, - otherwise the StartParagraph function will use the previous existing - table reference attributes since the variable is being shared. - */ - switchHeaderFooter(true,1); - /** Save the table info's before writing the shape - as there might be a new table that might get - spawned from within the VML & DML block and alter - the contents. - */ - ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_rExport.mpTableInfo; - //Reset the table infos after saving. - m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); + const SwFrmFmt& rFrmFmt = aFrame.GetFrmFmt(); + + if (!TextBoxIsFramePr(rFrmFmt) || m_bWritingHeaderFooter) + { + m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND); + m_pSerializer->startElementNS(XML_mc, XML_Choice, + XML_Requires, "wps", + FSEND); + /** + This is to avoid AltenateContent within another AlternateContent. + So when Choice is Open, only write the DML Drawing instead of both DML + and VML Drawing in another AlternateContent. + **/ + SetAlternateContentChoiceOpen( true ); + /** FDO#71834 : + We should probably be renaming the function + switchHeaderFooter to something like SaveRetrieveTableReference. + Save the table reference attributes before calling WriteDMLTextFrame, + otherwise the StartParagraph function will use the previous existing + table reference attributes since the variable is being shared. + */ + switchHeaderFooter(true,1); + /** Save the table info's before writing the shape + as there might be a new table that might get + spawned from within the VML & DML block and alter + the contents. + */ + ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_rExport.mpTableInfo; + //Reset the table infos after saving. + m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); m_rExport.SdrExporter().writeDMLTextFrame(&aFrame, m_anchorId++); m_pSerializer->endElementNS(XML_mc, XML_Choice); SetAlternateContentChoiceOpen( false ); - // Reset table infos, otherwise the depth of the cells will be incorrect, - // in case the text frame had table(s) and we try to export the - // same table second time. - m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); - //reset the tableReference. - switchHeaderFooter(false,0); - - m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND); - m_rExport.SdrExporter().writeVMLTextFrame(&aFrame); - /* FDO#71834 :Restore the data here after having written the Shape - for further processing. - */ - switchHeaderFooter(false,-1); - m_rExport.mpTableInfo = pOldTableInfo; - - m_pSerializer->endElementNS(XML_mc, XML_Fallback); - m_pSerializer->endElementNS(XML_mc, XML_AlternateContent); - + // Reset table infos, otherwise the depth of the cells will be incorrect, + // in case the text frame had table(s) and we try to export the + // same table second time. + m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); + //reset the tableReference. + switchHeaderFooter(false,0); + + m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND); + m_rExport.SdrExporter().writeVMLTextFrame(&aFrame); + /* FDO#71834 :Restore the data here after having written the Shape + for further processing. + */ + switchHeaderFooter(false,-1); + m_rExport.mpTableInfo = pOldTableInfo; + + m_pSerializer->endElementNS(XML_mc, XML_Fallback); + m_pSerializer->endElementNS(XML_mc, XML_AlternateContent); + } + else + { + ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_rExport.mpTableInfo; + //Reset the table infos after saving. + m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); + m_rExport.SdrExporter().writeOnlyTextOfFrame(&aFrame); + m_rExport.mpTableInfo = pOldTableInfo; + } m_pSerializer->endElementNS( XML_w, XML_r ); m_bParagraphFrameOpen = false; } - if (m_postponedCustomShape) + if (!m_postponedCustomShape->empty()) { m_pSerializer->startElementNS( XML_w, XML_r, FSEND ); WritePostponedCustomShape(); @@ -716,6 +818,20 @@ void DocxAttributeOutput::EndParagraphProperties( const SfxItemSet* pParagraphMa m_pSerializer->endElementNS( XML_w, XML_rPr ); } + if (!m_bWritingHeaderFooter) + { + //Check whether we have Frame for paragraph + for (size_t nIndex = 0; nIndex < m_aFramesOfParagraph.size(); ++nIndex) + { + sw::Frame aFrame = m_aFramesOfParagraph[nIndex]; + const SwFrmFmt& rFrmFmt = aFrame.GetFrmFmt(); + if (TextBoxIsFramePr(rFrmFmt)) + { + const Size aSize = aFrame.GetSize(); + PopulateFrameProperties(&rFrmFmt, aSize); + } + } + } m_pSerializer->endElementNS( XML_w, XML_pPr ); if ( m_nColBreakStatus == COLBRK_WRITE ) diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 324b31aa7185..6465a711cb87 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -416,7 +416,8 @@ private: void EndTableCell( ); void EndTableRow( ); void EndTable(); - + void PopulateFrameProperties(const SwFrmFmt* pFrmFmt, const Size& rSize); + bool TextBoxIsFramePr(const SwFrmFmt& rFrmFmt); /// End cell, row, and even the entire table if necessary. void FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph = false ); diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx index 435dc2bec407..42e9f9cd2abd 100644 --- a/sw/source/filter/ww8/docxsdrexport.cxx +++ b/sw/source/filter/ww8/docxsdrexport.cxx @@ -1197,6 +1197,26 @@ void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFr } } +void DocxSdrExport::writeOnlyTextOfFrame(sw::Frame* pParentFrame) +{ + const SwFrmFmt& rFrmFmt = pParentFrame->GetFrmFmt(); + const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx(); + sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer; + + sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0; + sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0; + + //Save data here and restore when out of scope + ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame); + + m_pImpl->m_pBodyPrAttrList = pFS->createAttrList(); + m_pImpl->m_bFrameBtLr = checkFrameBtlr(m_pImpl->m_rExport.pDoc->GetNodes()[nStt], 0); + m_pImpl->m_bFlyFrameGraphic = true; + m_pImpl->m_rExport.WriteText(); + m_pImpl->m_bFlyFrameGraphic = false; + m_pImpl->m_bFrameBtLr = false; +} + void DocxSdrExport::writeDMLTextFrame(sw::Frame* pParentFrame, int nAnchorId, bool bTextBoxOnly) { sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer; diff --git a/sw/source/filter/ww8/docxsdrexport.hxx b/sw/source/filter/ww8/docxsdrexport.hxx index 09f2185ec931..5c98a424dbb0 100644 --- a/sw/source/filter/ww8/docxsdrexport.hxx +++ b/sw/source/filter/ww8/docxsdrexport.hxx @@ -99,6 +99,8 @@ public: bool checkFrameBtlr(SwNode* pStartNode, sax_fastparser::FastAttributeList* pTextboxAttrList = 0); /// Is this a standalone TextFrame, or used as a TextBox of a shape? bool isTextBox(const SwFrmFmt& rFrmFmt); + /// Writes text from Textbox for <w:framePr> + void writeOnlyTextOfFrame(sw::Frame* pParentFrame); }; #endif // INCLUDED_SW_SOURCE_FILTER_WW8_DOCXSDREXPORT_HXX diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index b4b4dde014d1..cbf7ea368e34 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -788,7 +788,7 @@ void DomainMapper_Impl::CheckUnregisteredFrameConversion( ) StyleSheetEntryPtr pParaStyle = GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(rAppendContext.pLastParagraphProperties->GetParaStyleName()); - uno::Sequence< beans::PropertyValue > aFrameProperties(pParaStyle ? 16: 9); + uno::Sequence< beans::PropertyValue > aFrameProperties(pParaStyle ? 17: 9); if ( pParaStyle.get( ) ) { @@ -809,6 +809,7 @@ void DomainMapper_Impl::CheckUnregisteredFrameConversion( ) pFrameProperties[13].Name = rPropNameSupplier.GetName(PROP_TOP_MARGIN); pFrameProperties[14].Name = rPropNameSupplier.GetName(PROP_BOTTOM_MARGIN); pFrameProperties[15].Name = rPropNameSupplier.GetName(PROP_BACK_COLOR_TRANSPARENCY); + pFrameProperties[16].Name = "FrameInteropGrabBag"; const ParagraphProperties* pStyleProperties = dynamic_cast<const ParagraphProperties*>( pParaStyle->pProperties.get() ); if (!pStyleProperties) @@ -893,6 +894,13 @@ void DomainMapper_Impl::CheckUnregisteredFrameConversion( ) // will be ignored. pFrameProperties[15].Value <<= sal_Int32(100); + beans::PropertyValue aRet; + uno::Sequence<beans::PropertyValue> aGrabBag(1); + aRet.Name = "ParaFrameProperties"; + aRet.Value <<= uno::Any(rAppendContext.pLastParagraphProperties->IsFrameMode()); + aGrabBag[0] = aRet; + pFrameProperties[16].Value <<= aGrabBag; + lcl_MoveBorderPropertiesToFrame(aFrameProperties, rAppendContext.pLastParagraphProperties->GetStartingRange(), rAppendContext.pLastParagraphProperties->GetEndingRange()); |