Kaydet (Commit) e1386e32 authored tarafından Miklos Vajna's avatar Miklos Vajna

DocxSdrExport::writeDMLAndVMLDrawing: fix handling of inline VML shapes

In general Writer supports having objects inside a TextFrame, Word does
not. It turns out that Word allows having certain shapes inside other
shapes, as long as they are VML-only. So do that for now: if we receive
a shape when we're already inside a shape, then just export it as VML,
not the usual drawingml+VML pair.

Also, blacklist one more VML shape type, where the shape text is already
exported inside <v:textpath>, so no dedicated <v:textbox> is needed.

Change-Id: I5786bd6827eae9756e7c179bb2ef5a5741a91878
üst b779dc13
...@@ -971,6 +971,18 @@ bool lcl_isTextBox(const SdrObject* pSdrObject) ...@@ -971,6 +971,18 @@ bool lcl_isTextBox(const SdrObject* pSdrObject)
return false; return false;
} }
bool lcl_hasTextBoxContent(sal_uInt32 nShapeType)
{
switch (nShapeType)
{
case ESCHER_ShpInst_TextPlainText:
case ESCHER_ShpInst_TextSlantUp:
return false;
default:
return true;
}
}
OUString lcl_getAnchorIdFromGrabBag(const SdrObject* pSdrObject) OUString lcl_getAnchorIdFromGrabBag(const SdrObject* pSdrObject)
{ {
OUString aResult; OUString aResult;
...@@ -1126,7 +1138,7 @@ sal_Int32 VMLExport::StartShape() ...@@ -1126,7 +1138,7 @@ sal_Int32 VMLExport::StartShape()
// now check if we have some editeng text (not associated textbox) and we have a text exporter registered // now check if we have some editeng text (not associated textbox) and we have a text exporter registered
const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject); const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
if (pTxtObj && m_pTextExport && m_nShapeType != ESCHER_ShpInst_TextPlainText && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject)) if (pTxtObj && m_pTextExport && lcl_hasTextBoxContent(m_nShapeType) && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject))
{ {
const OutlinerParaObject* pParaObj = 0; const OutlinerParaObject* pParaObj = 0;
bool bOwnParaObj = false; bool bOwnParaObj = false;
......
...@@ -1685,9 +1685,23 @@ DECLARE_OOXMLEXPORT_TEST(testWordArtWithinDraingtool, "testWordArtWithinDraingto ...@@ -1685,9 +1685,23 @@ DECLARE_OOXMLEXPORT_TEST(testWordArtWithinDraingtool, "testWordArtWithinDraingto
xmlDocPtr pXmlDoc = parseExport("word/document.xml"); xmlDocPtr pXmlDoc = parseExport("word/document.xml");
if (!pXmlDoc) if (!pXmlDoc)
return; return;
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[2]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1); uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[2]/mc:AlternateContent[1]/mc:Fallback[1]/w:pict[1]/v:rect[1]/v:textbox[1]/w:txbxContent[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:inline[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1); uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:inline[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1); if (xIndexAccess->getCount())
{
// TODO TextBox: remove this when TextBox is enabled by default
// This second run is a bug, should be the first ideally
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[2]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1);
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[2]/mc:AlternateContent[1]/mc:Fallback[1]/w:pict[1]/v:rect[1]/v:textbox[1]/w:txbxContent[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:inline[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1);
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:inline[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1);
}
else
{
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1);
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Fallback[1]/w:pict[1]/v:rect[1]/v:textbox[1]/w:txbxContent[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:inline[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]",1);
// Make sure that the shape inside a shape is exported as VML-only, no embedded mc:AlternateContent before w:pict.
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:txbx[1]/w:txbxContent[1]/w:p/w:r/w:pict",1);
}
} }
DECLARE_OOXMLEXPORT_TEST(testFdo78957, "fdo78957.docx") DECLARE_OOXMLEXPORT_TEST(testFdo78957, "fdo78957.docx")
......
...@@ -690,6 +690,27 @@ void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFr ...@@ -690,6 +690,27 @@ void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFr
const_cast< SdrObject* >(sdrObj)->SetPage(0); const_cast< SdrObject* >(sdrObj)->SetPage(0);
} }
bool lcl_isLockedCanvas(uno::Reference<drawing::XShape> xShape)
{
bool bRet = false;
uno::Sequence< beans::PropertyValue > propList =
lclGetProperty(xShape, "InteropGrabBag");
for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
{
OUString propName = propList[nProp].Name;
if (propName == "LockedCanvas")
{
/*
* Export as Locked Canvas only if the property
* is in the PropertySet
*/
bRet = true;
break;
}
}
return bRet;
}
void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt* pFrmFmt, int nAnchorId) void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt* pFrmFmt, int nAnchorId)
{ {
uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(), uno::UNO_QUERY_THROW); uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(), uno::UNO_QUERY_THROW);
...@@ -723,22 +744,7 @@ void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt* ...@@ -723,22 +744,7 @@ void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt*
XML_uri, pNamespace, XML_uri, pNamespace,
FSEND); FSEND);
bool bLockedCanvas = false; bool bLockedCanvas = lcl_isLockedCanvas(xShape);
uno::Sequence< beans::PropertyValue > propList =
lclGetProperty(xShape, "InteropGrabBag");
for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
{
OUString propName = propList[nProp].Name;
if (propName == "LockedCanvas")
{
/*
* Export as Locked Canvas only if the property
* is in the PropertySet
*/
bLockedCanvas = true;
break;
}
}
if (bLockedCanvas) if (bLockedCanvas)
pFS->startElementNS(XML_lc, XML_lockedCanvas, pFS->startElementNS(XML_lc, XML_lockedCanvas,
FSNS(XML_xmlns, XML_lc), "http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas", FSNS(XML_xmlns, XML_lc), "http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas",
...@@ -827,15 +833,22 @@ bool DocxSdrExport::Impl::isSupportedDMLShape(uno::Reference<drawing::XShape> xS ...@@ -827,15 +833,22 @@ bool DocxSdrExport::Impl::isSupportedDMLShape(uno::Reference<drawing::XShape> xS
void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft, int nAnchorId) void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft, int nAnchorId)
{ {
bool bDMLAndVMLDrawingOpen = m_pImpl->m_bDMLAndVMLDrawingOpen;
m_pImpl->m_bDMLAndVMLDrawingOpen = true; m_pImpl->m_bDMLAndVMLDrawingOpen = true;
// Depending on the shape type, we actually don't write the shape as DML. // Depending on the shape type, we actually don't write the shape as DML.
OUString sShapeType; OUString sShapeType;
sal_uInt32 nMirrorFlags = 0; sal_uInt32 nMirrorFlags = 0;
uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObj)->getUnoShape(), uno::UNO_QUERY_THROW); uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObj)->getUnoShape(), uno::UNO_QUERY_THROW);
// Locked canvas is OK inside DML.
if (lcl_isLockedCanvas(xShape))
bDMLAndVMLDrawingOpen = false;
MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType(xShape, nMirrorFlags, sShapeType); MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType(xShape, nMirrorFlags, sShapeType);
if (eShapeType != ESCHER_ShpInst_TextPlainText && m_pImpl->isSupportedDMLShape(xShape)) // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
if (eShapeType != ESCHER_ShpInst_TextPlainText && m_pImpl->isSupportedDMLShape(xShape) && !bDMLAndVMLDrawingOpen)
{ {
m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND); m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment