/* -*- 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/.
*/
namespace
{
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedPNGShapeAsOLE)
{ // Given a document with an image shape:
createSwDoc();
uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XShape> xShape(
xFactory->createInstance(u"com.sun.star.drawing.GraphicObjectShape"_ustr), uno::UNO_QUERY);
xShape->setSize(awt::Size(10000, 10000));
uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
xShapeProps->setPropertyValue(u"GraphicURL"_ustr, uno::Any(createFileURL(u"ole2.png")));
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
xDrawPageSupplier->getDrawPage()->add(xShape);
// When exporting to XHTML:
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"ExportImagesAsOLE"_ustr, true),
};
saveWithParams(aStoreProperties);
// Then make sure the PNG is embedded with an RTF wrapper:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - Expected: text/rtf // - Actual : image/png // i.e. the OLE wrapper around the PNG was missing.
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", u"text/rtf");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNG)
{ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. if (!IsDefaultDPI()) return; // Given a document with a shape:
createSwDoc();
uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XShape> xShape(
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr), uno::UNO_QUERY);
xShape->setSize(awt::Size(10000, 10000));
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
xDrawPageSupplier->getDrawPage()->add(xShape);
// When exporting to XHTML:
ExportToReqif();
// Then make sure the shape is embedded as a PNG:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - Expected: image/png // - Actual : image/x-vclgraphic // i.e. the result was invalid ReqIF.
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", u"image/png");
// Then check the pixel size of the shape:
Size aPixelSize(Application::GetDefaultDevice()->LogicToPixel(Size(10000, 10000),
MapMode(MapUnit::Map100thMM))); // Without the accompanying fix in place, this test would have failed with: // - no attribute 'width' exist // i.e. shapes had no width.
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "width",
OUString::number(aPixelSize.getWidth()));
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testShapeAsImageHtml)
{ // Given a document with a shape:
createSwDoc();
uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XShape> xShape(
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr), uno::UNO_QUERY);
xShape->setSize(awt::Size(5080, 2540));
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
xDrawPageSupplier->getDrawPage()->add(xShape);
// When exporting to plain HTML:
saveAndReload(u"HTML (StarWriter)"_ustr);
// Without the accompanying fix in place, this test would have failed with: // - Expected: // - Actual : /> // i.e. the output was not well-formed.
CPPUNIT_ASSERT_EQUAL(u" "_ustr, getParagraph(1)->getString());
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testJson)
{ // Given a document with a shape:
createSwDoc();
uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XShape> xShape(
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr), uno::UNO_QUERY);
xShape->setSize(awt::Size(2540, 2540));
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
xDrawPageSupplier->getDrawPage()->add(xShape);
// When exporting to HTML, and specifying options as JSON:
setFilterOptions(u"{\"XhtmlNs\":{\"type\":\"string\", \"value\":\"reqif-xhtml\"}," "\"ShapeDPI\":{\"type\":\"long\",\"value\":\"192\"}}"_ustr);
save(u"HTML (StarWriter)"_ustr);
// Then make sure those options are not ignored: // Without the accompanying fix in place, this test would have failed, as GetPngPath() expects // XML output, but xhtmlns=reqif-xhtml was ignored.
OUString aPngUrl = GetPngPath();
SvFileStream aFileStream(aPngUrl, StreamMode::READ);
GraphicDescriptor aDescriptor(aFileStream, nullptr);
aDescriptor.Detect(/*bExtendedInfo=*/true); // Make sure that the increased DPI is taken into account:
tools::Long nExpected = 192;
CPPUNIT_ASSERT_EQUAL(nExpected, aDescriptor.GetSizePixel().getWidth());
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNGCustomDPI)
{ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. if (!IsDefaultDPI()) return; // Given a document with a shape:
createSwDoc();
uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XShape> xShape(
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr), uno::UNO_QUERY);
xShape->setSize(awt::Size(5080, 2540));
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
xDrawPageSupplier->getDrawPage()->add(xShape);
sal_Int32 nDPI = 600;
// When exporting to XHTML:
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"ShapeDPI"_ustr, nDPI),
};
saveWithParams(aStoreProperties);
// Then make sure the shape is embedded as a PNG:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", u"image/png");
// Then check the pixel size of the shape:
Size aPixelSize(Application::GetDefaultDevice()->LogicToPixel(Size(5080, 2540),
MapMode(MapUnit::Map100thMM)));
tools::Long nPNGWidth = 1200;
OUString aPngUrl = GetPngPath();
SvFileStream aFileStream(aPngUrl, StreamMode::READ);
GraphicDescriptor aDescriptor(aFileStream, nullptr);
aDescriptor.Detect(/*bExtendedInfo=*/true); // Without the accompanying fix in place, this test would have failed with: // - Expected: 1200 // - Actual : 1000 // i.e. first setting a double DPI didn't result in larger pixel width of the PNG, then it was // limited to 1000 pixels (because the pixel limit was 500k).
CPPUNIT_ASSERT_EQUAL(nPNGWidth, aDescriptor.GetSizePixel().getWidth());
// Then make sure the shape's logic size (in CSS pixels) don't change:
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "width",
OUString::number(aPixelSize.getWidth()));
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOleBmpTransparent)
{ // Given a document with a transparent image:
createSwDoc();
uno::Sequence<beans::PropertyValue> aArgs = {
comphelper::makePropertyValue(u"FileName"_ustr, createFileURL(u"transparent.png")),
};
dispatchCommand(mxComponent, u".uno:InsertGraphic"_ustr, aArgs);
// When exporting to reqif with ExportImagesAsOLE=true:
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"ExportImagesAsOLE"_ustr, true),
};
saveWithParams(aStoreProperties);
// Then make sure the transparent pixel turns into white:
SvMemoryStream aOle1;
ParseOle1FromRtfUrl(GetOlePath(), aOle1);
OLE1Reader aOle1Reader(aOle1);
SvMemoryStream aBitmapStream(aOle1Reader.m_aNativeData.data(), aOle1Reader.m_aNativeData.size(),
StreamMode::READ);
Bitmap aBitmap;
ReadDIB(aBitmap, aBitmapStream, /*bFileHeader=*/true);
Size aBitmapSize = aBitmap.GetSizePixel();
BitmapEx aBitmapEx(aBitmap);
Color nActualColor
= aBitmapEx.GetPixelColor(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1); // Without the accompanying fix in place, this test would have failed with: // - Expected: Color: R:255 G:255 B:255 A:0 // - Actual : Color: R:0 G:0 B:0 A:0 // i.e. the bitmap without an alpha channel was black, not white.
CPPUNIT_ASSERT_EQUAL(COL_WHITE, nActualColor);
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testOleEmfPreviewToHtml)
{ // Given a document containing an embedded object, with EMF preview:
createSwDoc("ole2.odt");
// When exporting to HTML:
ExportToHTML();
// Then make sure the <img> tag has matching file extension and data:
htmlDocUniquePtr pDoc = parseHtml(maTempFile);
OUString aPath = getXPath(pDoc, "/html/body/p/img", "src"); // Without the accompanying fix in place, this test would have failed, as aPath was // ole_html_3978e5f373402b43.JPG, with EMF data.
CPPUNIT_ASSERT(aPath.endsWith("gif"));
}
// Then make sure that there is a <li> between the outer and the inner <ol>:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - XPath '//reqif-xhtml:ol/reqif-xhtml:li/reqif-xhtml:ol/reqif-xhtml:li/reqif-xhtml:p' not found // i.e. the <li> inside the outer <ol> was missing.
assertXPathContent(
pXmlDoc, "//reqif-xhtml:ol/reqif-xhtml:li/reqif-xhtml:ol/reqif-xhtml:li/reqif-xhtml:p",
u"second");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTrailingLineBreak)
{ // Given a document with a trailing line-break:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Insert(u"test\n"_ustr);
// When exporting to reqif-xhtml:
ExportToReqif();
// Then make sure that we still have a single line-break:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - Expected: 1 // - Actual : 2 // - XPath '//reqif-xhtml:br' number of nodes is incorrect
assertXPath(pXmlDoc, "//reqif-xhtml:br", 1);
// Then test the import side: // Given an empty document: // When importing a <br> from reqif-xhtml:
ImportFromReqif(maTempFile.GetURL());
// Then make sure that line-break is not lost:
pWrtShell = getSwDocShell()->GetWrtShell();
OUString aActual = pWrtShell->GetCursor()->GetPointNode().GetTextNode()->GetText(); // Without the accompanying fix in place, this test would have failed, as the trailing // line-break was lost.
CPPUNIT_ASSERT_EQUAL(u"test\n"_ustr, aActual);
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testLeadingTab)
{ // Given a document with leading tabs:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Insert(u"\t first"_ustr);
pWrtShell->SplitNode();
pWrtShell->Insert(u"\t\t second"_ustr);
pWrtShell->SplitNode();
pWrtShell->Insert(u"thi \t rd"_ustr);
// When exporting to HTML, using LeadingTabWidth=2:
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"LeadingTabWidth"_ustr, static_cast<sal_Int32>(2)),
};
saveWithParams(aStoreProperties);
// Then make sure that leading tabs are replaced with 2 nbsps:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - Expected: <nbsp><nbsp><space>first // - Actual : <tab><space>first // i.e. the leading tab was not replaced by 2 nbsps.
assertXPathContent(pXmlDoc, "//reqif-xhtml:p[1]", u"\xa0\xa0 first"); // Test a leading tab that is not at the start of the paragraph:
assertXPathContent(pXmlDoc, "//reqif-xhtml:p[2]", u"\xa0\xa0\xa0\xa0 second"); // Test a tab which is not leading:
assertXPathContent(pXmlDoc, "//reqif-xhtml:p[3]", u"thi \t rd");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testLeadingTabHTML)
{ // Given a document with leading tabs:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Insert(u"\t test"_ustr);
// When exporting to plain HTML, using LeadingTabWidth=2:
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"LeadingTabWidth"_ustr, static_cast<sal_Int32>(2)),
};
saveWithParams(aStoreProperties);
// Then make sure that leading tabs are replaced with 2 nbsps:
htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
CPPUNIT_ASSERT(pHtmlDoc); // Without the accompanying fix in place, this test would have failed with: // - Expected: <newline><nbsp><nbsp><space>test // - Actual : <newline><tab><space>test // i.e. the leading tab was not replaced by 2 nbsps.
assertXPathContent(pHtmlDoc, "/html/body/p", u"\n\xa0\xa0 test");
}
CPPUNIT_TEST_FIXTURE(HtmlExportTest, testClearingBreak)
{ auto verify = [this]() {
uno::Reference<container::XEnumerationAccess> xParagraph(getParagraph(1), uno::UNO_QUERY);
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
uno::Reference<beans::XPropertySet> xPortion;
OUString aPortionType; while (true)
{ // Ignore leading comments.
xPortion.set(xPortions->nextElement(), uno::UNO_QUERY);
xPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType; if (aPortionType != "Annotation")
{ break;
}
} // Skip "foo". // Without the accompanying fix in place, this test would have failed with: // An uncaught exception of type com.sun.star.container.NoSuchElementException // i.e. the first para was just comments + text portion, the clearing break was lost.
xPortion.set(xPortions->nextElement(), uno::UNO_QUERY);
xPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
CPPUNIT_ASSERT_EQUAL(u"LineBreak"_ustr, aPortionType);
uno::Reference<text::XTextContent> xLineBreak;
xPortion->getPropertyValue(u"LineBreak"_ustr) >>= xLineBreak;
sal_Int16 eClear{};
uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
xLineBreakProps->getPropertyValue(u"Clear"_ustr) >>= eClear;
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(SwLineBreakClear::ALL), eClear);
};
// Given a document with an at-para anchored image + a clearing break: // When loading that file:
createSwWebDoc("clearing-break.html"); // Then make sure that the clear property of the break is not ignored:
verify();
saveAndReload(mpFilter); // Make sure that the clear property of the break is not ignored during export:
verify();
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTableBackground)
{ // Given a document with two tables: first stable has a background, second table has a // background in its first row:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SwInsertTableOptions aInsertTableOptions(SwInsertTableFlags::DefaultBorder, /*nRowsToRepeat=*/0);
pWrtShell->InsertTable(aInsertTableOptions, /*nRows=*/1, /*nCols=*/1);
pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
SvxBrushItem aBrush(COL_LIGHTRED, RES_BACKGROUND);
pWrtShell->SetTabBackground(aBrush);
pWrtShell->Down(/*bSelect=*/false);
pWrtShell->SplitNode();
pWrtShell->InsertTable(aInsertTableOptions, /*nRows=*/2, /*nCols=*/1);
pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
aBrush.SetColor(COL_LIGHTGREEN);
pWrtShell->SetRowBackground(aBrush);
pWrtShell->Down(/*bSelect=*/false); // Second row has an explicit transparent background.
aBrush.SetColor(COL_TRANSPARENT);
pWrtShell->SetRowBackground(aBrush);
// When exporting to reqif-xhtml:
ExportToReqif();
// Then make sure that CSS markup is used, not HTML one:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - XPath '//reqif-xhtml:table[1]' no attribute 'style' exist // i.e. HTML markup was used for the table background color.
assertXPath(pXmlDoc, "//reqif-xhtml:table[1]", "style", u"background: #ff0000");
assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:table[1]", "bgcolor");
assertXPath(pXmlDoc, "//reqif-xhtml:table[2]/reqif-xhtml:tr[1]", "style",
u"background: #00ff00");
assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:table[2]/reqif-xhtml:tr[1]", "bgcolor"); // Second row has no explicit style, the default is not written.
assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:table[2]/reqif-xhtml:tr[2]", "style");
}
CPPUNIT_TEST_FIXTURE(HtmlExportTest, testImageKeepRatio)
{ // Given a document with an image: width is relative, height is "keep ratio":
createSwDoc();
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xTextGraphic(
xFactory->createInstance(u"com.sun.star.text.TextGraphicObject"_ustr), uno::UNO_QUERY);
xTextGraphic->setPropertyValue(u"AnchorType"_ustr,
uno::Any(text::TextContentAnchorType_AS_CHARACTER));
xTextGraphic->setPropertyValue(u"RelativeWidth"_ustr, uno::Any(static_cast<sal_Int16>(42)));
xTextGraphic->setPropertyValue(u"IsSyncHeightToWidth"_ustr, uno::Any(true));
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XText> xBodyText = xTextDocument->getText();
uno::Reference<text::XTextCursor> xCursor(xBodyText->createTextCursor());
uno::Reference<text::XTextContent> xTextContent(xTextGraphic, uno::UNO_QUERY);
xBodyText->insertTextContent(xCursor, xTextContent, false);
// When exporting to HTML:
save(mpFilter);
// Then make sure that the width is not a fixed size, that would break on resizing the browser // window:
htmlDocUniquePtr pDoc = parseHtml(maTempFile); // Without the accompanying fix in place, this test would have failed with: // - Expected: auto // - Actual : 2 // i.e. a static (CSS pixel) height was written.
assertXPath(pDoc, "/html/body/p/img", "height", u"auto");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testSectionDir)
{ // Given a document with a section:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Insert(u"test"_ustr);
pWrtShell->SelAll();
SwSectionData aSectionData(SectionType::Content, UIName(u"mysect"_ustr));
pWrtShell->InsertSection(aSectionData);
// When exporting to (reqif-)xhtml:
ExportToReqif();
// Then make sure CSS is used to export the text direction of the section:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile(); // Without the accompanying fix in place, this test would have failed with: // - XPath '//reqif-xhtml:div[@id='mysect']' no attribute 'style' exist // i.e. the dir="ltr" HTML attribute was used instead.
assertXPath(pXmlDoc, "//reqif-xhtml:div[@id='mysect']", "style", u"dir: ltr");
}
CPPUNIT_TEST_FIXTURE(HtmlExportTest, testTdf114769)
{ // Create document from scratch since relative urls to filesystem can be replaced // by absolute during save/load
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Insert(u"Hyperlink1"_ustr);
pWrtShell->SplitNode();
pWrtShell->Insert(u"Hyperlink2"_ustr);
pWrtShell->SplitNode();
pWrtShell->Insert(u"Hyperlink3"_ustr);
pWrtShell->SplitNode();
pWrtShell->Insert(u"Hyperlink4"_ustr);
pWrtShell->SplitNode();
pWrtShell->Insert(u"Hyperlink5"_ustr);
pWrtShell->SplitNode();
// Normal external URL
uno::Reference<beans::XPropertySet> xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY);
xRun->setPropertyValue(u"HyperLinkURL"_ustr, uno::Any(u"http://libreoffice.org/"_ustr));
assertXPath(pDoc, "//reqif-xhtml:table"); // There should be no 'dd' or 'dl' tags, used as a hack for table indentation
assertXPath(pDoc, "//reqif-xhtml:dl", 0);
assertXPath(pDoc, "//reqif-xhtml:dd", 0);
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIfTransparentTifImg)
{ // reqIf export must keep the TIF encoding of the image
createSwDoc("reqif-transparent-tif-img.odt");
ExportToReqif();
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object[1]", "type", u"image/tiff");
OUString imageName = getXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object[1]", "data"); // Without the accompanying fix in place, this test would have failed, // ending with .gif, because XOutFlags::UseGifIfSensible flag combined // with the transparent image would result in GIF export
CPPUNIT_ASSERT(imageName.endsWith(".tif"));
// Without the fix in place, this would fail
xmlDocUniquePtr pDoc = WrapReqifFromTempFile();
// Single top-level list
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul"); // Single top-level item
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul/reqif-xhtml:li"); // 4 top-level paragraphs in the item
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul/reqif-xhtml:li/reqif-xhtml:p", 4); // 2 sublists in the item
assertXPath(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul/reqif-xhtml:li/reqif-xhtml:ul", 2); // 2 items in the first sublist
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul/reqif-xhtml:li/reqif-xhtml:ul[1]/" "reqif-xhtml:li",
2); // Check the last (most nested) subitem's text
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul/reqif-xhtml:li/reqif-xhtml:ul[2]/" "reqif-xhtml:li/reqif-xhtml:ul/reqif-xhtml:li/reqif-xhtml:p",
u"l3");
}
// Without the fix in place, this would fail
xmlDocUniquePtr pDoc = WrapReqifFromTempFile();
// Two top-level lists
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul", 2); // Single top-level item
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul[1]/reqif-xhtml:li"); // One top-level paragraph in the item
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul[1]/reqif-xhtml:li/reqif-xhtml:p"); // One sublist in the item
assertXPath(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul[1]/reqif-xhtml:li/reqif-xhtml:ul"); // One item in the sublist
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul[1]/reqif-xhtml:li/reqif-xhtml:ul/" "reqif-xhtml:li"); // Check its text
OUString aContent = getXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ul[1]/reqif-xhtml:li/reqif-xhtml:ul/" "reqif-xhtml:li/reqif-xhtml:p");
CPPUNIT_ASSERT_EQUAL(u"list 1 item 1\n\t\tsub-header"_ustr, aContent.trim());
}
// Without the fix, this would fail with // - Expected: Some text in frame & <foo> // - Actual : Frame1 // i.e., frame name was used as the object element content, not frame text
assertXPathContent(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[2]/reqif-xhtml:object",
u"Some text in frame & ");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testSingleOleExport)
{ // Given a document containing an embedded OLE object:
createSwDoc("ole2.odt");
// Create a selection for that object: auto xDrawPageSupplier(mxComponent.queryThrow<css::drawing::XDrawPageSupplier>()); auto xDrawPage(xDrawPageSupplier->getDrawPage()); auto xModel(mxComponent.queryThrow<css::frame::XModel>()); auto xController(xModel->getCurrentController().queryThrow<css::view::XSelectionSupplier>());
xController->select(xDrawPage->getByIndex(0));
// Store only the selection
css::uno::Sequence<css::beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"RTFOLEMimeType"_ustr, u"text/rtf"_ustr),
comphelper::makePropertyValue(u"SelectionOnly"_ustr, true),
};
saveWithParams(aStoreProperties);
// The root element must be reqif-xhtml:object
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:object", "type", u"text/rtf"); // It has no children
assertXPathChildren(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:object", 0); // And the content is empty
assertXPathContent(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:object", u"");
// The outer table must be kept in the document where the outer table is the first element, // and its A1 starts with a nested table
// Only two sub-elements must be inside the div: an outer table and a trailing paragraph
assertXPathChildren(pDoc, "/reqif-xhtml:html/reqif-xhtml:div", 2); // The outer table must have exactly two rows
assertXPath(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr", 2); // First outer table cell must have two sub-elements: an inner table and a trailing paragraph
assertXPathChildren(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]",
2); // The inner table must have exactly two rows
assertXPath(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/" "reqif-xhtml:table/reqif-xhtml:tr",
2); // Check all the elements' content
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/" "reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/reqif-xhtml:p",
u"Inner.A1");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/" "reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[2]/reqif-xhtml:p",
u"Inner.B1");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/" "reqif-xhtml:table/reqif-xhtml:tr[2]/reqif-xhtml:td[1]/reqif-xhtml:p",
u"Inner.A2");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/" "reqif-xhtml:table/reqif-xhtml:tr[2]/reqif-xhtml:td[2]/reqif-xhtml:p",
u"Inner.B2");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[1]/" "reqif-xhtml:p",
u"Outer.A1");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[1]/reqif-xhtml:td[2]/" "reqif-xhtml:p",
u"Outer.B1");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[2]/reqif-xhtml:td[1]/" "reqif-xhtml:p",
u"Outer.A2");
assertXPathContent(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr[2]/reqif-xhtml:td[2]/" "reqif-xhtml:p",
u"Outer.B2");
assertXPathContent(pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p", u"Following text");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTdf156647_CellPaddingRoundtrip)
{ // Given a document with a table with cell padding:
createSwDoc("table_cell_padding.fodt");
{ auto xTable = getParagraphOrTable(1); auto aTableBorder = getProperty<css::table::TableBorder2>(xTable, u"TableBorder2"_ustr);
CPPUNIT_ASSERT_EQUAL(sal_Int16(1270), aTableBorder.Distance);
CPPUNIT_ASSERT(aTableBorder.IsDistanceValid);
} // When exporting to reqif-xhtml:
ExportToReqif(); // Make sure that we export it:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "//reqif-xhtml:table", "cellpadding", u"48"); // px // Now import it
ImportFromReqif(maTempFile.GetURL()); // Then make sure that padding is not lost:
{ auto xTable = getParagraphOrTable(1); auto aTableBorder = getProperty<css::table::TableBorder2>(xTable, u"TableBorder2"_ustr); // Without the accompanying fix in place, this test would have failed: // - Expected: 1270 // - Actual : 97 // as the padding was lost, and the default 55 twip padding was used.
CPPUNIT_ASSERT_EQUAL(sal_Int16(1270), aTableBorder.Distance);
CPPUNIT_ASSERT(aTableBorder.IsDistanceValid);
}
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTdf157643_WideHBorder)
{ // Given a document with a table with a wide border between its two rows:
createSwDoc("table_with_wide_horizontal_border.fodt"); // When exporting to reqif-xhtml:
ExportToReqif(); // Make sure that there's no extra tr's:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:table/reqif-xhtml:tr", 2);
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_PreserveSpaces)
{ // Given a document with leading, trailing, and repeating intermediate spaces:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); static constexpr OUString paraText = u"\t test \t more text \t"_ustr;
pWrtShell->Insert(paraText);
// When exporting to plain HTML, using PreserveSpaces:
saveWithParams({
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"PreserveSpaces"_ustr, true),
});
// Then make sure that "white-space: pre-wrap" is written into the paragraph's style:
htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
CPPUNIT_ASSERT(pHtmlDoc); const OUString style = getXPath(pHtmlDoc, "/html/body/p", "style");
CPPUNIT_ASSERT(style.indexOf("white-space: pre-wrap") >= 0); // Also check that the paragraph text is correct, without modifications in whitespace
assertXPathContent(pHtmlDoc, "/html/body/p", paraText);
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_PreserveSpaces)
{ // Given a document with leading, trailing, and repeating intermediate spaces:
createSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); static constexpr OUString paraText = u"\t test \t more text \t"_ustr;
pWrtShell->Insert(paraText);
// When exporting to ReqIF, using PreserveSpaces:
saveWithParams({
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"PreserveSpaces"_ustr, true),
});
// Then make sure that xml:space="preserve" attribute exists in the paragraph element:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p", "space", u"preserve"); // Also check that the paragraph text is correct, without modifications in whitespace
assertXPathContent(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p", paraText);
// No whitespace preservation, where no leading / trailing / double whitespace
assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[1]"); // Whitespace preserved for a leading space
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[2]"); // Whitespace preserved for a trailing space
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[3]"); // Whitespace preserved for a double space
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[4]"); // No whitespace preservation for leading / trailing breaks
assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[5]"); // Whitespace preserved for a leading break + space
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[6]"); // Whitespace preserved for a trailing space + break
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[7]"); // No whitespace preservation for a middle break
assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[8]"); // Whitespace preserved for a middle space + break
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[9]"); // Whitespace preserved for a middle break + space
assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[10]"); // No whitespace preservation for a trailing space and SVG
assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[11]");
CPPUNIT_ASSERT_EQUAL(u"No special spaces"_ustr, getParagraph(1)->getString());
CPPUNIT_ASSERT_EQUAL(u" Leading space"_ustr, getParagraph(2)->getString());
CPPUNIT_ASSERT_EQUAL(u"Trailing space "_ustr, getParagraph(3)->getString());
CPPUNIT_ASSERT_EQUAL(u"Double space"_ustr, getParagraph(4)->getString()); // Trailing break is removed in SwHTMLParser::AppendTextNode, and replaced with para spacing
CPPUNIT_ASSERT_EQUAL(u"\nLeading/trailing breaks"_ustr, getParagraph(5)->getString());
CPPUNIT_ASSERT_EQUAL(u"\n Leading break + space"_ustr, getParagraph(6)->getString()); // Trailing break is removed in SwHTMLParser::AppendTextNode, and replaced with para spacing
CPPUNIT_ASSERT_EQUAL(u"Trailing space + break "_ustr, getParagraph(7)->getString());
CPPUNIT_ASSERT_EQUAL(u"Middle\nbreak"_ustr, getParagraph(8)->getString());
CPPUNIT_ASSERT_EQUAL(u"Middle space \n+ break"_ustr, getParagraph(9)->getString());
CPPUNIT_ASSERT_EQUAL(u"Middle break\n + space"_ustr, getParagraph(10)->getString()); // The SVG is replaced by a space in SwXParagraph::getString()
CPPUNIT_ASSERT_EQUAL(u"Trailing space and SVG "_ustr, getParagraph(11)->getString());
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_NoPreserveSpaces)
{ // Test cases where "PreserveSpaces" should not introduce respective markup
createSwDoc("test_no_space_preserve.fodt");
// Export to ReqIF, using PreserveSpaces:
saveWithParams({
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"PreserveSpaces"_ustr, true),
});
// No whitespace preservation, where no leading / trailing / double whitespace
assertXPathNoAttribute(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[1]", "space"); // Whitespace preserved for a leading space
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[2]", "space",
u"preserve"); // Whitespace preserved for a trailing space
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[3]", "space",
u"preserve"); // Whitespace preserved for a double space
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[4]", "space",
u"preserve"); // No whitespace preservation for leading / trailing breaks
assertXPathNoAttribute(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[5]", "space"); // Whitespace preserved for a leading break + space
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[6]", "space",
u"preserve"); // No whitespace preservation for a trailing space + break
assertXPathNoAttribute(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[7]", "space"); // No whitespace preservation for a middle break
assertXPathNoAttribute(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[8]", "space"); // No whitespace preservation for a middle space + break
assertXPathNoAttribute(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[9]", "space"); // Whitespace preserved for a middle break + space
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[10]", "space",
u"preserve"); // No whitespace preservation for a trailing space and SVG
assertXPathNoAttribute(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[11]", "space");
CPPUNIT_ASSERT_EQUAL(u"No special spaces"_ustr, getParagraph(1)->getString());
CPPUNIT_ASSERT_EQUAL(u" Leading space"_ustr, getParagraph(2)->getString());
CPPUNIT_ASSERT_EQUAL(u"Trailing space "_ustr, getParagraph(3)->getString());
CPPUNIT_ASSERT_EQUAL(u"Double space"_ustr, getParagraph(4)->getString());
CPPUNIT_ASSERT_EQUAL(u"\nLeading/trailing breaks\n"_ustr, getParagraph(5)->getString());
CPPUNIT_ASSERT_EQUAL(u"\n Leading break + space"_ustr, getParagraph(6)->getString());
CPPUNIT_ASSERT_EQUAL(u"Trailing space + break \n"_ustr, getParagraph(7)->getString());
CPPUNIT_ASSERT_EQUAL(u"Middle\nbreak"_ustr, getParagraph(8)->getString());
CPPUNIT_ASSERT_EQUAL(u"Middle space \n+ break"_ustr, getParagraph(9)->getString());
CPPUNIT_ASSERT_EQUAL(u"Middle break\n + space"_ustr, getParagraph(10)->getString()); // The SVG is replaced by a space in SwXParagraph::getString()
CPPUNIT_ASSERT_EQUAL(u"Trailing space and SVG "_ustr, getParagraph(11)->getString());
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_ExportFormulasAsPDF)
{ #if ENABLE_PDFIMPORT // Given a document with a formula:
createSwDoc("embedded_formula.fodt");
// When exporting to reqif with ExportFormulasAsPDF=true:
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"ExportFormulasAsPDF"_ustr, true),
};
saveWithParams(aStoreProperties);
// Make sure that the formula is exported as PDF:
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[2]/reqif-xhtml:object", "type", u"application/pdf");
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_NoBrClearForImageWrap)
{ // Given a document with a paragraph-anchored image with "none" wrap:
createSwDoc("image_anchored_to_paragraph_no_wrap.fodt"); // When exporting to reqif:
ExportToReqif(); // Make sure that there's no 'br' elements in the 'object' (used to represent the wrapping // in HTML export, using 'clear' attribute):
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object");
assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object/reqif-xhtml:br",
0);
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_Tdf160017_spanClosingOrder)
{ // Given a document with a paragraph having explicit font color and character border properties:
createSwDoc("char_border_and_font_color.fodt"); // When exporting to reqif:
ExportToReqif(); // Without the fix, this would fail, because there was an extra closing </reqif-xhtml:span>
WrapReqifFromTempFile();
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_Tdf160017_spanClosingOrder)
{ // Given a document with a paragraph having explicit font color and character border properties:
createSwDoc("char_border_and_font_color.fodt"); // When exporting to HTML:
ExportToHTML(); // Parse it as XML (strict!) // Without the fix, this would fail, because span and font elements closed in wrong order
CPPUNIT_ASSERT(parseXml(maTempFile));
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_Tdf160390)
{ // This document must not hang infinitely on HTML export
createSwDoc("tdf160390.fodt");
ExportToHTML();
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_160867)
{ // Given a document with an image with hyperlink, and text with hyperlink, both in a frame:
createSwDoc("tdf160867_image_with_link.fodt"); // When exporting to HTML:
ExportToHTML(); // Parse it as XML (strict!)
xmlDocUniquePtr pDoc = parseXml(maTempFile);
CPPUNIT_ASSERT(pDoc);
assertXPath(pDoc, "/html/body/p", 2);
// Test export of image and text hyperlinks in the image map. // Without the fix, the test would fail with // - Expected: 1 // - Actual : 0 // - In <>, XPath '/html/body/p[2]/map' number of nodes is incorrect const OUString mapName = getXPath(pDoc, "/html/body/p[2]/map", "name");
assertXPath(pDoc, "/html/body/p[2]/map/area[1]", "shape", u"rect");
CPPUNIT_ASSERT(getXPath(pDoc, "/html/body/p[2]/map/area[1]", "href").endsWith("foo/bar"));
assertXPath(pDoc, "/html/body/p[2]/map/area[2]", "shape", u"rect");
CPPUNIT_ASSERT(getXPath(pDoc, "/html/body/p[2]/map/area[2]", "href").endsWith("baz"));
assertXPath(pDoc, "/html/body/p[2]/img", "usemap", Concat2View("#" + mapName));
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_160867)
{ // Given a document with an image with hyperlink, and text with hyperlink, both in a frame:
createSwDoc("tdf160867_image_with_link.fodt"); // When exporting to reqif:
ExportToReqif(); // For now, we don't (yet) output the whole map in ReqIF case. // Make sure that the first hyperlink from the objects in the frame is output as an <a> element // around the whole image of the frame.
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
assertXPath(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a/reqif-xhtml:object");
CPPUNIT_ASSERT(
getXPath(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a", "href").endsWith("foo/bar")); // There must be no 'target' attribute
assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a", "target");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_161979)
{ // Given a document with two embedded metafiles:
createSwDoc("tdf161979_metafile.fodt");
ExportToHTML();
xmlDocUniquePtr pDoc = parseXml(maTempFile);
CPPUNIT_ASSERT(pDoc); // First image: it has no EMF+ actions, and didn't use canvas rendering before the fix; // yet, it didn't export correctly.
OUString imgName = getXPath(pDoc, "/html/body/p[2]/img", "src");
CPPUNIT_ASSERT(imgName.endsWith(".gif"));
INetURLObject aUrl(maTempFile.GetURL());
aUrl.setName(imgName);
Graphic graphic;
CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, GraphicFilter().ImportGraphic(graphic, aUrl));
// Check that only ~4% of pixels are not transparent (before the fix, it was completely black)
BitmapEx bitmap = graphic.GetBitmapEx();
Size size = bitmap.GetSizePixel(); int numNonTransparent = 0; for (tools::Long y = 0; y < size.Height(); ++y) for (tools::Long x = 0; x < size.Width(); ++x) if (bitmap.GetPixelColor(x, y) != COL_TRANSPARENT)
++numNonTransparent;
CPPUNIT_ASSERT_DOUBLES_EQUAL(0.04, numNonTransparent / double(size.Height() * size.Width()),
0.01);
// Second image: it consists of EMF+ records (no EMF fallback). It used canvas rendering // before the fix; it also didn't export correctly.
imgName = getXPath(pDoc, "/html/body/p[4]/img", "src");
CPPUNIT_ASSERT(imgName.endsWith(".gif"));
aUrl.SetURL(maTempFile.GetURL());
aUrl.setName(imgName);
graphic.Clear();
CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, GraphicFilter().ImportGraphic(graphic, aUrl));
// Check that some pixels are transparent (before the fix, it was completely black)
bitmap = graphic.GetBitmapEx();
size = bitmap.GetSizePixel();
numNonTransparent = 0; for (tools::Long y = 0; y < size.Height(); ++y) for (tools::Long x = 0; x < size.Width(); ++x) if (bitmap.GetPixelColor(x, y) != COL_TRANSPARENT)
++numNonTransparent;
CPPUNIT_ASSERT(numNonTransparent > 0);
CPPUNIT_ASSERT(numNonTransparent < size.Height() * size.Width());
}
// HTTP URL: must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:p[1]/reqif-xhtml:a", "href", u"http://www.example.org/"); // file URL: must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a", "href",
createFileURL(u"NonExistingPath/NonExistingFile.html")); // form URL: must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:form", "action", u"https://www.example.org/submit"); // linked image exported as object: generated, must be relative
OUString url = getXPath(pXmlDoc, "//reqif-xhtml:p[3]/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".ole")); // its original image URL: must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:p[3]/reqif-xhtml:object/reqif-xhtml:object", "data",
createFileURL(u"external.png")); // embedded image exported as object: generated, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[4]/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".ole")); // its image URL: generated, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[4]/reqif-xhtml:object/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".png")); // unordered list with image bullet - it gets embedded as base64 data
OUString style = getXPath(pXmlDoc, "//reqif-xhtml:ul", "style");
CPPUNIT_ASSERT(style.indexOf("list-style-image: url(data:image/png;base64,") != -1); // an as-char frame, exported as a whole to an object, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".ole")); // its file hyperlink must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a", "href",
createFileURL(u"foo/bar")); // its image URL: generated, must be relative
url = getXPath(
pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".png"));
}
createSwDoc("URLs.odt"); // Export to ReqIF, using relative URLs (the default)
saveWithParams({
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
comphelper::makePropertyValue(u"ExportImagesAsOLE"_ustr, true),
});
xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
// HTTP URL: must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:p[1]/reqif-xhtml:a", "href", u"http://www.example.org/"); // file URL: must be relative
OUString url = getXPath(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a", "href");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith("NonExistingPath/NonExistingFile.html")); // form URL: must be absolute
assertXPath(pXmlDoc, "//reqif-xhtml:form", "action", u"https://www.example.org/submit"); // linked image exported as object: generated, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[3]/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".ole")); // its original image URL: must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[3]/reqif-xhtml:object/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith("external.png")); // embedded image exported as object: generated, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[4]/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".ole")); // its image URL: generated, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[4]/reqif-xhtml:object/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".png")); // unordered list with image bullet - it gets embedded as base64 data
OUString style = getXPath(pXmlDoc, "//reqif-xhtml:ul", "style");
CPPUNIT_ASSERT(style.indexOf("list-style-image: url(data:image/png;base64,") != -1); // an as-char frame, exported as a whole to an object, must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".ole")); // its file hyperlink must be relative
url = getXPath(pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a", "href");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith("foo/bar")); // its image URL: generated, must be relative
url = getXPath(
pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(!url.startsWith("file:"));
CPPUNIT_ASSERT(url.endsWith(".png"));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.