summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Kłos <szymon.klos@collabora.com>2017-05-24 00:15:15 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-05-26 09:31:08 +0200
commit271094ad8f9e334d17176744b90b35e80528bcb2 (patch)
tree7d23532e46f978d500ec8eafba49436416ddee09
parente1b247625419515a8aeaf9e1f232f16cb4f59f73 (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.cxx4
-rw-r--r--oox/source/vml/vmlshapecontext.cxx11
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport7.cxx4
-rw-r--r--sw/qa/extras/uiwriter/data/watermark.docxbin0 -> 18768 bytes
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx23
-rw-r--r--sw/source/core/edit/edfcol.cxx17
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
new file mode 100644
index 000000000000..0b26d4442e98
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/watermark.docx
Binary files differ
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();
}
}