diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2017-05-24 00:15:15 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-05-26 09:31:08 +0200 |
commit | 271094ad8f9e334d17176744b90b35e80528bcb2 (patch) | |
tree | 7d23532e46f978d500ec8eafba49436416ddee09 | |
parent | e1b247625419515a8aeaf9e1f232f16cb4f59f73 (diff) |
Watermark: docx interoperability
Before patch:
Document created in MS Word:
<v:shapetype id="_x0000_t136" o:spt="136" ...>
<v:shape type="#_x0000_t136" ...>
Imported to LO and exported:
<v:shapetype id="shapetype_136" o:spt="136" ...>
<v:shape type="shapetype_136" ...>
Then again imported to MS Word and exported:
<v:shapetype id="shapetype_136" o:spid="_x0000_m1026" o:spt="100" ...>
<v:shape type="#shapetype_136" ...>
In this moment LO after import had shape in the navigator but it wasn't visible.
Patch:
* vmshapecontext.cxx is changed to read ShapeType from id instead of o:spt
when o:spid is present.
* vmlexport.cxx added o:spid for Word to identify inserted watermark
* edfxol.cxx changed name of shape to "PowerPlusWaterMarkObject" for Word
* tests
Change-Id: I25322628838a98c45cbeed64144d04977b2ea9ba
Reviewed-on: https://gerrit.libreoffice.org/37969
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r-- | oox/source/export/vmlexport.cxx | 4 | ||||
-rw-r--r-- | oox/source/vml/vmlshapecontext.cxx | 11 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport7.cxx | 4 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/data/watermark.docx | bin | 0 -> 18768 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter.cxx | 23 | ||||
-rw-r--r-- | sw/source/core/edit/edfcol.cxx | 17 |
6 files changed, 50 insertions, 9 deletions
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index ef400be64f7c..623beaaa88ec 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -190,8 +190,10 @@ void VMLExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uIn } else { - // A watermark object - store the optional shape ID also ('o:spid') + // A watermark object - store the optional shape ID m_pShapeAttrList->add( XML_id, OUStringToOString(m_pSdrObject->GetName(), RTL_TEXTENCODING_UTF8) ); + // also ('o:spid') + m_pShapeAttrList->addNS( XML_o, XML_spid, ShapeIdString( nShapeId ) ); } } diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx index dc654223aca6..ed369ae1c7d9 100644 --- a/oox/source/vml/vmlshapecontext.cxx +++ b/oox/source/vml/vmlshapecontext.cxx @@ -275,11 +275,18 @@ ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, ShapeType& r mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() ); mrTypeModel.maLegacyId = rAttribs.getString( XML_id, OUString() ); OSL_ENSURE( !mrTypeModel.maShapeId.isEmpty(), "ShapeTypeContext::ShapeTypeContext - missing shape identifier" ); + // builtin shape type identifier + mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) ); // if the o:spid attribute exists, the id attribute contains the user-defined shape name if( bHasOspid ) + { mrTypeModel.maShapeName = rAttribs.getXString( XML_id, OUString() ); - // builtin shape type identifier - mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) ); + // get ShapeType and ShapeId from name for compatibility + mrTypeModel.maShapeId = mrTypeModel.maShapeName; + static const OUString sShapeTypePrefix = "shapetype_"; + if( mrTypeModel.maShapeName.startsWith( sShapeTypePrefix ) ) + mrTypeModel.moShapeType = mrTypeModel.maShapeName.copy(sShapeTypePrefix.getLength()).toInt32(); + } // coordinate system position/size, CSS style mrTypeModel.moCoordPos = lclDecodeInt32Pair( rAttribs, XML_coordorigin ); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx index f9b851175202..67179b5c14a0 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx @@ -108,6 +108,10 @@ DECLARE_OOXMLEXPORT_TEST(testTextWatermark, "textWatermark.docx") return; assertXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","id","PowerPlusWaterMarkObject93701316"); + + //The second problem was that Word uses also "o:spid" + const OUString& sSpid = getXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","spid"); + CPPUNIT_ASSERT(!sSpid.isEmpty()); } DECLARE_OOXMLEXPORT_TEST(testPictureWatermark, "pictureWatermark.docx") diff --git a/sw/qa/extras/uiwriter/data/watermark.docx b/sw/qa/extras/uiwriter/data/watermark.docx Binary files differnew file mode 100644 index 000000000000..0b26d4442e98 --- /dev/null +++ b/sw/qa/extras/uiwriter/data/watermark.docx diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index 8621a81884a9..1e482e1ac87d 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -104,6 +104,7 @@ #include <comphelper/configurationhelper.hxx> #include <editeng/unolingu.hxx> #include <config_features.h> +#include <sfx2/watermarkitem.hxx> static const char* const DATA_DIRECTORY = "/sw/qa/extras/uiwriter/data/"; @@ -125,6 +126,7 @@ public: void testDOCXAutoTextMultiple(); void testDOTMAutoText(); void testDOCXAutoTextGallery(); + void testWatermarkDOCX(); void testTdf67238(); void testFdo75110(); void testFdo75898(); @@ -263,6 +265,7 @@ public: CPPUNIT_TEST(testDOCXAutoTextMultiple); CPPUNIT_TEST(testDOTMAutoText); CPPUNIT_TEST(testDOCXAutoTextGallery); + CPPUNIT_TEST(testWatermarkDOCX); CPPUNIT_TEST(testTdf67238); CPPUNIT_TEST(testFdo75110); CPPUNIT_TEST(testFdo75898); @@ -855,6 +858,26 @@ void SwUiWriterTest::testDOCXAutoTextGallery() CPPUNIT_ASSERT_EQUAL(OUString("Multiple"), pGlossary->GetLongName(0)); } +void SwUiWriterTest::testWatermarkDOCX() +{ + SwDoc* const pDoc = createDoc("watermark.docx"); + SwDocShell* pDocShell = pDoc->GetDocShell(); + const SfxPoolItem* pItem; + SfxItemState eState = pDocShell->GetViewShell()->GetViewFrame()->GetDispatcher()->QueryState(SID_WATERMARK, pItem); + + CPPUNIT_ASSERT(eState >= SfxItemState::DEFAULT); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL((unsigned short)SID_WATERMARK, pItem->Which()); + + const SfxWatermarkItem* pWatermark = static_cast<const SfxWatermarkItem*>(pItem); + CPPUNIT_ASSERT_EQUAL(OUString("CustomWatermark"), pWatermark->GetText()); + //TODO: VML import textpath style + //CPPUNIT_ASSERT_EQUAL(OUString("DejaVu Sans Light"), pWatermark->GetFont()); + CPPUNIT_ASSERT_EQUAL((sal_Int16)45, pWatermark->GetAngle()); + CPPUNIT_ASSERT_EQUAL((sal_uInt32)0x548dd4, pWatermark->GetColor()); + CPPUNIT_ASSERT_EQUAL((sal_Int16)50, pWatermark->GetTransparency()); +} + void SwUiWriterTest::testFdo74981() { // create a document with an input field diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 4ffbd1263864..ec94e4b88a4e 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -60,6 +60,8 @@ #include <pagefrm.hxx> #include <sfx2/watermarkitem.hxx> +#define WATERMARK_NAME "PowerPlusWaterMarkObject" + namespace { @@ -114,8 +116,8 @@ bool lcl_hasField(const uno::Reference<text::XText>& xText, const OUString& rSer return false; } -/// Search for a frame named rShapeName of type rServiceName in xText. -uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XText>& xText, const OUString& rServiceName, const OUString& rShapeName) +/// Search for a frame with WATERMARK_NAME in name of type rServiceName in xText. Returns found name in rShapeName. +uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XText>& xText, const OUString& rServiceName, OUString& rShapeName) { uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xText, uno::UNO_QUERY); uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration(); @@ -144,9 +146,12 @@ uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XTex continue; uno::Reference<container::XNamed> xNamed(xWatermark, uno::UNO_QUERY); - if (xNamed->getName() != rShapeName) + + if (!xNamed->getName().match(WATERMARK_NAME)) continue; + rShapeName = xNamed->getName(); + uno::Reference<drawing::XShape> xShape(xWatermark, uno::UNO_QUERY); return xShape; } @@ -283,7 +288,7 @@ SfxWatermarkItem SwEditShell::GetWatermark() xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; OUString aShapeServiceName = "com.sun.star.drawing.CustomShape"; - static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK(); + OUString sWatermark = ""; uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark); if (xWatermark.is()) @@ -349,7 +354,7 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark) xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; OUString aShapeServiceName = "com.sun.star.drawing.CustomShape"; - static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK(); + OUString sWatermark = WATERMARK_NAME; uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark); bool bDeleteWatermark = rWatermark.GetText().isEmpty(); @@ -490,7 +495,7 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark) xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec))); uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY); - xNamed->setName(SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK()); + xNamed->setName(sWatermark); xLockable->removeActionLock(); } } |