Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #define BASEGFX_STATICLIBRARY
30 : :
31 : : #ifdef SYSTEM_ZLIB
32 : : #include "zlib.h"
33 : : #else
34 : : #include <zlib/zlib.h>
35 : : #endif
36 : :
37 : : #include "outputwrap.hxx"
38 : : #include "contentsink.hxx"
39 : : #include "pdfihelper.hxx"
40 : : #include "wrapper.hxx"
41 : : #include "pdfparse.hxx"
42 : : #include "../pdfiadaptor.hxx"
43 : :
44 : : #include <rtl/math.hxx>
45 : : #include <osl/file.hxx>
46 : : #include <osl/process.h>
47 : : #include <cppuhelper/compbase1.hxx>
48 : : #include <cppuhelper/bootstrap.hxx>
49 : : #include <cppuhelper/basemutex.hxx>
50 : : #include <comphelper/sequence.hxx>
51 : : #include <comphelper/processfactory.hxx>
52 : :
53 : : #include "cppunit/TestAssert.h"
54 : : #include "cppunit/TestFixture.h"
55 : : #include "cppunit/extensions/HelperMacros.h"
56 : : #include "cppunit/plugin/TestPlugIn.h"
57 : : #include <test/bootstrapfixture.hxx>
58 : :
59 : : #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
60 : : #include <com/sun/star/rendering/XCanvas.hpp>
61 : : #include <com/sun/star/rendering/XColorSpace.hpp>
62 : : #include <com/sun/star/rendering/PathJoinType.hpp>
63 : : #include <com/sun/star/rendering/PathCapType.hpp>
64 : : #include <com/sun/star/rendering/BlendMode.hpp>
65 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
66 : : #include <com/sun/star/lang/XInitialization.hpp>
67 : : #include <com/sun/star/registry/XSimpleRegistry.hpp>
68 : :
69 : : #include <basegfx/matrix/b2dhommatrix.hxx>
70 : : #include <basegfx/tools/canvastools.hxx>
71 : : #include <basegfx/polygon/b2dpolygon.hxx>
72 : : #include <basegfx/polygon/b2dpolypolygon.hxx>
73 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
74 : : #include <basegfx/polygon/b2dpolygonclipper.hxx>
75 : :
76 : : #include <vector>
77 : : #include <boost/unordered_map.hpp>
78 : :
79 : : #include <cassert>
80 : : #include <rtl/oustringostreaminserter.hxx>
81 : :
82 : : using namespace ::pdfparse;
83 : : using namespace ::pdfi;
84 : : using namespace ::com::sun::star;
85 : :
86 : : namespace rtl
87 : : {
88 : : template< typename charT, typename traits > std::basic_ostream<charT, traits> &
89 : 0 : operator <<(
90 : : std::basic_ostream<charT, traits> & stream, rtl::OString const & string)
91 : : {
92 : 0 : return stream << string.getStr();
93 : : }
94 : : }
95 : :
96 : : namespace
97 : : {
98 : :
99 : : class TestSink : public ContentSink
100 : : {
101 : : public:
102 : 3 : TestSink() :
103 : : m_nNextFontId( 1 ),
104 : : m_aIdToFont(),
105 : : m_aFontToId(),
106 : : m_aGCStack(1),
107 : : m_aPageSize(),
108 : : m_aHyperlinkBounds(),
109 : : m_aURI(),
110 : : m_aTextOut(),
111 : : m_nNumPages(0),
112 : : m_bPageEnded(false),
113 : : m_bRedCircleSeen(false),
114 : : m_bGreenStrokeSeen(false),
115 [ + - ][ + - ]: 3 : m_bDashedLineSeen(false)
[ + - ]
116 : 3 : {}
117 : :
118 : 6 : ~TestSink()
119 [ + - ][ + - ]: 3 : {
120 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "A4 page size (in 100th of points): Width", m_aPageSize.Width, 79400, 0.00000001);
[ + - ][ + - ]
[ + - ]
121 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "A4 page size (in 100th of points): Height" , m_aPageSize.Height, 59500, 0.0000001 );
[ + - ][ + - ]
[ + - ]
122 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "endPage() called", m_bPageEnded );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
123 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "Num pages equal one", m_nNumPages, (sal_Int32) 1 );
[ + - ][ + - ]
[ + - ]
124 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Correct hyperlink bounding box",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
125 : : rtl::math::approxEqual(m_aHyperlinkBounds.X1,34.7 ) &&
126 : : rtl::math::approxEqual(m_aHyperlinkBounds.Y1,386.0) &&
127 : : rtl::math::approxEqual(m_aHyperlinkBounds.X2,166.7) &&
128 [ + - ]: 3 : rtl::math::approxEqual(m_aHyperlinkBounds.Y2,406.2) );
129 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "Correct hyperlink URI", m_aURI, ::rtl::OUString("http://download.openoffice.org/") );
[ + - ][ + - ]
[ + - ]
130 : :
131 : : const char* sText = " \n \nThis is a testtext\nNew paragraph,\nnew line\n"
132 : 3 : "Hyperlink, this is\n?\nThis is more text\noutline mode\n?\nNew paragraph\n";
133 : 3 : ::rtl::OString aTmp;
134 : : m_aTextOut.makeStringAndClear().convertToString( &aTmp,
135 : : RTL_TEXTENCODING_ASCII_US,
136 [ + - ]: 3 : OUSTRING_TO_OSTRING_CVTFLAGS );
137 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "Imported text is \"This is a testtext New paragraph, new line"
[ + - ][ + - ]
138 : : " Hyperlink, this is * This is more text outline mode * New paragraph\"",
139 [ + - ]: 3 : rtl::OString(sText), aTmp );
140 : :
141 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "red circle seen in input", m_bRedCircleSeen );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
142 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "green stroke seen in input", m_bGreenStrokeSeen );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
143 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "dashed line seen in input", m_bDashedLineSeen );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
144 [ - + ]: 6 : }
145 : :
146 : : private:
147 : 156 : GraphicsContext& getCurrentContext() { return m_aGCStack.back(); }
148 : :
149 : : // ContentSink interface implementation
150 : 3 : virtual void setPageNum( sal_Int32 nNumPages )
151 : : {
152 : 3 : m_nNumPages = nNumPages;
153 : 3 : }
154 : :
155 : 3 : virtual void startPage( const geometry::RealSize2D& rSize )
156 : : {
157 : 3 : m_aPageSize = rSize;
158 : 3 : }
159 : :
160 : 3 : virtual void endPage()
161 : : {
162 : 3 : m_bPageEnded = true;
163 : 3 : }
164 : :
165 : 3 : virtual void hyperLink( const geometry::RealRectangle2D& rBounds,
166 : : const ::rtl::OUString& rURI )
167 : : {
168 : 3 : m_aHyperlinkBounds = rBounds;
169 : 3 : m_aURI = rURI;
170 : 3 : }
171 : :
172 : 48 : virtual void pushState()
173 : : {
174 [ + - ][ + - ]: 48 : GraphicsContextStack::value_type const a(m_aGCStack.back());
175 [ + - ][ + - ]: 48 : m_aGCStack.push_back(a);
176 : 48 : }
177 : :
178 : 48 : virtual void popState()
179 : : {
180 : 48 : m_aGCStack.pop_back();
181 : 48 : }
182 : :
183 : 6 : virtual void setTransformation( const geometry::AffineMatrix2D& rMatrix )
184 : : {
185 : : basegfx::unotools::homMatrixFromAffineMatrix(
186 : 6 : getCurrentContext().Transformation,
187 : 6 : rMatrix );
188 : 6 : }
189 : :
190 : 6 : virtual void setLineDash( const uno::Sequence<double>& dashes,
191 : : double start )
192 : : {
193 : 6 : GraphicsContext& rContext( getCurrentContext() );
194 [ + + ]: 6 : if( dashes.getLength() )
195 : 3 : comphelper::sequenceToContainer(rContext.DashArray,dashes);
196 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "line dashing start offset", start, 0.0, 0.000000001 );
[ + - ][ + - ]
[ + - ]
197 : 6 : }
198 : :
199 : 3 : virtual void setFlatness( double nFlatness )
200 : : {
201 : 3 : getCurrentContext().Flatness = nFlatness;
202 : 3 : }
203 : :
204 : 9 : virtual void setLineJoin(sal_Int8 nJoin)
205 : : {
206 : 9 : getCurrentContext().LineJoin = nJoin;
207 : 9 : }
208 : :
209 : 9 : virtual void setLineCap(sal_Int8 nCap)
210 : : {
211 : 9 : getCurrentContext().LineCap = nCap;
212 : 9 : }
213 : :
214 : 3 : virtual void setMiterLimit(double nVal)
215 : : {
216 : 3 : getCurrentContext().MiterLimit = nVal;
217 : 3 : }
218 : :
219 : 12 : virtual void setLineWidth(double nVal)
220 : : {
221 : 12 : getCurrentContext().LineWidth = nVal;
222 : 12 : }
223 : :
224 : 42 : virtual void setFillColor( const rendering::ARGBColor& rColor )
225 : : {
226 : 42 : getCurrentContext().FillColor = rColor;
227 : 42 : }
228 : :
229 : 12 : virtual void setStrokeColor( const rendering::ARGBColor& rColor )
230 : : {
231 : 12 : getCurrentContext().LineColor = rColor;
232 : 12 : }
233 : :
234 : 0 : virtual void setBlendMode(sal_Int8 nMode)
235 : : {
236 : 0 : getCurrentContext().BlendMode = nMode;
237 : 0 : }
238 : :
239 : 33 : virtual void setFont( const FontAttributes& rFont )
240 : : {
241 [ + - ]: 33 : FontToIdMap::const_iterator it = m_aFontToId.find( rFont );
242 [ + + ][ + - ]: 33 : if( it != m_aFontToId.end() )
243 [ + - ][ + - ]: 21 : getCurrentContext().FontId = it->second;
244 : : else
245 : : {
246 [ + - ]: 12 : m_aFontToId[ rFont ] = m_nNextFontId;
247 [ + - ]: 12 : m_aIdToFont[ m_nNextFontId ] = rFont;
248 [ + - ]: 12 : getCurrentContext().FontId = m_nNextFontId;
249 : 12 : m_nNextFontId++;
250 : : }
251 : 33 : }
252 : :
253 : 6 : virtual void strokePath( const uno::Reference<rendering::XPolyPolygon2D>& rPath )
254 : : {
255 [ + - ]: 6 : GraphicsContext& rContext( getCurrentContext() );
256 [ + - ]: 6 : basegfx::B2DPolyPolygon aPath = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
257 [ + - ]: 6 : aPath.transform( rContext.Transformation );
258 : :
259 [ + + ]: 6 : if( rContext.DashArray.empty() )
260 : : {
261 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is green", rContext.LineColor.Alpha, 1.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
262 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is green", rContext.LineColor.Blue, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
263 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is green", rContext.LineColor.Green, 1.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
264 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is green", rContext.LineColor.Red, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
265 : :
266 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Line width is 0",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
267 [ + - ]: 3 : rtl::math::approxEqual(rContext.LineWidth, 28.3) );
268 : :
269 : 3 : const char* sExportString = "m53570 7650-35430 24100";
270 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Stroke is m535.7 518.5-354.3-241",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
271 [ + - ]: 3 : basegfx::tools::exportToSvgD( aPath ).compareToAscii(sExportString) == 0 );
272 : :
273 : 3 : m_bGreenStrokeSeen = true;
274 : : }
275 : : else
276 : : {
277 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Dash array consists of four entries",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
278 : : rContext.DashArray.size() == 4 &&
279 : : rtl::math::approxEqual(rContext.DashArray[0],14.3764) &&
280 : : rContext.DashArray[0] == rContext.DashArray[1] &&
281 : : rContext.DashArray[1] == rContext.DashArray[2] &&
282 [ + - ]: 3 : rContext.DashArray[2] == rContext.DashArray[3] );
283 : :
284 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Alpha, 1.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
285 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Blue, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
286 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Green, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
287 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Red, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
288 : :
289 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line width is 0",
[ + - ][ + - ]
290 [ + - ]: 3 : rContext.LineWidth, 0, 0.0000001 );
291 : :
292 : 3 : const char* sExportString = "m49890 5670.00000000001-35430 24090";
293 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Stroke is m49890 5670.00000000001-35430 24090",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
294 [ + - ]: 3 : basegfx::tools::exportToSvgD( aPath ).compareToAscii(sExportString) == 0 );
295 : :
296 : 3 : m_bDashedLineSeen = true;
297 : : }
298 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE( "Blend mode is normal",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
299 [ + - ]: 6 : rContext.BlendMode == rendering::BlendMode::NORMAL );
300 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE( "Join type is round",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
301 [ + - ]: 6 : rContext.LineJoin == rendering::PathJoinType::ROUND );
302 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE( "Cap type is butt",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
303 [ + - ]: 6 : rContext.LineCap == rendering::PathCapType::BUTT );
304 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line miter limit is 10",
[ + - ][ + - ]
305 [ + - ]: 6 : rContext.MiterLimit, 10, 0.0000001 );
306 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Flatness is 0",
[ + - ][ + - ]
307 [ + - ]: 6 : rContext.Flatness, 1, 0.00000001 );
308 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "Font id is 0",
[ + - ][ + - ]
309 [ + - + - ]: 12 : rContext.FontId, (sal_Int32) 0 );
310 : 6 : }
311 : :
312 : 0 : virtual void fillPath( const uno::Reference<rendering::XPolyPolygon2D>& rPath )
313 : : {
314 [ # # ]: 0 : GraphicsContext& rContext( getCurrentContext() );
315 [ # # ]: 0 : basegfx::B2DPolyPolygon aPath = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
316 [ # # ]: 0 : aPath.transform( rContext.Transformation );
317 : :
318 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Alpha, 1.0, 0.00000001);
[ # # ][ # # ]
[ # # ]
319 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Blue, 0.0, 0.00000001);
[ # # ][ # # ]
[ # # ]
320 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Green, 0.0, 0.00000001);
[ # # ][ # # ]
[ # # ]
321 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Red, 0.0, 0.00000001);
[ # # ][ # # ]
[ # # ]
322 : :
323 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "Blend mode is normal",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
324 [ # # ]: 0 : rContext.BlendMode == rendering::BlendMode::NORMAL );
325 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Flatness is 10",
[ # # ][ # # ]
326 [ # # ]: 0 : rContext.Flatness, 10, 0.00000001 );
327 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "Font id is 0",
[ # # ][ # # ]
328 [ # # # # ]: 0 : rContext.FontId, (sal_Int32) 0 );
329 : 0 : }
330 : :
331 : 3 : virtual void eoFillPath( const uno::Reference<rendering::XPolyPolygon2D>& rPath )
332 : : {
333 [ + - ]: 3 : GraphicsContext& rContext( getCurrentContext() );
334 [ + - ]: 3 : basegfx::B2DPolyPolygon aPath = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
335 [ + - ]: 3 : aPath.transform( rContext.Transformation );
336 : :
337 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Alpha, 1.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
338 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Blue, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
339 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Green, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
340 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Line color is black", rContext.LineColor.Red, 0.0, 0.00000001);
[ + - ][ + - ]
[ + - ]
341 : :
342 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Blend mode is normal",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
343 [ + - ]: 3 : rContext.BlendMode == rendering::BlendMode::NORMAL );
344 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Flatness is 0",
[ + - ][ + - ]
345 [ + - ]: 3 : rContext.Flatness, 1, 0.00000001 );
346 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "Font id is 0",
[ + - ][ + - ]
347 [ + - ]: 3 : rContext.FontId, (sal_Int32) 0 );
348 : :
349 : : const char* sExportString = "m12050 49610c-4310 0-7800-3490-7800-7800 0-4300 "
350 : 3 : "3490-7790 7800-7790 4300 0 7790 3490 7790 7790 0 4310-3490 7800-7790 7800z";
351 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE( "Stroke is a 4-bezier circle",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
352 [ + - ]: 3 : basegfx::tools::exportToSvgD( aPath ).compareToAscii(sExportString) == 0 );
353 : :
354 [ + - ]: 3 : m_bRedCircleSeen = true;
355 : 3 : }
356 : :
357 : 3 : virtual void intersectClip(const uno::Reference<rendering::XPolyPolygon2D>& rPath)
358 : : {
359 [ + - ]: 3 : basegfx::B2DPolyPolygon aNewClip = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
360 [ + - ][ + - ]: 3 : basegfx::B2DPolyPolygon aCurClip = getCurrentContext().Clip;
361 : :
362 [ + - ][ - + ]: 3 : if( aCurClip.count() ) // #i92985# adapted API from (..., false, false) to (..., true, false)
363 [ # # ][ # # ]: 0 : aNewClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aCurClip, aNewClip, true, false );
[ # # ]
364 : :
365 [ + - ][ + - ]: 3 : getCurrentContext().Clip = aNewClip;
[ + - ][ + - ]
366 : 3 : }
367 : :
368 : 3 : virtual void intersectEoClip(const uno::Reference<rendering::XPolyPolygon2D>& rPath)
369 : : {
370 [ + - ]: 3 : basegfx::B2DPolyPolygon aNewClip = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
371 [ + - ][ + - ]: 3 : basegfx::B2DPolyPolygon aCurClip = getCurrentContext().Clip;
372 : :
373 [ + - ][ + - ]: 3 : if( aCurClip.count() ) // #i92985# adapted API from (..., false, false) to (..., true, false)
374 [ + - ][ + - ]: 3 : aNewClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aCurClip, aNewClip, true, false );
[ + - ]
375 : :
376 [ + - ][ + - ]: 3 : getCurrentContext().Clip = aNewClip;
[ + - ][ + - ]
377 : 3 : }
378 : :
379 : 312 : virtual void drawGlyphs( const rtl::OUString& rGlyphs,
380 : : const geometry::RealRectangle2D& /*rRect*/,
381 : : const geometry::Matrix2D& /*rFontMatrix*/ )
382 : : {
383 : 312 : m_aTextOut.append(rGlyphs);
384 : 312 : }
385 : :
386 : 33 : virtual void endText()
387 : : {
388 [ + - ]: 33 : m_aTextOut.append( ::rtl::OUString("\n") );
389 : 33 : }
390 : :
391 : 0 : virtual void drawMask(const uno::Sequence<beans::PropertyValue>& xBitmap,
392 : : bool /*bInvert*/ )
393 : : {
394 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawMask received two properties",
[ # # ][ # # ]
395 [ # # ]: 0 : xBitmap.getLength(), (sal_Int32) 3 );
396 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawMask got URL param",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
397 [ # # ]: 0 : xBitmap[0].Name.compareToAscii( "URL" ) == 0 );
398 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawMask got InputStream param",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
399 [ # # ]: 0 : xBitmap[1].Name.compareToAscii( "InputStream" ) == 0 );
400 : 0 : }
401 : :
402 : 0 : virtual void drawImage(const uno::Sequence<beans::PropertyValue>& xBitmap )
403 : : {
404 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawImage received two properties",
[ # # ][ # # ]
405 [ # # ]: 0 : xBitmap.getLength(), (sal_Int32) 3 );
406 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawImage got URL param",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
407 [ # # ]: 0 : xBitmap[0].Name.compareToAscii( "URL" ) == 0 );
408 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawImage got InputStream param",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
409 [ # # ]: 0 : xBitmap[1].Name.compareToAscii( "InputStream" ) == 0 );
410 : 0 : }
411 : :
412 : 0 : virtual void drawColorMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
413 : : const uno::Sequence<uno::Any>& /*xMaskColors*/ )
414 : : {
415 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawColorMaskedImage received two properties",
[ # # ][ # # ]
416 [ # # ]: 0 : xBitmap.getLength(), (sal_Int32) 3 );
417 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawColorMaskedImage got URL param",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
418 [ # # ]: 0 : xBitmap[0].Name.compareToAscii( "URL" ) == 0 );
419 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawColorMaskedImage got InputStream param",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
420 [ # # ]: 0 : xBitmap[1].Name.compareToAscii( "InputStream" ) == 0 );
421 : 0 : }
422 : :
423 : 0 : virtual void drawMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
424 : : const uno::Sequence<beans::PropertyValue>& xMask,
425 : : bool /*bInvertMask*/)
426 : : {
427 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawMaskedImage received two properties #1",
[ # # ][ # # ]
428 [ # # ]: 0 : xBitmap.getLength(), (sal_Int32) 3 );
429 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawMaskedImage got URL param #1",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
430 [ # # ]: 0 : xBitmap[0].Name.compareToAscii( "URL" ) == 0 );
431 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawMaskedImage got InputStream param #1",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
432 [ # # ]: 0 : xBitmap[1].Name.compareToAscii( "InputStream" ) == 0 );
433 : :
434 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawMaskedImage received two properties #2",
[ # # ][ # # ]
435 [ # # ]: 0 : xMask.getLength(), (sal_Int32) 3 );
436 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawMaskedImage got URL param #2",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
437 [ # # ]: 0 : xMask[0].Name.compareToAscii( "URL" ) == 0 );
438 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawMaskedImage got InputStream param #2",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
439 [ # # ]: 0 : xMask[1].Name.compareToAscii( "InputStream" ) == 0 );
440 : 0 : }
441 : :
442 : 0 : virtual void drawAlphaMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
443 : : const uno::Sequence<beans::PropertyValue>& xMask)
444 : : {
445 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawAlphaMaskedImage received two properties #1",
[ # # ][ # # ]
446 [ # # ]: 0 : xBitmap.getLength(), (sal_Int32) 3 );
447 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawAlphaMaskedImage got URL param #1",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
448 [ # # ]: 0 : xBitmap[0].Name.compareToAscii( "URL" ) == 0 );
449 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawAlphaMaskedImage got InputStream param #1",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
450 [ # # ]: 0 : xBitmap[1].Name.compareToAscii( "InputStream" ) == 0 );
451 : :
452 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE( "drawAlphaMaskedImage received two properties #2",
[ # # ][ # # ]
453 [ # # ]: 0 : xMask.getLength(), (sal_Int32) 3 );
454 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawAlphaMaskedImage got URL param #2",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
455 [ # # ]: 0 : xMask[0].Name.compareToAscii( "URL" ) == 0 );
456 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE( "drawAlphaMaskedImage got InputStream param #2",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
457 [ # # ]: 0 : xMask[1].Name.compareToAscii( "InputStream" ) == 0 );
458 : 0 : }
459 : :
460 : 0 : virtual void setTextRenderMode( sal_Int32 )
461 : : {
462 : 0 : }
463 : :
464 : : typedef boost::unordered_map<sal_Int32,FontAttributes> IdToFontMap;
465 : : typedef boost::unordered_map<FontAttributes,sal_Int32,FontAttrHash> FontToIdMap;
466 : :
467 : : typedef std::vector<GraphicsContext> GraphicsContextStack;
468 : :
469 : : sal_Int32 m_nNextFontId;
470 : : IdToFontMap m_aIdToFont;
471 : : FontToIdMap m_aFontToId;
472 : :
473 : : GraphicsContextStack m_aGCStack;
474 : : geometry::RealSize2D m_aPageSize;
475 : : geometry::RealRectangle2D m_aHyperlinkBounds;
476 : : ::rtl::OUString m_aURI;
477 : : ::rtl::OUStringBuffer m_aTextOut;
478 : : sal_Int32 m_nNumPages;
479 : : bool m_bPageEnded;
480 : : bool m_bRedCircleSeen;
481 : : bool m_bGreenStrokeSeen;
482 : : bool m_bDashedLineSeen;
483 : : };
484 : :
485 : : /*
486 : : This is a (hackish) way to set correct path to the xpdfimport executable
487 : : during build. Because $OUTDIR/bin is not in $PATH, it will not be found
488 : : directly. We also know that xpdf_ImportFromFile() tries to get the path
489 : : through the extension mechanism, but there are no registered extensions
490 : : available when this test is run. So we create a phony
491 : : PackageInformationProvider that pretends such extension exists and passes
492 : : out the path we need .-)
493 : : */
494 : :
495 : : typedef cppu::WeakComponentImplHelper1<deployment::XPackageInformationProvider> PackageInformationProvider_Base;
496 : :
497 [ + - ][ - + ]: 18 : class PackageInformationProvider
498 : : : private cppu::BaseMutex
499 : : , public PackageInformationProvider_Base
500 : : {
501 : : public:
502 : 9 : PackageInformationProvider()
503 : 9 : : PackageInformationProvider_Base(m_aMutex)
504 : : {
505 : 9 : }
506 : :
507 : : private:
508 : 9 : virtual rtl::OUString SAL_CALL getPackageLocation(rtl::OUString const&)
509 : : throw()
510 : : {
511 : 9 : rtl::OUString const aLocation(PDFIMPORT_EXECUTABLE_LOCATION);
512 : 9 : return aLocation;
513 : : }
514 : :
515 : 0 : virtual uno::Sequence<uno::Sequence<rtl::OUString> > SAL_CALL isUpdateAvailable(rtl::OUString const&)
516 : : throw()
517 : : {
518 : : // dummy impl.
519 : 0 : uno::Sequence<uno::Sequence<rtl::OUString> > const aSeq;
520 : 0 : return aSeq;
521 : : }
522 : :
523 : 0 : virtual uno::Sequence<uno::Sequence<rtl::OUString> > SAL_CALL getExtensionList()
524 : : throw()
525 : : {
526 : : // dummy impl.
527 : 0 : uno::Sequence<uno::Sequence<rtl::OUString> > const aSeq;
528 : 0 : return aSeq;
529 : : }
530 : : };
531 : :
532 : : typedef cppu::WeakComponentImplHelper1<uno::XComponentContext> ComponentContext_Base;
533 : :
534 [ + - ][ - + ]: 18 : class ComponentContext
535 : : : private cppu::BaseMutex
536 : : , public ComponentContext_Base
537 : : {
538 : : public:
539 : 9 : explicit ComponentContext(uno::Reference<uno::XComponentContext> const& xParent)
540 : : : ComponentContext_Base(m_aMutex)
541 : 9 : , m_xParent(xParent)
542 : : {
543 : : assert(m_xParent.is());
544 : 9 : }
545 : :
546 : : private:
547 : 9 : virtual uno::Any SAL_CALL getValueByName(rtl::OUString const& rName)
548 : : throw()
549 : : {
550 [ + - ]: 9 : if ( rName == "/singletons/com.sun.star.deployment.PackageInformationProvider" )
551 : : {
552 [ + - ][ + - ]: 9 : uno::Reference<deployment::XPackageInformationProvider> const xProvider(new PackageInformationProvider());
[ + - ]
553 : 9 : uno::Any aComponent;
554 [ + - ]: 9 : aComponent <<= xProvider;
555 : 9 : return aComponent;
556 : : }
557 : :
558 : 9 : return m_xParent->getValueByName(rName);
559 : : }
560 : :
561 : 39 : virtual uno::Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager()
562 : : throw()
563 : : {
564 : 39 : return m_xParent->getServiceManager();
565 : : }
566 : :
567 : : private:
568 : : uno::Reference<uno::XComponentContext> m_xParent;
569 : : };
570 : :
571 [ - + ]: 27 : class PDFITest : public test::BootstrapFixture
572 : : {
573 : : public:
574 : 3 : void testXPDFParser()
575 : : {
576 [ + - ][ + - ]: 3 : pdfi::ContentSinkSharedPtr pSink( new TestSink() );
[ + - ]
577 : : pdfi::xpdf_ImportFromFile( getURLFromSrc("/sdext/source/pdfimport/test/testinput.pdf"),
578 : : pSink,
579 : : uno::Reference< task::XInteractionHandler >(),
580 : : rtl::OUString(),
581 [ + - ][ + - ]: 3 : impl_getComponentContext() );
[ + - ]
582 : :
583 : : // make destruction explicit, a bunch of things are
584 : : // checked in the destructor
585 [ + - ][ + - ]: 3 : pSink.reset();
586 : 3 : }
587 : :
588 : 3 : void testOdfDrawExport()
589 : : {
590 [ + - ][ + - ]: 3 : pdfi::PDFIRawAdaptor aAdaptor( impl_getComponentContext() );
591 [ + - ][ + - ]: 3 : aAdaptor.setTreeVisitorFactory( createDrawTreeVisitorFactory() );
[ + - ]
592 : :
593 : 3 : ::rtl::OUString tempFileURL;
594 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT( osl::File::createTempFile( NULL, NULL, &tempFileURL ) == osl::File::E_None );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
595 [ + - ]: 3 : osl::File::remove( tempFileURL ); // FIXME the below apparently fails silently if the file already exists
596 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Exporting to ODF",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
597 : : aAdaptor.odfConvert( getURLFromSrc("/sdext/source/pdfimport/test/testinput.pdf"),
598 : : new OutputWrap(tempFileURL),
599 [ + - ]: 3 : NULL ));
600 [ + - ][ + - ]: 3 : osl::File::remove( tempFileURL );
601 : 3 : }
602 : :
603 : 3 : void testOdfWriterExport()
604 : : {
605 [ + - ][ + - ]: 3 : pdfi::PDFIRawAdaptor aAdaptor( impl_getComponentContext() );
606 [ + - ][ + - ]: 3 : aAdaptor.setTreeVisitorFactory( createWriterTreeVisitorFactory() );
[ + - ]
607 : :
608 : 3 : ::rtl::OUString tempFileURL;
609 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT( osl::File::createTempFile( NULL, NULL, &tempFileURL ) == osl::File::E_None );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
610 [ + - ]: 3 : osl::File::remove( tempFileURL ); // FIXME the below apparently fails silently if the file already exists
611 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Exporting to ODF",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
612 : : aAdaptor.odfConvert( getURLFromSrc("/sdext/source/pdfimport/test/testinput.pdf"),
613 : : new OutputWrap(tempFileURL),
614 [ + - ]: 3 : NULL ));
615 [ + - ][ + - ]: 3 : osl::File::remove( tempFileURL );
616 : 3 : }
617 : :
618 [ + - ][ + - ]: 6 : CPPUNIT_TEST_SUITE(PDFITest);
[ + - ][ + - ]
[ # # ]
619 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testXPDFParser);
[ + - ][ + - ]
[ + - ][ + - ]
620 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testOdfWriterExport);
[ + - ][ + - ]
[ + - ][ + - ]
621 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testOdfDrawExport);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
622 [ + - ][ + - ]: 6 : CPPUNIT_TEST_SUITE_END();
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
623 : :
624 : : private:
625 : 9 : uno::Reference<uno::XComponentContext> impl_getComponentContext()
626 : : {
627 [ + - ][ + - ]: 9 : uno::Reference<uno::XComponentContext> const xCtxt(new ComponentContext(getComponentContext()));
[ + - ]
628 : 9 : return xCtxt;
629 : : }
630 : : };
631 : :
632 : : }
633 : :
634 : 3 : CPPUNIT_TEST_SUITE_REGISTRATION(PDFITest);
635 : :
636 [ + - ][ + - ]: 12 : CPPUNIT_PLUGIN_IMPLEMENT();
[ + - ][ + - ]
[ + - ][ # # ]
637 : :
638 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|