summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRohit Deshmukh <rohit.deshmukh@synerzip.com>2014-06-13 11:39:56 +0530
committerMiklos Vajna <vmiklos@collabora.co.uk>2014-06-19 11:01:17 +0000
commit1c876f5616522ab695de8c0316cdb0c601081815 (patch)
treecca50a93dbf02fe9e9e6b8935a2a4496b051f642
parentee9e8f677103f3b93faaef55832fb704f95e0a4b (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.docxbin0 -> 59732 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport.cxx13
-rw-r--r--sw/source/core/unocore/unoframe.cxx7
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx206
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx3
-rw-r--r--sw/source/filter/ww8/docxsdrexport.cxx20
-rw-r--r--sw/source/filter/ww8/docxsdrexport.hxx2
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx10
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
new file mode 100644
index 000000000000..c32b0276b9f2
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/FDO78590.docx
Binary files differ
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());