1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <cppunit/TestAssert.h>
12 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
13 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
14 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
15 #include <com/sun/star/beans/XPropertySet.hpp>
16 #include <com/sun/star/awt/XControlModel.hpp>
17 #include <com/sun/star/graphic/XGraphic.hpp>
18 #include <com/sun/star/table/XCellRange.hpp>
19 #include <com/sun/star/text/XTextRange.hpp>
20 #include <com/sun/star/text/ControlCharacter.hpp>
21 #include <com/sun/star/frame/XStorable.hpp>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/propertysequence.hxx>
25 #include <test/unoapixml_test.hxx>
26 #include <unotools/tempfile.hxx>
27 #include <svx/unopage.hxx>
28 #include <vcl/virdev.hxx>
29 #include <svx/sdr/contact/displayinfo.hxx>
30 #include <drawinglayer/tools/primitive2dxmldump.hxx>
31 #include <svx/sdr/contact/viewcontact.hxx>
32 #include <svx/sdr/contact/viewobjectcontact.hxx>
33 #include <unotools/streamwrap.hxx>
34 #include <unotools/mediadescriptor.hxx>
35 #include <vcl/filter/PngImageReader.hxx>
37 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
39 using namespace ::com::sun::star
;
43 /// Tests for svx/source/unodraw/ code.
44 class UnodrawTest
: public UnoApiXmlTest
48 : UnoApiXmlTest("svx/qa/unit/data/")
53 CPPUNIT_TEST_FIXTURE(UnodrawTest
, testWriterGraphicExport
)
55 // Load a document with a Writer picture in it.
56 loadFromURL(u
"unodraw-writer-image.odt");
57 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
58 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
59 uno::Reference
<lang::XComponent
> xShape(xDrawPage
->getByIndex(0), uno::UNO_QUERY
);
62 uno::Reference
<drawing::XGraphicExportFilter
> xExportFilter
63 = drawing::GraphicExportFilter::create(mxComponentContext
);
64 // This resulted in a css::lang::IllegalArgumentException for a Writer
66 xExportFilter
->setSourceDocument(xShape
);
68 uno::Sequence
<beans::PropertyValue
> aProperties(
69 comphelper::InitPropertySequence({ { "URL", uno::Any(maTempFile
.GetURL()) },
70 { "MediaType", uno::Any(OUString("image/jpeg")) } }));
71 CPPUNIT_ASSERT(xExportFilter
->filter(aProperties
));
74 CPPUNIT_TEST_FIXTURE(UnodrawTest
, testTdf93998
)
76 loadFromURL(u
"tdf93998.odp");
77 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
78 CPPUNIT_ASSERT(xDrawPagesSupplier
.is());
80 uno::Reference
<drawing::XDrawPage
> xDrawPage(xDrawPagesSupplier
->getDrawPages()->getByIndex(0),
82 CPPUNIT_ASSERT(xDrawPage
.is());
84 uno::Reference
<beans::XPropertySet
> xShape(xDrawPage
->getByIndex(0), uno::UNO_QUERY
);
85 CPPUNIT_ASSERT(xShape
.is());
87 uno::Reference
<lang::XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
88 uno::Reference
<awt::XControlModel
> xModel(
89 xFactory
->createInstance("com.sun.star.awt.UnoControlDialogModel"), uno::UNO_QUERY
);
90 CPPUNIT_ASSERT(xModel
.is());
92 uno::Reference
<beans::XPropertySet
> xModelProps(xModel
, uno::UNO_QUERY
);
93 CPPUNIT_ASSERT(xModelProps
.is());
95 // This resulted in a uno::RuntimeException, assigning a shape to a dialog model's image was
97 xModelProps
->setPropertyValue("ImageURL", xShape
->getPropertyValue("GraphicURL"));
98 uno::Reference
<graphic::XGraphic
> xGraphic
;
99 xModelProps
->getPropertyValue("Graphic") >>= xGraphic
;
100 CPPUNIT_ASSERT(xGraphic
.is());
103 CPPUNIT_TEST_FIXTURE(UnodrawTest
, testTableShadowDirect
)
105 // Create an Impress document an insert a table shape.
106 mxComponent
= loadFromDesktop("private:factory/simpress",
107 "com.sun.star.presentation.PresentationDocument");
108 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
109 uno::Reference
<drawing::XShape
> xShape(
110 xFactory
->createInstance("com.sun.star.drawing.TableShape"), uno::UNO_QUERY
);
111 xShape
->setPosition(awt::Point(1000, 1000));
112 xShape
->setSize(awt::Size(10000, 10000));
113 uno::Reference
<drawing::XDrawPagesSupplier
> xSupplier(mxComponent
, uno::UNO_QUERY
);
114 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xSupplier
->getDrawPages();
115 uno::Reference
<drawing::XDrawPage
> xDrawPage(xDrawPages
->getByIndex(0), uno::UNO_QUERY
);
116 xDrawPage
->add(xShape
);
118 // Create a red shadow on it without touching its style.
119 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
120 // Without the accompanying fix in place, this test would have failed with throwing a
121 // beans.UnknownPropertyException, as shadow-as-direct-formatting on tables were not possible.
122 xShapeProps
->setPropertyValue("Shadow", uno::Any(true));
123 sal_Int32 nRed
= 0xff0000;
124 xShapeProps
->setPropertyValue("ShadowColor", uno::Any(nRed
));
125 CPPUNIT_ASSERT(xShapeProps
->getPropertyValue("ShadowColor") >>= nRed
);
126 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0xff0000), nRed
);
129 uno::Reference
<table::XCellRange
> xTable(xShapeProps
->getPropertyValue("Model"),
131 uno::Reference
<text::XTextRange
> xCell(xTable
->getCellByPosition(0, 0), uno::UNO_QUERY
);
132 xCell
->setString("A1");
134 // Generates drawinglayer primitives for the shape.
135 auto pDrawPage
= dynamic_cast<SvxDrawPage
*>(xDrawPage
.get());
136 CPPUNIT_ASSERT(pDrawPage
);
137 SdrPage
* pSdrPage
= pDrawPage
->GetSdrPage();
138 ScopedVclPtrInstance
<VirtualDevice
> aVirtualDevice
;
139 sdr::contact::ObjectContactOfObjListPainter
aObjectContact(*aVirtualDevice
,
140 { pSdrPage
->GetObj(0) }, nullptr);
141 const sdr::contact::ViewObjectContact
& rDrawPageVOContact
142 = pSdrPage
->GetViewContact().GetViewObjectContact(aObjectContact
);
143 sdr::contact::DisplayInfo aDisplayInfo
;
144 drawinglayer::primitive2d::Primitive2DContainer xPrimitiveSequence
;
145 rDrawPageVOContact
.getPrimitive2DSequenceHierarchy(aDisplayInfo
, xPrimitiveSequence
);
147 // Check the primitives.
148 drawinglayer::Primitive2dXmlDump aDumper
;
149 xmlDocUniquePtr pDocument
= aDumper
.dumpAndParse(xPrimitiveSequence
);
150 assertXPath(pDocument
, "//shadow", /*nNumberOfNodes=*/1);
152 // Without the accompanying fix in place, this test would have failed with:
155 // i.e. there was shadow for the cell text, while here PowerPoint-compatible output is expected,
156 // which has no shadow for cell text (only for cell borders and cell background).
157 assertXPath(pDocument
, "//shadow//sdrblocktext", /*nNumberOfNodes=*/0);
160 CPPUNIT_TEST_FIXTURE(UnodrawTest
, testTitleShapeBullets
)
162 // Create a title shape with 2 paragraphs in it.
163 mxComponent
= loadFromDesktop("private:factory/simpress",
164 "com.sun.star.presentation.PresentationDocument");
165 uno::Reference
<drawing::XDrawPagesSupplier
> xSupplier(mxComponent
, uno::UNO_QUERY
);
166 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xSupplier
->getDrawPages();
167 uno::Reference
<drawing::XDrawPage
> xDrawPage(xDrawPages
->getByIndex(0), uno::UNO_QUERY
);
168 // A default document contains a title shape and a text shape on the first slide.
169 uno::Reference
<drawing::XShape
> xTitleShape(xDrawPage
->getByIndex(0), uno::UNO_QUERY
);
170 uno::Reference
<lang::XServiceInfo
> xTitleShapeInfo(xTitleShape
, uno::UNO_QUERY
);
171 CPPUNIT_ASSERT(xTitleShapeInfo
->supportsService("com.sun.star.presentation.TitleTextShape"));
172 uno::Reference
<text::XTextRange
> xTitleShapeText(xTitleShape
, uno::UNO_QUERY
);
173 uno::Reference
<text::XText
> xText
= xTitleShapeText
->getText();
174 uno::Reference
<text::XTextRange
> xCursor
= xText
->createTextCursor();
175 xText
->insertString(xCursor
, "foo", /*bAbsorb=*/false);
176 xText
->insertControlCharacter(xCursor
, text::ControlCharacter::APPEND_PARAGRAPH
,
178 xText
->insertString(xCursor
, "bar", /*bAbsorb=*/false);
180 // Check that the title shape has 2 paragraphs.
181 uno::Reference
<container::XEnumerationAccess
> xTextEA(xText
, uno::UNO_QUERY
);
182 uno::Reference
<container::XEnumeration
> xTextE
= xTextEA
->createEnumeration();
183 // Has a first paragraph.
184 CPPUNIT_ASSERT(xTextE
->hasMoreElements());
185 xTextE
->nextElement();
186 // Has a second paragraph.
187 // Without the accompanying fix in place, this test would have failed, because the 2 paragraphs
188 // were merged together (e.g. 1 bullet instead of 2 bullets for bulleted paragraphs).
189 CPPUNIT_ASSERT(xTextE
->hasMoreElements());
192 CPPUNIT_TEST_FIXTURE(UnodrawTest
, testPngExport
)
194 // Given an empty Impress document:
195 mxComponent
= loadFromDesktop("private:factory/simpress",
196 "com.sun.star.presentation.PresentationDocument");
198 // When exporting that document to PNG with a JSON size:
199 uno::Reference
<frame::XStorable
> xStorable(mxComponent
, uno::UNO_QUERY_THROW
);
200 SvMemoryStream aStream
;
201 uno::Reference
<io::XOutputStream
> xOut
= new utl::OOutputStreamWrapper(aStream
);
202 utl::MediaDescriptor aMediaDescriptor
;
203 aMediaDescriptor
["FilterName"] <<= OUString("impress_png_Export");
204 aMediaDescriptor
["FilterOptions"]
205 <<= OUString("{\"PixelHeight\":{\"type\":\"long\",\"value\":\"192\"},"
206 "\"PixelWidth\":{\"type\":\"long\",\"value\":\"192\"}}");
207 aMediaDescriptor
["OutputStream"] <<= xOut
;
208 xStorable
->storeToURL("private:stream", aMediaDescriptor
.getAsConstPropertyValueList());
210 // Then make sure that the size request is handled:
211 aStream
.Seek(STREAM_SEEK_TO_BEGIN
);
212 vcl::PngImageReader
aPngReader(aStream
);
214 aPngReader
.read(aBitmapEx
);
215 Size aSize
= aBitmapEx
.GetSizePixel();
216 // Without the accompanying fix in place, this test would have failed with:
219 // i.e. it was not possible to influence the size from the cmdline.
220 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long
>(192), aSize
.getHeight());
221 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long
>(192), aSize
.getWidth());
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */