1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 */ 9 10 #include <swmodeltestbase.hxx> 11 12 #include <com/sun/star/text/XTextColumns.hpp> 13 #include <com/sun/star/text/XTextTablesSupplier.hpp> 14 #include <com/sun/star/text/XTextSectionsSupplier.hpp> 15 #include <com/sun/star/graphic/XGraphic.hpp> 16 17 #include <editeng/boxitem.hxx> 18 #include <editeng/lrspitem.hxx> 19 #include <editeng/ulspitem.hxx> 20 #include <sfx2/docfile.hxx> 21 #include <sfx2/docfilt.hxx> 22 23 #include <ndgrf.hxx> 24 #include <docsh.hxx> 25 #include <unotxdoc.hxx> 26 #include <viewsh.hxx> 27 #include <IDocumentLayoutAccess.hxx> 28 29 // tests should only be added to ww8IMPORT *if* they fail round-tripping in ww8EXPORT 30 31 class Test : public SwModelTestBase 32 { 33 public: Test()34 Test() : SwModelTestBase("/sw/qa/extras/ww8import/data/", "MS Word 97") 35 { 36 } 37 }; 38 39 #define DECLARE_WW8IMPORT_TEST(TestName, filename) DECLARE_SW_IMPORT_TEST(TestName, filename, nullptr, Test) 40 41 DECLARE_WW8IMPORT_TEST(testFloatingTableSectionMargins, "floating-table-section-margins.doc") 42 { 43 sal_Int32 pageLeft = parseDump("/root/page[2]/infos/bounds", "left").toInt32(); 44 sal_Int32 pageWidth = parseDump("/root/page[2]/infos/bounds", "width").toInt32(); 45 sal_Int32 tableLeft = parseDump("//tab/infos/bounds", "left").toInt32(); 46 sal_Int32 tableWidth = parseDump("//tab/infos/bounds", "width").toInt32(); 47 CPPUNIT_ASSERT( pageWidth > 0 ); 48 CPPUNIT_ASSERT( tableWidth > 0 ); 49 // The table's resulting position should be roughly centered. 50 CPPUNIT_ASSERT( abs(( pageLeft + pageWidth / 2 ) - ( tableLeft + tableWidth / 2 )) < 20 ); 51 52 uno::Reference<beans::XPropertySet> xTextSection = getProperty< uno::Reference<beans::XPropertySet> >(getParagraph(2), "TextSection"); 53 CPPUNIT_ASSERT(xTextSection.is()); 54 uno::Reference<text::XTextColumns> xTextColumns = getProperty< uno::Reference<text::XTextColumns> >(xTextSection, "TextColumns"); 55 OUString pageStyleName = getProperty<OUString>(getParagraph(2), "PageStyleName"); 56 uno::Reference<style::XStyle> pageStyle( getStyles("PageStyles")->getByName(pageStyleName), uno::UNO_QUERY); 57 uno::Reference<beans::XPropertySet> xPageStyle(getStyles("PageStyles")->getByName(pageStyleName), uno::UNO_QUERY); 58 uno::Reference<text::XTextColumns> xPageColumns = getProperty< uno::Reference<text::XTextColumns> >(xPageStyle, "TextColumns"); 59 60 //either one or the other should get the column's, not both. 61 CPPUNIT_ASSERT( xTextColumns->getColumnCount() != xPageColumns->getColumnCount()); 62 } 63 64 DECLARE_WW8IMPORT_TEST(testN816593, "n816593.doc") 65 { 66 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY); 67 uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY); 68 // Make sure that even if we import the two tables as non-floating, we 69 // still consider them different, and not merge them. 70 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount()); 71 } 72 73 DECLARE_WW8IMPORT_TEST(testBnc875715, "bnc875715.doc") 74 { 75 uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY); 76 uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY); 77 // Was incorrectly set as -1270. 78 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xSections->getByIndex(0), "SectionLeftMargin")); 79 } 80 81 DECLARE_WW8IMPORT_TEST(testFloatingTableSectionColumns, "floating-table-section-columns.doc") 82 { 83 OUString tableWidth = parseDump("/root/page[1]/body/section/column[2]/body/txt/anchored/fly/tab/infos/bounds", "width"); 84 // table width was restricted by a column 85 CPPUNIT_ASSERT( tableWidth.toInt32() > 10000 ); 86 } 87 88 DECLARE_WW8IMPORT_TEST(testTdf124601, "tdf124601.doc") 89 { 90 // Without the accompanying fix in place, this test would have failed, as the importer lost the 91 // fLayoutInCell shape property for wrap-though shapes. 92 CPPUNIT_ASSERT(getProperty<bool>(getShapeByName(u"Grafik 18"), "IsFollowingTextFlow")); 93 CPPUNIT_ASSERT(getProperty<bool>(getShapeByName(u"Grafik 19"), "IsFollowingTextFlow")); 94 } 95 96 DECLARE_WW8IMPORT_TEST(testImageLazyRead, "image-lazy-read.doc") 97 { 98 auto xGraphic = getProperty<uno::Reference<graphic::XGraphic>>(getShape(1), "Graphic"); 99 Graphic aGraphic(xGraphic); 100 // This failed, import loaded the graphic, it wasn't lazy-read. 101 CPPUNIT_ASSERT(!aGraphic.isAvailable()); 102 } 103 104 DECLARE_WW8IMPORT_TEST(testImageLazyRead0size, "image-lazy-read-0size.doc") 105 { 106 // Load a document with a single bitmap in it: it's declared as a WMF one, but actually a TGA 107 // bitmap. 108 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); 109 SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); 110 SwNode* pNode = pDoc->GetNodes()[6]; 111 SwGrfNode* pGrfNode = pNode->GetGrfNode(); 112 CPPUNIT_ASSERT(pGrfNode); 113 // Without the accompanying fix in place, this test would have failed with: 114 // - Expected: 7590x10440 115 // - Actual : 0x0 116 // i.e. the size was 0, even if the actual bitmap had a non-0 size. 117 CPPUNIT_ASSERT_EQUAL(Size(7590, 10440), pGrfNode->GetTwipSize()); 118 } 119 120 DECLARE_WW8IMPORT_TEST(testTdf106799, "tdf106799.doc") 121 { 122 // Ensure that all text portions are calculated before testing. 123 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); 124 CPPUNIT_ASSERT(pTextDoc); 125 SwViewShell* pViewShell 126 = pTextDoc->GetDocShell()->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell(); 127 CPPUNIT_ASSERT(pViewShell); 128 pViewShell->Reformat(); 129 130 sal_Int32 const nCellWidths[3][4] = { { 9528, 0, 0, 0 },{ 2382, 2382, 2382, 2382 },{ 2382, 2382, 2382, 2382 } }; 131 sal_Int32 const nCellTxtLns[3][4] = { { 1, 0, 0, 0 },{ 1, 0, 0, 0},{ 1, 1, 1, 1 } }; 132 // Table was distorted because of missing sprmPFInnerTableCell at paragraph marks (0x0D) with sprmPFInnerTtp 133 for (sal_Int32 nRow : { 0, 1, 2 }) 134 for (sal_Int32 nCell : { 0, 1, 2, 3 }) 135 { 136 OString cellXPath("/root/page/body/tab/row/cell/tab/row[" + OString::number(nRow+1) + "]/cell[" + OString::number(nCell+1) + "]/"); 137 CPPUNIT_ASSERT_EQUAL_MESSAGE(cellXPath.getStr(), nCellWidths[nRow][nCell], parseDump(cellXPath + "infos/bounds", "width").toInt32()); 138 if (nCellTxtLns[nRow][nCell] != 0) 139 CPPUNIT_ASSERT_EQUAL_MESSAGE(cellXPath.getStr(), nCellTxtLns[nRow][nCell], parseDump(cellXPath + "txt/Text", "nLength").toInt32()); 140 } 141 } 142 143 DECLARE_WW8IMPORT_TEST(testTdf121734, "tdf121734.doc") 144 { 145 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); 146 CPPUNIT_ASSERT(pTextDoc); 147 SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); 148 SwPosFlyFrames aPosFlyFrames = pDoc->GetAllFlyFormats(nullptr, false); 149 // There is only one fly frame in the document: the one with the imported floating table 150 CPPUNIT_ASSERT_EQUAL(size_t(1), aPosFlyFrames.size()); 151 for (const auto& rPosFlyFrame : aPosFlyFrames) 152 { 153 const SwFrameFormat& rFormat = rPosFlyFrame->GetFormat(); 154 const SfxPoolItem* pItem = nullptr; 155 156 // The LR and UL spacings and borders must all be set explicitly; 157 // spacings and border distances must be 0; borders must be absent. 158 159 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, rFormat.GetItemState(RES_LR_SPACE, false, &pItem)); 160 auto pLR = static_cast<const SvxLRSpaceItem*>(pItem); 161 CPPUNIT_ASSERT(pLR); 162 CPPUNIT_ASSERT_EQUAL(tools::Long(0), pLR->GetLeft()); 163 CPPUNIT_ASSERT_EQUAL(tools::Long(0), pLR->GetRight()); 164 165 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, rFormat.GetItemState(RES_UL_SPACE, false, &pItem)); 166 auto pUL = static_cast<const SvxULSpaceItem*>(pItem); 167 CPPUNIT_ASSERT(pUL); 168 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pUL->GetUpper()); 169 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pUL->GetLower()); 170 171 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, rFormat.GetItemState(RES_BOX, false, &pItem)); 172 auto pBox = static_cast<const SvxBoxItem*>(pItem); 173 CPPUNIT_ASSERT(pBox); 174 for (auto eLine : { SvxBoxItemLine::TOP, SvxBoxItemLine::BOTTOM, 175 SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT }) 176 { 177 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pBox->GetDistance(eLine)); 178 CPPUNIT_ASSERT(!pBox->GetLine(eLine)); 179 } 180 } 181 } 182 183 DECLARE_WW8IMPORT_TEST(testTdf125281, "tdf125281.doc") 184 { 185 #if !defined(_WIN32) 186 // Windows fails with actual == 26171 for some reason; also lazy load isn't lazy in Windows 187 // debug builds, reason is not known at the moment. 188 189 // Load a .doc file which has an embedded .emf image. 190 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); 191 SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); 192 SwNode* pNode = pDoc->GetNodes()[6]; 193 CPPUNIT_ASSERT(pNode->IsGrfNode()); 194 SwGrfNode* pGrfNode = pNode->GetGrfNode(); 195 const Graphic& rGraphic = pGrfNode->GetGrf(); 196 197 // Without the accompanying fix in place, this test would have failed, as pref size was 0 till 198 // an actual Paint() was performed (and even then, it was wrong). 199 tools::Long nExpected = 25664; 200 CPPUNIT_ASSERT_EQUAL(nExpected, rGraphic.GetPrefSize().getWidth()); 201 202 // Without the accompanying fix in place, this test would have failed, as setting the pref size 203 // swapped the image in. 204 CPPUNIT_ASSERT(!rGraphic.isAvailable()); 205 #endif 206 } 207 208 DECLARE_WW8IMPORT_TEST(testTdf122425_1, "tdf122425_1.doc") 209 { 210 // This is for header text in case we use a hack for fixed-height headers 211 // (see SwWW8ImplReader::Read_HdFtTextAsHackedFrame) 212 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); 213 CPPUNIT_ASSERT(pTextDoc); 214 SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); 215 SwPosFlyFrames aPosFlyFrames = pDoc->GetAllFlyFormats(nullptr, false); 216 // There are two fly frames in the document: for first page's header, and for other pages' 217 CPPUNIT_ASSERT_EQUAL(size_t(2), aPosFlyFrames.size()); 218 for (const auto& rPosFlyFrame : aPosFlyFrames) 219 { 220 const SwFrameFormat& rFormat = rPosFlyFrame->GetFormat(); 221 const SfxPoolItem* pItem = nullptr; 222 223 // The LR and UL spacings and borders must all be set explicitly; 224 // spacings and border distances must be 0; borders must be absent 225 226 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, rFormat.GetItemState(RES_LR_SPACE, false, &pItem)); 227 auto pLR = static_cast<const SvxLRSpaceItem*>(pItem); 228 CPPUNIT_ASSERT(pLR); 229 CPPUNIT_ASSERT_EQUAL(tools::Long(0), pLR->GetLeft()); 230 CPPUNIT_ASSERT_EQUAL(tools::Long(0), pLR->GetRight()); 231 232 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, rFormat.GetItemState(RES_UL_SPACE, false, &pItem)); 233 auto pUL = static_cast<const SvxULSpaceItem*>(pItem); 234 CPPUNIT_ASSERT(pUL); 235 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pUL->GetUpper()); 236 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pUL->GetLower()); 237 238 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, rFormat.GetItemState(RES_BOX, false, &pItem)); 239 auto pBox = static_cast<const SvxBoxItem*>(pItem); 240 CPPUNIT_ASSERT(pBox); 241 for (auto eLine : { SvxBoxItemLine::TOP, SvxBoxItemLine::BOTTOM, 242 SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT }) 243 { 244 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pBox->GetDistance(eLine)); 245 CPPUNIT_ASSERT(!pBox->GetLine(eLine)); 246 } 247 } 248 249 //tdf#139495: without the fix, a negative number was converted into a uInt16, overflowing to 115501 250 auto nDist = getProperty<sal_uInt32>(getStyles("PageStyles")->getByName("Standard"), "HeaderBodyDistance"); 251 CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), nDist); 252 } 253 254 DECLARE_WW8IMPORT_TEST(testTdf110987, "tdf110987") 255 { 256 // The input document is an empty .doc, but without file name 257 // extension. Check that it was loaded as a normal .doc document, 258 // and not a template. 259 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); 260 CPPUNIT_ASSERT(pTextDoc); 261 OUString sFilterName = pTextDoc->GetDocShell()->GetMedium()->GetFilter()->GetFilterName(); 262 CPPUNIT_ASSERT(sFilterName != "MS Word 97 Vorlage"); 263 } 264 265 DECLARE_WW8IMPORT_TEST(testTdf120761_zOrder, "tdf120761_zOrder.doc") 266 { 267 //The blue shape was covering everything (highest zorder = 2) instead of the lowest(0) 268 uno::Reference<drawing::XShape> xShape(getShapeByName(u"Picture 2"), uno::UNO_QUERY); 269 CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), getProperty<sal_uInt32>(xShape, "ZOrder")); 270 } 271 272 273 // tests should only be added to ww8IMPORT *if* they fail round-tripping in ww8EXPORT 274 275 CPPUNIT_PLUGIN_IMPLEMENT(); 276 277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 278