Change-Id: I2f3539c4536a090ccb827e12a39f4718a73fe4fd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211771 Tested-by: Julien Nabet <serval2412@yahoo.fr> Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
1396 lines
65 KiB
C++
1396 lines
65 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <swmodeltestbase.hxx>
|
|
|
|
#include <com/sun/star/awt/FontWeight.hpp>
|
|
#include <com/sun/star/text/RelOrientation.hpp>
|
|
#include <com/sun/star/text/VertOrientation.hpp>
|
|
#include <com/sun/star/text/XFootnote.hpp>
|
|
#include <com/sun/star/text/XTextColumns.hpp>
|
|
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
|
|
#include <com/sun/star/view/XSelectionSupplier.hpp>
|
|
#include <com/sun/star/style/ParagraphAdjust.hpp>
|
|
#include <com/sun/star/text/SizeType.hpp>
|
|
#include <com/sun/star/text/XTextContent.hpp>
|
|
#include <com/sun/star/text/XTextField.hpp>
|
|
#include <com/sun/star/text/XTextTable.hpp>
|
|
|
|
#include <tools/UnitConversion.hxx>
|
|
#include <comphelper/sequenceashashmap.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
|
|
#include <drawdoc.hxx>
|
|
#include <IDocumentDrawModelAccess.hxx>
|
|
#include <unotxdoc.hxx>
|
|
#include <docsh.hxx>
|
|
#include <IDocumentLayoutAccess.hxx>
|
|
#include <rootfrm.hxx>
|
|
#include <pagefrm.hxx>
|
|
#include <flyfrms.hxx>
|
|
#include <sortedobjs.hxx>
|
|
#include <txtfrm.hxx>
|
|
#include <IDocumentMarkAccess.hxx>
|
|
#include <xmloff/odffields.hxx>
|
|
|
|
class Test : public SwModelTestBase
|
|
{
|
|
public:
|
|
Test()
|
|
: SwModelTestBase(u"/sw/qa/extras/ooxmlexport/data/"_ustr)
|
|
{
|
|
}
|
|
};
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testFdo78939, "fdo78939.docx")
|
|
{
|
|
// fdo#78939 : LO hanged while opening issue document
|
|
|
|
// Whenever a para-style was applied to a Numbering format level,
|
|
// LO incorrectly also changed the para-style...
|
|
|
|
// check that file opens and does not hang while opening and also
|
|
// check that an incorrect numbering style is not applied ...
|
|
CPPUNIT_ASSERT_EQUAL(OUString(),
|
|
getProperty<OUString>(getParagraph(1), u"NumberingStyleName"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testFootnote, "footnote.docx")
|
|
{
|
|
uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
|
|
uno::Reference<text::XTextRange> xFootnote(xFootnotes->getByIndex(0), uno::UNO_QUERY);
|
|
OUString aFootnote = xFootnote->getString();
|
|
// Ensure there are no additional newlines after "bar".
|
|
CPPUNIT_ASSERT(aFootnote.endsWith("bar"));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTableBtlrCenter, "table-btlr-center.docx")
|
|
{
|
|
// Note that this is btLr text, so layout and doc model horizontal/vertical is the opposite of
|
|
// each other.
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XCell> xCell = xTable->getCellByName(u"A2"_ustr);
|
|
// Cell vertical alignment was CENTER, should be NONE.
|
|
CPPUNIT_ASSERT_EQUAL(text::VertOrientation::NONE,
|
|
getProperty<sal_Int16>(xCell, u"VertOrient"_ustr));
|
|
|
|
// Cell horizontal alignment should be CENTER.
|
|
uno::Reference<text::XText> xCellText(xCell, uno::UNO_QUERY);
|
|
auto nActual = getProperty<sal_Int32>(getParagraphOfText(1, xCellText), u"ParaAdjust"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(style::ParagraphAdjust_CENTER), nActual);
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testFdo80555, "fdo80555.docx")
|
|
{
|
|
uno::Reference<drawing::XShape> xShape = getShape(1);
|
|
// Shape was wrongly placed at X=0, Y=0
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(3318), xShape->getPosition().X);
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(247), xShape->getPosition().Y);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf104418)
|
|
{
|
|
createSwDoc("tdf104418.odt");
|
|
saveAndReload(TestFilter::DOCX);
|
|
// Problem was that <w:hideMark> cell property was ignored.
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
|
|
|
|
// Without the fix in place, this test would have failed with
|
|
// - Expected: 750
|
|
// - Actual : 1499
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int64(750),
|
|
getProperty<sal_Int64>(xTableRows->getByIndex(0), u"Height"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testHidemark, "hidemark.docx")
|
|
{
|
|
// Problem was that <w:hideMark> cell property was ignored.
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
|
|
// Height should be minimal
|
|
CPPUNIT_ASSERT_EQUAL(convertTwipToMm100(MINLAY),
|
|
getProperty<sal_Int64>(xTableRows->getByIndex(1), u"Height"_ustr));
|
|
// Size type was MIN, should be FIX to avoid considering the end of paragraph marker.
|
|
CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX,
|
|
getProperty<sal_Int16>(xTableRows->getByIndex(1), u"SizeType"_ustr));
|
|
|
|
//tdf#104876: Width was not recognized during import when table size was 'auto'
|
|
CPPUNIT_ASSERT_MESSAGE("table size is less than 7000?",
|
|
sal_Int32(7000) > getProperty<sal_Int32>(xTextTable, u"Width"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testHidemarkb, "tdf99616_hidemarkb.docx")
|
|
{
|
|
// Problem was that the smallest possible height was forced, not the min specified size.
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
|
|
// Height should be .5cm
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int64(501),
|
|
getProperty<sal_Int64>(xTableRows->getByIndex(1), u"Height"_ustr));
|
|
// Size type was MIN, should be FIX to avoid considering the end of paragraph marker.
|
|
CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX,
|
|
getProperty<sal_Int16>(xTableRows->getByIndex(1), u"SizeType"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testBnc891663, "bnc891663.docx")
|
|
{
|
|
// The image should be inside a cell, so the text in the following cell should be below it.
|
|
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
|
int imageTop
|
|
= getXPath(pXmlDoc, "/root/page/body/tab/row[1]/cell[2]/txt[1]/anchored/fly/infos/bounds",
|
|
"top")
|
|
.toInt32();
|
|
int imageHeight
|
|
= getXPath(pXmlDoc, "/root/page/body/tab/row[1]/cell[2]/txt[1]/anchored/fly/infos/bounds",
|
|
"height")
|
|
.toInt32();
|
|
int textNextRowTop
|
|
= getXPath(pXmlDoc, "/root/page/body/tab/row[2]/cell[1]/txt[1]/infos/bounds", "top")
|
|
.toInt32();
|
|
CPPUNIT_ASSERT(textNextRowTop >= imageTop + imageHeight);
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf123104, "tdf123104.docx")
|
|
{
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XCell> xCell = xTable->getCellByName(u"E1"_ustr);
|
|
// See SwXCell::getPropertyValue(), we really put 'long' into an Any there.
|
|
// Without the accompanying fix in place, this test would have failed with 'Expected: 3;Actual :
|
|
// 2', i.e. the vertical merge covered one less cell, resulting in a cell with white background.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(3),
|
|
getProperty<tools::Long>(xCell, u"RowSpan"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testFdo85542, "fdo85542.docx")
|
|
{
|
|
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(),
|
|
uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), xBookmarksByIdx->getCount());
|
|
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"B1"_ustr));
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"B2"_ustr));
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"B3"_ustr));
|
|
// B1
|
|
uno::Reference<text::XTextContent> xContent1(xBookmarksByName->getByName(u"B1"_ustr),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xRange1 = xContent1->getAnchor();
|
|
CPPUNIT_ASSERT_EQUAL(u"ABB"_ustr, xRange1->getString());
|
|
// B2
|
|
uno::Reference<text::XTextContent> xContent2(xBookmarksByName->getByName(u"B2"_ustr),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xRange2 = xContent2->getAnchor();
|
|
CPPUNIT_ASSERT_EQUAL(u"BBC"_ustr, xRange2->getString());
|
|
// B3 -- testing a collapsed bookmark
|
|
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName(u"B3"_ustr),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
|
|
CPPUNIT_ASSERT_EQUAL(xRange3->getString(), OUString());
|
|
uno::Reference<text::XText> xText = xRange3->getText();
|
|
uno::Reference<text::XTextCursor> xNeighborhoodCursor = xText->createTextCursor();
|
|
xNeighborhoodCursor->gotoRange(xRange3, false);
|
|
xNeighborhoodCursor->goLeft(1, false);
|
|
xNeighborhoodCursor->goRight(2, true);
|
|
CPPUNIT_ASSERT_EQUAL(u"AB"_ustr, xNeighborhoodCursor->getString());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf65955)
|
|
{
|
|
createSwDoc("tdf65955.odt");
|
|
saveAndReload(TestFilter::DOCX);
|
|
CPPUNIT_ASSERT_EQUAL(1, getPages());
|
|
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(),
|
|
uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xBookmarksByIdx->getCount());
|
|
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"a"_ustr));
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"b"_ustr));
|
|
// a
|
|
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName(u"a"_ustr),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
|
|
CPPUNIT_ASSERT_EQUAL(xRange3->getString(), OUString());
|
|
// b
|
|
uno::Reference<text::XTextContent> xContent2(xBookmarksByName->getByName(u"b"_ustr),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xRange2 = xContent2->getAnchor();
|
|
CPPUNIT_ASSERT_EQUAL(u"r"_ustr, xRange2->getString());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf65955_2)
|
|
{
|
|
createSwDoc("tdf65955_2.odt");
|
|
saveAndReload(TestFilter::DOCX);
|
|
CPPUNIT_ASSERT_EQUAL(1, getPages());
|
|
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(),
|
|
uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xBookmarksByIdx->getCount());
|
|
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"test"_ustr));
|
|
|
|
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName(u"test"_ustr),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
|
|
CPPUNIT_ASSERT_EQUAL(u"foo bar"_ustr, xRange3->getString());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testChtOutlineNumberingOoxml, "chtoutline.docx")
|
|
{
|
|
static constexpr OUStringLiteral aExpectedNumbering = u"\u7b2c 1 \u7ae0";
|
|
|
|
uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering),
|
|
getProperty<OUString>(xPara, u"ListLabelString"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(mathtype, "mathtype.docx")
|
|
{
|
|
uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent,
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xEmbeddedObjects(
|
|
xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY);
|
|
// This failed as the Model property was empty.
|
|
auto xModel = getProperty<uno::Reference<lang::XServiceInfo>>(xEmbeddedObjects->getByIndex(0),
|
|
u"Model"_ustr);
|
|
CPPUNIT_ASSERT(xModel->supportsService(u"com.sun.star.formula.FormulaProperties"_ustr));
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf8255)
|
|
{
|
|
auto verify = [this]() {
|
|
// A full-page-wide multi-page floating table should be allowed to split:
|
|
uno::Reference<text::XTextFramesSupplier> xDocument(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<beans::XPropertySet> xFrame(
|
|
xDocument->getTextFrames()->getByName(u"Frame1"_ustr), uno::UNO_QUERY);
|
|
bool bIsSplitAllowed{};
|
|
xFrame->getPropertyValue(u"IsSplitAllowed"_ustr) >>= bIsSplitAllowed;
|
|
CPPUNIT_ASSERT(bIsSplitAllowed);
|
|
};
|
|
createSwDoc("tdf8255.docx");
|
|
verify();
|
|
saveAndReload(TestFilter::DOCX);
|
|
verify();
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf87460, "tdf87460.docx")
|
|
{
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(xTextDocument, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes();
|
|
// This was 0: endnote was lost on import.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xEndnotes->getCount());
|
|
|
|
// Also make sure that <w:tblpPr> is mapped to a text frame (hosting the table):
|
|
uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XNameAccess> xTextFrames = xTextFramesSupplier->getTextFrames();
|
|
// Without the fix in place, this test would have failed, the table was inline.
|
|
CPPUNIT_ASSERT(xTextFrames->hasByName(u"Frame1"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf90611, "tdf90611.docx")
|
|
{
|
|
uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
|
|
uno::Reference<text::XText> xFootnoteText;
|
|
xFootnotes->getByIndex(0) >>= xFootnoteText;
|
|
// This was 11.
|
|
CPPUNIT_ASSERT_EQUAL(
|
|
10.f, getProperty<float>(getParagraphOfText(1, xFootnoteText), u"CharHeight"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf89702, "tdf89702.docx")
|
|
{
|
|
// Get the first paragraph's numbering style's 2nd level's character style name.
|
|
uno::Reference<text::XTextRange> xParagraph = getParagraph(1);
|
|
auto xLevels
|
|
= getProperty<uno::Reference<container::XIndexAccess>>(xParagraph, u"NumberingRules"_ustr);
|
|
uno::Sequence<beans::PropertyValue> aLevel;
|
|
xLevels->getByIndex(1) >>= aLevel; // 2nd level
|
|
OUString aCharStyleName = std::find_if(std::cbegin(aLevel), std::cend(aLevel),
|
|
[](const beans::PropertyValue& rValue) {
|
|
return rValue.Name == "CharStyleName";
|
|
})
|
|
->Value.get<OUString>();
|
|
|
|
// Make sure that the font name is Arial, this was Verdana.
|
|
uno::Reference<beans::XPropertySet> xStyle(
|
|
getStyles(u"CharacterStyles"_ustr)->getByName(aCharStyleName), uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(u"Arial"_ustr, getProperty<OUString>(xStyle, u"CharFontName"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf86374, "tdf86374.docx")
|
|
{
|
|
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XTableRows> xTableRows = xTable->getRows();
|
|
// btLr text direction was imported as FIX, it should be MIN to have enough space for the additionally entered paragraphs.
|
|
CPPUNIT_ASSERT_EQUAL(text::SizeType::MIN,
|
|
getProperty<sal_Int16>(xTableRows->getByIndex(0), u"SizeType"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf87924, "tdf87924.docx")
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY);
|
|
comphelper::SequenceAsHashMap aGeometry(
|
|
xPropertySet->getPropertyValue(u"CustomShapeGeometry"_ustr));
|
|
// This was -270, the text rotation angle was set when it should not be rotated.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
|
|
aGeometry[u"TextPreRotateAngle"_ustr].get<sal_Int32>());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testIndents, "indents.docx")
|
|
{
|
|
//expected left margin and first line indent values
|
|
static const sal_Int32 indents[] = { 0, 0, -2000, 0, -2000, 1000, -1000, -1000, 2000, -1000 };
|
|
uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(textDocument->getText(),
|
|
uno::UNO_QUERY);
|
|
// list of paragraphs
|
|
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
|
|
size_t paraIndex = 0;
|
|
do
|
|
{
|
|
uno::Reference<lang::XServiceInfo> xServiceInfo;
|
|
if (xParaEnum->nextElement() >>= xServiceInfo)
|
|
{
|
|
uno::Reference<beans::XPropertySet> const xPropertySet(xServiceInfo,
|
|
uno::UNO_QUERY_THROW);
|
|
sal_Int32 nIndent = 0;
|
|
sal_Int32 nFirstLine = 0;
|
|
xPropertySet->getPropertyValue(u"ParaLeftMargin"_ustr) >>= nIndent;
|
|
xPropertySet->getPropertyValue(u"ParaFirstLineIndent"_ustr) >>= nFirstLine;
|
|
CPPUNIT_ASSERT_EQUAL(indents[paraIndex * 2], nIndent);
|
|
CPPUNIT_ASSERT_EQUAL(indents[paraIndex * 2 + 1], nFirstLine);
|
|
++paraIndex;
|
|
}
|
|
} while (xParaEnum->hasMoreElements());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf92454, "tdf92454.docx")
|
|
{
|
|
// The first paragraph had a large indentation / left margin as inheritance
|
|
// in Word and Writer works differently, and no direct value was set to be
|
|
// explicit.
|
|
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(1), uno::UNO_QUERY);
|
|
// This was beans::PropertyState_DEFAULT_VALUE.
|
|
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE,
|
|
xParagraph->getPropertyState(u"ParaFirstLineIndent"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf95377, "tdf95377.docx")
|
|
{
|
|
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(1), uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(1000),
|
|
getProperty<sal_Int32>(xParagraph, u"ParaRightMargin"_ustr));
|
|
|
|
xParagraph.set(getParagraph(2), uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(-501),
|
|
getProperty<sal_Int32>(xParagraph, u"ParaFirstLineIndent"_ustr));
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(2501),
|
|
getProperty<sal_Int32>(xParagraph, u"ParaLeftMargin"_ustr));
|
|
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE,
|
|
xParagraph->getPropertyState(u"ParaFirstLineIndent"_ustr));
|
|
|
|
xParagraph.set(getParagraph(3), uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(-250),
|
|
getProperty<sal_Int32>(xParagraph, u"ParaFirstLineIndent"_ustr));
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(250),
|
|
getProperty<sal_Int32>(xParagraph, u"ParaLeftMargin"_ustr));
|
|
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE,
|
|
xParagraph->getPropertyState(u"ParaFirstLineIndent"_ustr));
|
|
|
|
//default style has numbering enabled. Styles inherit numbering unless specifically disabled
|
|
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
|
assertXPath(pXmlDoc,
|
|
"//body/txt/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
|
|
3); //first three paragraphs have numbering
|
|
assertXPath(pXmlDoc,
|
|
"//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
|
|
"expand", u"a.");
|
|
assertXPath(pXmlDoc,
|
|
"//body/txt[2]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
|
|
"expand", u"b.");
|
|
assertXPath(pXmlDoc,
|
|
"//body/txt[3]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
|
|
"expand", u"c.");
|
|
assertXPath(
|
|
pXmlDoc,
|
|
"/root/page/body/txt[4]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
|
|
0); //last paragraph style disables numbering
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf95376, "tdf95376.docx")
|
|
{
|
|
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(2), uno::UNO_QUERY);
|
|
// This was beans::PropertyState_DIRECT_VALUE: indentation-from-numbering
|
|
// did not have priority over indentation-from-paragraph-style, due to a
|
|
// filter workaround that's not correct here.
|
|
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DEFAULT_VALUE,
|
|
xParagraph->getPropertyState(u"ParaFirstLineIndent"_ustr));
|
|
|
|
//tdf#131321 - paragraph styles lost their numbering. Bullet+space inherits WWNum1 from Bullet
|
|
uno::Reference<beans::XPropertySet> xStyle(
|
|
getStyles(u"ParagraphStyles"_ustr)->getByName(u"Bullet+space"_ustr), uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT(!(getProperty<OUString>(xStyle, u"NumberingStyleName"_ustr)).isEmpty());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf92124, "tdf92124.docx")
|
|
{
|
|
// Get the second paragraph's numbering style's 1st level's suffix.
|
|
uno::Reference<text::XTextRange> xParagraph = getParagraph(2);
|
|
auto xLevels
|
|
= getProperty<uno::Reference<container::XIndexAccess>>(xParagraph, u"NumberingRules"_ustr);
|
|
uno::Sequence<beans::PropertyValue> aLevel;
|
|
xLevels->getByIndex(0) >>= aLevel; // 1st level
|
|
OUString aSuffix
|
|
= std::find_if(std::cbegin(aLevel), std::cend(aLevel),
|
|
[](const beans::PropertyValue& rValue) { return rValue.Name == "Suffix"; })
|
|
->Value.get<OUString>();
|
|
// Make sure it's empty as the source document contains <w:suff w:val="nothing"/>.
|
|
CPPUNIT_ASSERT(aSuffix.isEmpty());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf169024_verticalTopFrame)
|
|
{
|
|
// Given an SW frame anchored TO_CHAR, vertically aligned above (top) the Line of Text
|
|
// gets exported as 'bottom' in DOCX, and import maps 'bottom' to top of Line of Text again
|
|
|
|
auto verify = [this]() {
|
|
// To Character anchored Line of Text needs to be LINE_TOP in order for the GUI to pick it up
|
|
CPPUNIT_ASSERT_EQUAL(text::RelOrientation::TEXT_LINE,
|
|
getProperty<sal_Int16>(getShape(1), u"VertOrientRelation"_ustr));
|
|
CPPUNIT_ASSERT_EQUAL(text::VertOrientation::LINE_TOP,
|
|
getProperty<sal_Int16>(getShape(1), u"VertOrient"_ustr));
|
|
};
|
|
|
|
createSwDoc("tdf169024_verticalTopFrame.odt");
|
|
verify();
|
|
saveAndReload(TestFilter::DOCX_2007);
|
|
verify();
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf90153, "tdf90153.docx")
|
|
{
|
|
// This was at-para, so the line-level VertOrientRelation was lost, resulting in an incorrect vertical position.
|
|
CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
|
|
getProperty<text::TextContentAnchorType>(getShape(1), u"AnchorType"_ustr));
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf169024)
|
|
{
|
|
createSwDoc("tdf90153.docx");
|
|
//saveAndReload(TestFilter::DOCX);
|
|
|
|
// To Character anchored Line of Text needs to be LINE_BOTTOM in order for the GUI to pick it up
|
|
CPPUNIT_ASSERT_EQUAL(text::RelOrientation::TEXT_LINE,
|
|
getProperty<sal_Int16>(getShape(1), u"VertOrientRelation"_ustr));
|
|
CPPUNIT_ASSERT_EQUAL(text::VertOrientation::LINE_BOTTOM,
|
|
getProperty<sal_Int16>(getShape(1), u"VertOrient"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf93919, "tdf93919.docx")
|
|
{
|
|
// This was 0, left margin was not inherited from the list style.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1270),
|
|
getProperty<sal_Int32>(getParagraph(1), u"ParaLeftMargin"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf91417, "tdf91417.docx")
|
|
{
|
|
// The first paragraph should contain a link to "http://www.google.com/"
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<text::XTextCursor> xTextCursor = xTextDocument->getText()->createTextCursor();
|
|
uno::Reference<beans::XPropertySet> xCursorProps(xTextCursor, uno::UNO_QUERY);
|
|
OUString aValue;
|
|
xCursorProps->getPropertyValue(u"HyperLinkURL"_ustr) >>= aValue;
|
|
CPPUNIT_ASSERT_EQUAL(u"http://www.google.com/"_ustr, aValue);
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf90810, "tdf90810short.docx")
|
|
{
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<text::XFootnotesSupplier> xFootnoteSupp(xTextDocument, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xFootnoteIdxAcc = xFootnoteSupp->getFootnotes();
|
|
uno::Reference<text::XFootnote> xFootnote(xFootnoteIdxAcc->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<text::XText> xFootnoteText(xFootnote, uno::UNO_QUERY);
|
|
OUString sFootnoteText = xFootnoteText->getString();
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(89), sFootnoteText.getLength());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf89165, "tdf89165.docx")
|
|
{
|
|
// This must not hang in layout
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf95777, "tdf95777.docx")
|
|
{
|
|
// This must not fail on open
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf94374)
|
|
{
|
|
createSwDoc("hello.docx");
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<text::XTextRange> xText = xTextDocument->getText();
|
|
uno::Reference<text::XTextRange> xEnd = xText->getEnd();
|
|
// This failed: it wasn't possible to insert a DOCX document into an existing Writer one.
|
|
paste(u"ooxmlexport/data/tdf94374.docx", u"com.sun.star.comp.Writer.WriterFilter"_ustr, xEnd);
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf83300, "tdf83300.docx")
|
|
{
|
|
// tdf#143722: This was 'TOC Heading', upon updating a TOC the heading replaced its Word-default blue + Calibri style
|
|
// with a Writer-default black + Liberation Sans one
|
|
CPPUNIT_ASSERT_EQUAL(u"Contents Heading"_ustr,
|
|
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf78902, "tdf78902.docx")
|
|
{
|
|
// This hung in layout.
|
|
CPPUNIT_ASSERT_EQUAL(2, getPages());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf95775, "tdf95775.docx")
|
|
{
|
|
// This must not fail in layout
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf92157, "tdf92157.docx")
|
|
{
|
|
// A graphic with dimensions 0,0 should not fail on load
|
|
|
|
// Additionally, the bookmark names should not change (they got a "1" appended when copied)
|
|
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"referentiegegevens"_ustr));
|
|
CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"referentiegegevens_bk"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf97417, "section_break_numbering.docx")
|
|
{
|
|
uno::Reference<beans::XPropertySet> xProps(getParagraph(1), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_MESSAGE("1st page: first paragraph erroneous numbering",
|
|
!xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
|
|
// paragraph with numbering and section break was removed by writerfilter
|
|
// but its numbering was copied to all following paragraphs
|
|
CPPUNIT_ASSERT_MESSAGE("2nd page: first paragraph missing numbering",
|
|
getProperty<uno::Reference<container::XIndexAccess>>(
|
|
getParagraph(2), u"NumberingRules"_ustr)
|
|
.is());
|
|
xProps = uno::Reference<beans::XPropertySet>(getParagraph(3), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_MESSAGE("2nd page: second paragraph erroneous numbering",
|
|
!xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2, getPages());
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf94043, "tdf94043.docx")
|
|
{
|
|
auto xTextSection
|
|
= getProperty<uno::Reference<beans::XPropertySet>>(getParagraph(2), u"TextSection"_ustr);
|
|
auto xTextColumns
|
|
= getProperty<uno::Reference<text::XTextColumns>>(xTextSection, u"TextColumns"_ustr);
|
|
// This was 0, the separator line was not visible due to 0 width.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2),
|
|
getProperty<sal_Int32>(xTextColumns, u"SeparatorLineWidth"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf95213, "tdf95213.docx")
|
|
{
|
|
// Get the second paragraph's numbering style's 2nd level's character style name.
|
|
uno::Reference<text::XTextRange> xParagraph = getParagraph(2);
|
|
auto xLevels
|
|
= getProperty<uno::Reference<container::XIndexAccess>>(xParagraph, u"NumberingRules"_ustr);
|
|
uno::Sequence<beans::PropertyValue> aLevel;
|
|
xLevels->getByIndex(1) >>= aLevel; // 2nd level
|
|
OUString aName = std::find_if(std::cbegin(aLevel), std::cend(aLevel),
|
|
[](const beans::PropertyValue& rValue) {
|
|
return rValue.Name == "CharStyleName";
|
|
})
|
|
->Value.get<OUString>();
|
|
|
|
uno::Reference<beans::XPropertySet> xStyle(getStyles(u"CharacterStyles"_ustr)->getByName(aName),
|
|
uno::UNO_QUERY);
|
|
// This was awt::FontWeight::BOLD.
|
|
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xStyle, u"CharWeight"_ustr));
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf97371, "tdf97371.docx")
|
|
{
|
|
SwDoc* pDoc = getSwDoc();
|
|
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
|
|
SdrObject* pShape = pPage->GetObj(0);
|
|
SdrObject* pTextBox = pPage->GetObj(1);
|
|
tools::Long nDiff = std::abs(pShape->GetSnapRect().Top() - pTextBox->GetSnapRect().Top());
|
|
// The top of the two shapes were 410 and 3951, now it should be 3950 and 3951.
|
|
CPPUNIT_ASSERT(nDiff < 10);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(3900), pShape->GetSnapRect().Top(), 100);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf99140)
|
|
{
|
|
auto verify = [this]() {
|
|
// A multi-page floating table appeared only on the first page.
|
|
SwDoc* pDoc = getSwDoc();
|
|
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
|
auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
|
|
CPPUNIT_ASSERT(pPage1);
|
|
const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
|
|
auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
|
|
CPPUNIT_ASSERT(pPage1Fly);
|
|
SwFrame* pTab1 = pPage1Fly->GetLower();
|
|
// This was text::HoriOrientation::NONE, the second table was too wide due to this.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(9622), pTab1->getFrameArea().Width());
|
|
SwFrame* pRow1 = pTab1->GetLower();
|
|
SwFrame* pCell1 = pRow1->GetLower();
|
|
auto pText1 = dynamic_cast<SwTextFrame*>(pCell1->GetLower());
|
|
CPPUNIT_ASSERT(pText1);
|
|
CPPUNIT_ASSERT_EQUAL(u"Table2:A1"_ustr, pText1->GetText());
|
|
|
|
auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
|
|
CPPUNIT_ASSERT(pPage2);
|
|
const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
|
|
auto pPage2Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage2Objs[0]);
|
|
CPPUNIT_ASSERT(pPage2Fly);
|
|
SwFrame* pTab2 = pPage2Fly->GetLower();
|
|
SwFrame* pRow2 = pTab2->GetLower();
|
|
SwFrame* pCell2 = pRow2->GetLower();
|
|
auto pText2 = dynamic_cast<SwTextFrame*>(pCell2->GetLower());
|
|
CPPUNIT_ASSERT(pText2);
|
|
CPPUNIT_ASSERT_EQUAL(u"Table2:A2"_ustr, pText2->GetText());
|
|
};
|
|
createSwDoc("tdf99140.docx");
|
|
verify();
|
|
saveAndReload(TestFilter::DOCX);
|
|
verify();
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTableMarginAdjustment)
|
|
{
|
|
createSwDoc("table.fodt");
|
|
saveAndReload(TestFilter::DOCX);
|
|
// Writer, (new) Word: margin 0 means table border starts at 0
|
|
// (old) Word: margin 0 means paragraph in table starts at 0
|
|
|
|
auto const xTable(getParagraphOrTable(1));
|
|
// shifted very slightly to account for half of the thin border width, so 4, not 0.
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), getProperty<sal_Int32>(xTable, u"LeftMargin"_ustr));
|
|
|
|
// Now that compatibilityMode is set to 2013's 15 (new), expect the new values,
|
|
// since LO is exporting in the NEW way now instead of the OLD way.
|
|
// This was 55 when using 2007's compatibilityMode of 12 (old)
|
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
|
|
assertXPath(pXmlDoc, "//w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "type", u"dxa");
|
|
assertXPath(pXmlDoc, "//w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "w", u"0");
|
|
|
|
// tdf#143982: automatic tables should export as something better than just left-and-size
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xTable, u"RelativeWidth"_ustr));
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf119760_tableInTablePosition)
|
|
{
|
|
auto verify = [this]() {
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
// For compatibilityMode 15: margin 0 means table border starts at 0,
|
|
// shifted to account for half of the thick border width, so 106, not 0.
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(106), getProperty<sal_Int32>(xTable, u"LeftMargin"_ustr));
|
|
};
|
|
createSwDoc("tdf119760_tableInTablePosition.docx");
|
|
verify();
|
|
saveAndReload(TestFilter::DOCX);
|
|
verify();
|
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
|
|
assertXPath(pXmlDoc, "//w:tbl[1]/w:tr[1]/w:tc[1]/w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "type",
|
|
u"dxa");
|
|
assertXPath(pXmlDoc, "//w:tbl[1]/w:tr[1]/w:tc[1]/w:tbl[1]//w:tblPr[1]/w:tblInd[1]", "w", u"0");
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTableCellMargin, "table-cell-margin.docx")
|
|
{
|
|
sal_Int32 const cellLeftMarginFromOffice[] = { 250, 100, 0, 0 };
|
|
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
uno::Reference<text::XTextTable> xTable1(xTables->getByIndex(i), uno::UNO_QUERY);
|
|
|
|
// Verify left margin of 1st cell :
|
|
// * Office left margins are measured relative to the right of the border
|
|
// * LO left spacing is measured from the center of the border
|
|
uno::Reference<table::XCell> xCell = xTable1->getCellByName(u"A1"_ustr);
|
|
uno::Reference<beans::XPropertySet> xPropSet(xCell, uno::UNO_QUERY_THROW);
|
|
sal_Int32 aLeftMargin = -1;
|
|
xPropSet->getPropertyValue(u"LeftBorderDistance"_ustr) >>= aLeftMargin;
|
|
uno::Any aLeftBorder = xPropSet->getPropertyValue(u"LeftBorder"_ustr);
|
|
table::BorderLine2 aLeftBorderLine;
|
|
aLeftBorder >>= aLeftBorderLine;
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
|
|
"Incorrect left spacing computed from docx cell margin", cellLeftMarginFromOffice[i],
|
|
aLeftMargin - 0.5 * aLeftBorderLine.LineWidth, 1);
|
|
// The 'a' in the fourth table should not be partly hidden by the border
|
|
if (i == 3)
|
|
{
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect cell left padding",
|
|
0.5 * aLeftBorderLine.LineWidth, aLeftMargin, 1);
|
|
// tdf#119885: cell's edit area must touch right border
|
|
sal_Int32 aRightMargin = -1;
|
|
xPropSet->getPropertyValue(u"RightBorderDistance"_ustr) >>= aRightMargin;
|
|
uno::Any aRightBorder = xPropSet->getPropertyValue(u"RightBorder"_ustr);
|
|
table::BorderLine2 aRightBorderLine;
|
|
aRightBorder >>= aRightBorderLine;
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect cell right padding",
|
|
0.5 * aRightBorderLine.LineWidth, aRightMargin, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, TestPuzzleExport)
|
|
{
|
|
createSwDoc("TestPuzzleExport.odt");
|
|
saveAndReload(TestFilter::DOCX);
|
|
// See tdf#148342 for details
|
|
// Create a metafile
|
|
auto pMeta = getSwDocShell()->GetPreviewMetaFile();
|
|
CPPUNIT_ASSERT(pMeta);
|
|
MetafileXmlDump aDumper;
|
|
auto pMetaXml = dumpAndParse(aDumper, *pMeta);
|
|
CPPUNIT_ASSERT(pMetaXml);
|
|
// After parsing check that node...
|
|
auto pXNode
|
|
= getXPathNode(pMetaXml, "/metafile/push/push/push/push[6]/push/push/polypolygon/polygon");
|
|
CPPUNIT_ASSERT(pXNode);
|
|
auto pNode = pXNode->nodesetval->nodeTab[0];
|
|
CPPUNIT_ASSERT(pNode);
|
|
auto it = pNode->children;
|
|
int nCount = 0;
|
|
// .. and count the children
|
|
while (it != nullptr)
|
|
{
|
|
nCount++;
|
|
it = it->next;
|
|
}
|
|
// In case of puzzle there will be so many... Without the fix there was a rectangle with 4 points.
|
|
CPPUNIT_ASSERT_GREATER(300, nCount);
|
|
}
|
|
|
|
// tdf#106742 for DOCX with compatibility level <= 14 (MS Word up to and incl. ver.2010), we should use cell margins when calculating table left border position
|
|
DECLARE_OOXMLEXPORT_TEST(testTablePosition14, "table-position-14.docx")
|
|
{
|
|
sal_Int32 const aXCoordsFromOffice[] = { 2500, -1000, 0, 0 };
|
|
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
uno::Reference<text::XTextTable> xTable1(xTables->getByIndex(i), uno::UNO_QUERY);
|
|
|
|
// Verify X coord
|
|
uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(),
|
|
uno::UNO_QUERY);
|
|
xCtrl->select(uno::Any(xTable1));
|
|
uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl,
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextViewCursor> xCursor = xTextViewCursorSupplier->getViewCursor();
|
|
awt::Point pos = xCursor->getPosition();
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect X coord computed from docx",
|
|
aXCoordsFromOffice[i], pos.X, 1);
|
|
}
|
|
}
|
|
|
|
// tdf#106742 for DOCX with compatibility level > 14 (MS Word since ver.2013),
|
|
// we should NOT use cell margins when calculating table left border position. But we do need to use border width.
|
|
DECLARE_OOXMLEXPORT_TEST(testTablePosition15, "table-position-15.docx")
|
|
{
|
|
sal_Int32 const aXCoordsFromOffice[] = { 2751, -899, 1, 212 };
|
|
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
uno::Reference<text::XTextTable> xTable1(xTables->getByIndex(i), uno::UNO_QUERY);
|
|
|
|
// Verify X coord
|
|
uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(),
|
|
uno::UNO_QUERY);
|
|
xCtrl->select(uno::Any(xTable1));
|
|
uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl,
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextViewCursor> xCursor = xTextViewCursorSupplier->getViewCursor();
|
|
awt::Point pos = xCursor->getPosition();
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect X coord computed from docx",
|
|
aXCoordsFromOffice[i], pos.X, 1);
|
|
}
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf107359, "tdf107359-char-pitch.docx")
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(
|
|
getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY);
|
|
|
|
bool bGridSnapToChars;
|
|
xPropertySet->getPropertyValue(u"GridSnapToChars"_ustr) >>= bGridSnapToChars;
|
|
CPPUNIT_ASSERT_EQUAL(false, bGridSnapToChars);
|
|
|
|
sal_Int32 nRubyHeight;
|
|
xPropertySet->getPropertyValue(u"GridRubyHeight"_ustr) >>= nRubyHeight;
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRubyHeight);
|
|
|
|
sal_Int32 nBaseHeight;
|
|
xPropertySet->getPropertyValue(u"GridBaseHeight"_ustr) >>= nBaseHeight;
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(convertTwipToMm100(18 * 20)), nBaseHeight);
|
|
|
|
sal_Int32 nBaseWidth;
|
|
xPropertySet->getPropertyValue(u"GridBaseWidth"_ustr) >>= nBaseWidth;
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(convertTwipToMm100(24 * 20)), nBaseWidth);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf77236_MissingSolidFill)
|
|
{
|
|
createSwDoc("tdf77236_MissingSolidFill.docx");
|
|
save(TestFilter::DOCX);
|
|
// tdf#77236: solidFill of VML shape was not exported if the colors of line and style were the same
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
assertXPath(
|
|
pXmlDoc,
|
|
"//mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:ln/a:solidFill",
|
|
1);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf105875_VmlShapeRotationWithFlip)
|
|
{
|
|
// tdf#105875: check whether the rotation of the VML bezier shape is ok (with flip too)
|
|
// TODO: fix export too
|
|
|
|
createSwDoc("tdf105875_VmlShapeRotationWithFlip.docx");
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
|
|
xPropertySet->getPropertyValue(u"RotateAngle"_ustr).get<sal_Int32>());
|
|
}
|
|
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(getShape(2), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(
|
|
sal_Int32(220 * 100),
|
|
xPropertySet->getPropertyValue(u"RotateAngle"_ustr).get<sal_Int32>(), 1);
|
|
}
|
|
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(getShape(3), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(
|
|
sal_Int32(320 * 100),
|
|
xPropertySet->getPropertyValue(u"RotateAngle"_ustr).get<sal_Int32>(), 1);
|
|
}
|
|
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(getShape(4), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(
|
|
sal_Int32(140 * 100),
|
|
xPropertySet->getPropertyValue(u"RotateAngle"_ustr).get<sal_Int32>(), 1);
|
|
}
|
|
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(getShape(5), uno::UNO_QUERY_THROW);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(
|
|
sal_Int32(40 * 100),
|
|
xPropertySet->getPropertyValue(u"RotateAngle"_ustr).get<sal_Int32>(), 1);
|
|
}
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf133363)
|
|
{
|
|
createSwDoc("tdf133363.docx");
|
|
save(TestFilter::DOCX);
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
// tdf#133363: remove extra auto space between first and second list elements
|
|
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p[2]/w:pPr/w:spacing", "before",
|
|
u"0");
|
|
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p[3]/w:pPr/w:spacing", "after",
|
|
u"0");
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf138093)
|
|
{
|
|
auto verify = [this](bool bIsExport = false) {
|
|
if (bIsExport)
|
|
{
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XCell> xCell = xTable->getCellByName(u"B1"_ustr);
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xParagraphs
|
|
= xParagraphsAccess->createEnumeration();
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(),
|
|
uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl,
|
|
uno::UNO_QUERY);
|
|
bool bDate{};
|
|
xContentControlProps->getPropertyValue(u"Date"_ustr) >>= bDate;
|
|
CPPUNIT_ASSERT(bDate);
|
|
uno::Reference<container::XEnumerationAccess> xContentControlEnumAccess(xContentControl,
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xContentControlEnum
|
|
= xContentControlEnumAccess->createEnumeration();
|
|
uno::Reference<text::XTextRange> xTextPortionRange(xContentControlEnum->nextElement(),
|
|
uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(u"2017"_ustr, xTextPortionRange->getString());
|
|
}
|
|
else
|
|
{
|
|
SwDoc* pDoc = getSwDoc();
|
|
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
|
|
|
|
::sw::mark::DateFieldmark* pFieldmark
|
|
= dynamic_cast<::sw::mark::DateFieldmark*>(*pMarkAccess->getAllMarksBegin());
|
|
CPPUNIT_ASSERT(pFieldmark);
|
|
CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
|
|
CPPUNIT_ASSERT_EQUAL(u"2017"_ustr, pFieldmark->GetContent());
|
|
}
|
|
};
|
|
|
|
createSwDoc("tdf138093.docx");
|
|
verify();
|
|
saveAndReload(TestFilter::DOCX);
|
|
verify(/*bIsExport*/ true);
|
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
assertXPath(pXmlDoc, "//w:sdt", 3);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf138093B)
|
|
{
|
|
createSwDoc("tdf138093B.docx");
|
|
saveAndReload(TestFilter::DOCX);
|
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
assertXPath(pXmlDoc, "//w:sdt", 3);
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(1), uno::UNO_QUERY);
|
|
uno::Reference<table::XCell> xCell = xTable->getCellByName(u"A1"_ustr);
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
bool bDate{};
|
|
xContentControlProps->getPropertyValue(u"Date"_ustr) >>= bDate;
|
|
CPPUNIT_ASSERT(bDate);
|
|
uno::Reference<container::XEnumerationAccess> xContentControlEnumAccess(xContentControl,
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xContentControlEnum
|
|
= xContentControlEnumAccess->createEnumeration();
|
|
uno::Reference<text::XTextRange> xTextPortionRange(xContentControlEnum->nextElement(),
|
|
uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(u"2019"_ustr, xTextPortionRange->getString());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf131722)
|
|
{
|
|
auto verify = [this](bool bIsExport = false) {
|
|
if (bIsExport)
|
|
{
|
|
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
|
|
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
|
uno::Reference<table::XCell> xCell = xTable->getCellByName(u"A1"_ustr);
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xParagraphs
|
|
= xParagraphsAccess->createEnumeration();
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(),
|
|
uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl,
|
|
uno::UNO_QUERY);
|
|
bool bDate{};
|
|
xContentControlProps->getPropertyValue(u"Date"_ustr) >>= bDate;
|
|
CPPUNIT_ASSERT(bDate);
|
|
uno::Reference<container::XEnumerationAccess> xContentControlEnumAccess(xContentControl,
|
|
uno::UNO_QUERY);
|
|
uno::Reference<container::XEnumeration> xContentControlEnum
|
|
= xContentControlEnumAccess->createEnumeration();
|
|
uno::Reference<text::XTextRange> xTextPortionRange(xContentControlEnum->nextElement(),
|
|
uno::UNO_QUERY);
|
|
CPPUNIT_ASSERT_EQUAL(u"Enter a date here!"_ustr, xTextPortionRange->getString());
|
|
}
|
|
else
|
|
{
|
|
SwDoc* pDoc = getSwDoc();
|
|
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getFieldmarksCount());
|
|
|
|
for (auto aIter = pMarkAccess->getFieldmarksBegin();
|
|
aIter != pMarkAccess->getFieldmarksEnd(); ++aIter)
|
|
{
|
|
::sw::mark::DateFieldmark* pFieldmark
|
|
= dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
|
|
CPPUNIT_ASSERT(pFieldmark);
|
|
CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
|
|
CPPUNIT_ASSERT_EQUAL(u"Enter a date here!"_ustr, pFieldmark->GetContent());
|
|
}
|
|
}
|
|
};
|
|
|
|
createSwDoc("tdf131722.docx");
|
|
verify();
|
|
saveAndReload(TestFilter::DOCX);
|
|
verify(/*bIsExport*/ true);
|
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
|
|
assertXPath(pXmlDoc, "//w:sdt", 4);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf155945)
|
|
{
|
|
createSwDoc("tdf155945.docx");
|
|
|
|
CPPUNIT_ASSERT_EQUAL(3, getParagraphs());
|
|
// Without a fix in place, this would fail with
|
|
// - Expected: 0
|
|
// - Actual : 423
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
|
|
getProperty<sal_Int32>(getParagraph(2), u"ParaBottomMargin"_ustr));
|
|
|
|
//tdf#170003: sectPr emulation: move sectPr bottom margin to the paragraph before the page break
|
|
// Without a fix in place, this was 0.
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(423),
|
|
getProperty<sal_Int32>(getParagraph(1), u"ParaBottomMargin"_ustr));
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf133560)
|
|
{
|
|
createSwDoc("lastEmptyLineWithDirectFormatting.docx");
|
|
|
|
CPPUNIT_ASSERT_EQUAL(4, getParagraphs());
|
|
// Without a fix in place, this would fail with
|
|
// - Expected: 12
|
|
// - Actual : 48
|
|
CPPUNIT_ASSERT_EQUAL(12.0f, getProperty<float>(getParagraph(4), u"CharHeight"_ustr));
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf150408_isLvl_RoundTrip)
|
|
{
|
|
createSwDoc("listWithLgl.docx");
|
|
save(TestFilter::DOCX);
|
|
|
|
// Second level's numbering should use Arabic numbers for first level reference
|
|
auto xPara = getParagraph(1);
|
|
CPPUNIT_ASSERT_EQUAL(u"CH I"_ustr, getProperty<OUString>(xPara, u"ListLabelString"_ustr));
|
|
xPara = getParagraph(2);
|
|
CPPUNIT_ASSERT_EQUAL(u"Sect 1.01"_ustr, getProperty<OUString>(xPara, u"ListLabelString"_ustr));
|
|
xPara = getParagraph(3);
|
|
CPPUNIT_ASSERT_EQUAL(u"CH II"_ustr, getProperty<OUString>(xPara, u"ListLabelString"_ustr));
|
|
xPara = getParagraph(4);
|
|
CPPUNIT_ASSERT_EQUAL(u"Sect 2.01"_ustr, getProperty<OUString>(xPara, u"ListLabelString"_ustr));
|
|
|
|
xmlDocUniquePtr pXml = parseExport(u"word/numbering.xml"_ustr);
|
|
assertXPath(pXml, "/w:numbering/w:abstractNum"); // Only one list
|
|
// The second list level must keep the isLgl element
|
|
assertXPath(pXml, "/w:numbering/w:abstractNum/w:lvl[2]/w:isLgl");
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf156372, "tdf156372.doc")
|
|
{
|
|
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
|
sal_Int32 nHeight
|
|
= getXPath(pXmlDoc, "//page[1]/header/tab/row[1]/infos/bounds", "height").toInt32();
|
|
// Without a fix in place, this would fail with
|
|
// - Expected: 847
|
|
// - Actual : 1327
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(847), nHeight, 5);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, getPages());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf156548)
|
|
{
|
|
// Given a document using two bookmarks with similar names longer than 40 characters
|
|
createSwDoc("longBookmarkName.fodt");
|
|
saveAndReload(TestFilter::DOCX);
|
|
|
|
// After the export, the names must be no longer than 40 characters; they must be unique;
|
|
// and the hyperlinks must use the same names, to still point to the correct targets:
|
|
|
|
{
|
|
// 1st paragraph - hyperlink to 4th paragraph
|
|
auto sURL = getProperty<OUString>(getRun(getParagraph(1), 1), u"HyperLinkURL"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"#A_bookmark_name_longer_than_forty_charac"_ustr, sURL);
|
|
// 4th paragraph - a bookmark
|
|
auto xBookmark = getProperty<uno::Reference<container::XNamed>>(getRun(getParagraph(4), 1),
|
|
u"Bookmark"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"A_bookmark_name_longer_than_forty_charac"_ustr,
|
|
xBookmark->getName());
|
|
}
|
|
|
|
{
|
|
// 2nd paragraph - hyperlink to 5th paragraph
|
|
auto sURL = getProperty<OUString>(getRun(getParagraph(2), 1), u"HyperLinkURL"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"#A_bookmark_name_longer_than_forty_chara1"_ustr, sURL);
|
|
// 5th paragraph - a bookmark
|
|
auto xBookmark = getProperty<uno::Reference<container::XNamed>>(getRun(getParagraph(5), 1),
|
|
u"Bookmark"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"A_bookmark_name_longer_than_forty_chara1"_ustr,
|
|
xBookmark->getName());
|
|
}
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf157136)
|
|
{
|
|
// Given a document with two content controls - one block, one inline
|
|
createSwDoc("tdf157136_TwoContentControls.docx");
|
|
|
|
// Both of them must import with the correct character style
|
|
|
|
{
|
|
// 1st paragraph - block content control
|
|
auto xRun = getRun(getParagraph(1), 1);
|
|
auto xContentControl
|
|
= getProperty<css::uno::Reference<css::text::XTextRange>>(xRun, u"ContentControl"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"Click or tap here to enter text."_ustr,
|
|
xContentControl->getString());
|
|
// Without the fix in place, this would fail with
|
|
// - Expected: Placeholder Text
|
|
// - Actual :
|
|
CPPUNIT_ASSERT_EQUAL(u"Placeholder Text"_ustr,
|
|
getProperty<OUString>(xRun, u"CharStyleName"_ustr));
|
|
}
|
|
|
|
{
|
|
// 2nd paragraph - inline content control
|
|
auto xRun = getRun(getParagraph(2), 1);
|
|
auto xContentControl
|
|
= getProperty<css::uno::Reference<css::text::XTextRange>>(xRun, u"ContentControl"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"Click or tap here to enter text."_ustr,
|
|
xContentControl->getString());
|
|
CPPUNIT_ASSERT_EQUAL(u"Placeholder Text"_ustr,
|
|
getProperty<OUString>(xRun, u"CharStyleName"_ustr));
|
|
}
|
|
|
|
// Test the same after round-trip
|
|
saveAndReload(TestFilter::DOCX);
|
|
|
|
{
|
|
// 1st paragraph - becomes inline content control after roundtrip
|
|
auto xRun = getRun(getParagraph(1), 1);
|
|
auto xContentControl
|
|
= getProperty<css::uno::Reference<css::text::XTextRange>>(xRun, u"ContentControl"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"Click or tap here to enter text."_ustr,
|
|
xContentControl->getString());
|
|
CPPUNIT_ASSERT_EQUAL(u"Placeholder Text"_ustr,
|
|
getProperty<OUString>(xRun, u"CharStyleName"_ustr));
|
|
}
|
|
|
|
{
|
|
// 2nd paragraph - inline content control
|
|
auto xRun = getRun(getParagraph(2), 1);
|
|
auto xContentControl
|
|
= getProperty<css::uno::Reference<css::text::XTextRange>>(xRun, u"ContentControl"_ustr);
|
|
CPPUNIT_ASSERT_EQUAL(u"Click or tap here to enter text."_ustr,
|
|
xContentControl->getString());
|
|
CPPUNIT_ASSERT_EQUAL(u"Placeholder Text"_ustr,
|
|
getProperty<OUString>(xRun, u"CharStyleName"_ustr));
|
|
}
|
|
}
|
|
|
|
//Tests for support of fallback for ECMA-376 1st ed to merge the title value with descr attribute
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf148952_2007)
|
|
{
|
|
//Given a document with 1 image (with name, alt title and description field populated) in odt format
|
|
createSwDoc("tdf148952.odt");
|
|
|
|
//Export it to MS word 2007(.docx) format
|
|
saveAndReload(TestFilter::DOCX_2007);
|
|
|
|
// Checks the number of images in the docx file
|
|
CPPUNIT_ASSERT_EQUAL(1, getShapes());
|
|
|
|
uno::Reference<beans::XPropertySet> xImage(getShape(1), uno::UNO_QUERY);
|
|
|
|
// Check if alt title value is appended to description
|
|
OUString descr;
|
|
xImage->getPropertyValue(u"Description"_ustr) >>= descr;
|
|
CPPUNIT_ASSERT_EQUAL(u"Black\nShapes"_ustr, descr);
|
|
|
|
// Check if alt title field is empty
|
|
OUString title;
|
|
xImage->getPropertyValue(u"Title"_ustr) >>= title;
|
|
CPPUNIT_ASSERT_EQUAL(u""_ustr, title);
|
|
}
|
|
|
|
//Tests for support of title attribute for ECMA-376 2nd ed and above
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf148952_2010)
|
|
{
|
|
//Given a document with 1 image (with name, alt title and description field populated) in odt format
|
|
createSwDoc("tdf148952.odt");
|
|
|
|
//Export it to MS word 2010-365 (.docx) format
|
|
saveAndReload(TestFilter::DOCX);
|
|
|
|
// Checks the number of images in the docx file
|
|
CPPUNIT_ASSERT_EQUAL(1, getShapes());
|
|
|
|
uno::Reference<beans::XPropertySet> xImage(getShape(1), uno::UNO_QUERY);
|
|
|
|
// Check if description field contains same value after export
|
|
OUString descr;
|
|
xImage->getPropertyValue(u"Description"_ustr) >>= descr;
|
|
CPPUNIT_ASSERT_EQUAL(u"Shapes"_ustr, descr);
|
|
|
|
// Check if alt title field contains same value after export
|
|
OUString title;
|
|
xImage->getPropertyValue(u"Title"_ustr) >>= title;
|
|
CPPUNIT_ASSERT_EQUAL(u"Black"_ustr, title);
|
|
}
|
|
|
|
DECLARE_OOXMLEXPORT_TEST(testTdf153196, "A019_min.docx")
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPageStyle;
|
|
getStyles("PageStyles")->getByName("Converted1") >>= xPageStyle;
|
|
sal_Int32 nLeftMargin{};
|
|
xPageStyle->getPropertyValue("LeftMargin") >>= nLeftMargin;
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
// - Expected: 4265
|
|
// - Actual : 0
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4265), nLeftMargin);
|
|
sal_Int32 nRightMargin{};
|
|
xPageStyle->getPropertyValue("RightMargin") >>= nRightMargin;
|
|
// - Expected: 0
|
|
// - Actual : 4265
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nRightMargin);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf168886_EmfPassThrough)
|
|
{
|
|
// tdf#168886: EMF pasted from OriginPro must be saved as original .emf bytes
|
|
// in DOCX, not re-exported through EMFWriter. Re-export changes the EMF header
|
|
// reference device metrics, causing scaling errors on HiDPI displays.
|
|
createSwDoc("tdf168886_emf_origin.odt");
|
|
|
|
// Verify image dimensions preserved after DOCX roundtrip (±0.5%)
|
|
saveAndReload(TestFilter::DOCX);
|
|
uno::Reference<drawing::XShape> xShape = getShape(1);
|
|
awt::Size aSize = xShape->getSize();
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(17000.0, static_cast<double>(aSize.Width), 85.0);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(13019.0, static_cast<double>(aSize.Height), 65.0);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf168237_EmfExcelPassThrough)
|
|
{
|
|
// tdf#168237: EMF from Excel uses printer DC (600 DPI) as reference device.
|
|
// Without pass-through, EMFWriter re-exports at VDev DPI, causing ~76% shrink.
|
|
createSwDoc("tdf168237_emf_excel.odt");
|
|
|
|
saveAndReload(TestFilter::DOCX);
|
|
uno::Reference<drawing::XShape> xShape = getShape(1);
|
|
awt::Size aSize = xShape->getSize();
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(16002.0, static_cast<double>(aSize.Width), 80.0);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(9001.0, static_cast<double>(aSize.Height), 45.0);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf168237_EmfExcelShear)
|
|
{
|
|
// tdf#168237: Excel EMF with non-standard aspect ratio (portrait).
|
|
createSwDoc("tdf168237_emf_excel_smaller_taller_shear.odt");
|
|
|
|
saveAndReload(TestFilter::DOCX);
|
|
uno::Reference<drawing::XShape> xShape = getShape(1);
|
|
awt::Size aSize = xShape->getSize();
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8962), aSize.Width);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(10504), aSize.Height);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(Test, testTdf168237_EmfCalcShear)
|
|
{
|
|
// tdf#168237: Calc EMF with different device context than Excel.
|
|
createSwDoc("tdf168237_emf_calc_smaller_taller_shear.odt");
|
|
|
|
saveAndReload(TestFilter::DOCX);
|
|
uno::Reference<drawing::XShape> xShape = getShape(1);
|
|
awt::Size aSize = xShape->getSize();
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11456), aSize.Width);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(10502), aSize.Height);
|
|
}
|
|
|
|
CPPUNIT_PLUGIN_IMPLEMENT();
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|