1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26
27 #define BASEGFX_STATICLIBRARY
28
29 #ifdef SYSTEM_ZLIB
30 #include "zlib.h"
31 #else
32 #include <zlib/zlib.h>
33 #endif
34
35 #include "outputwrap.hxx"
36 #include "contentsink.hxx"
37 #include "pdfihelper.hxx"
38 #include "wrapper.hxx"
39 #include "pdfparse.hxx"
40 #include "../pdfiadaptor.hxx"
41
42 #include <rtl/math.hxx>
43 #include <osl/file.hxx>
44 #include <osl/process.h>
45 #include <gtest/gtest.h>
46 #include <cppuhelper/compbase1.hxx>
47 #include <cppuhelper/bootstrap.hxx>
48 #include <cppuhelper/basemutex.hxx>
49 #include <comphelper/sequence.hxx>
50
51
52 #include <com/sun/star/rendering/XCanvas.hpp>
53 #include <com/sun/star/rendering/XColorSpace.hpp>
54 #include <com/sun/star/rendering/PathJoinType.hpp>
55 #include <com/sun/star/rendering/PathCapType.hpp>
56 #include <com/sun/star/rendering/BlendMode.hpp>
57 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
58 #include <com/sun/star/lang/XInitialization.hpp>
59 #include <com/sun/star/registry/XSimpleRegistry.hpp>
60
61 #include <basegfx/matrix/b2dhommatrix.hxx>
62 #include <basegfx/tools/canvastools.hxx>
63 #include <basegfx/polygon/b2dpolygon.hxx>
64 #include <basegfx/polygon/b2dpolypolygon.hxx>
65 #include <basegfx/polygon/b2dpolypolygontools.hxx>
66 #include <basegfx/polygon/b2dpolygonclipper.hxx>
67
68 #include <vector>
69 #include <hash_map>
70
71
72 using namespace ::pdfparse;
73 using namespace ::pdfi;
74 using namespace ::com::sun::star;
75
76 namespace
77 {
78 class TestSink : public ContentSink
79 {
80 public:
TestSink()81 TestSink() :
82 m_nNextFontId( 1 ),
83 m_aIdToFont(),
84 m_aFontToId(),
85 m_aGCStack(1),
86 m_aPageSize(),
87 m_aHyperlinkBounds(),
88 m_aURI(),
89 m_aTextOut(),
90 m_nNumPages(0),
91 m_bPageEnded(false),
92 m_bRedCircleSeen(false),
93 m_bGreenStrokeSeen(false),
94 m_bDashedLineSeen(false)
95 {}
96
~TestSink()97 ~TestSink()
98 {
99 ASSERT_TRUE(m_aPageSize.Width == 79400 && m_aPageSize.Height == 59500) << "A4 page size (in 100th of points)";
100 ASSERT_TRUE(m_bPageEnded) << "endPage() called";
101 ASSERT_TRUE(m_nNumPages == 1) << "Num pages equal one";
102 ASSERT_TRUE(rtl::math::approxEqual(m_aHyperlinkBounds.X1,34.7 ) &&
103 rtl::math::approxEqual(m_aHyperlinkBounds.Y1,386.0) &&
104 rtl::math::approxEqual(m_aHyperlinkBounds.X2,166.7) &&
105 rtl::math::approxEqual(m_aHyperlinkBounds.Y2,406.2)) << "Correct hyperlink bounding box";
106 ASSERT_TRUE(m_aURI == ::rtl::OUString::createFromAscii( "http://download.openoffice.org/" )) << "Correct hyperlink URI";
107
108 const char* sText = " \n \nThis is a testtext\nNew paragraph,\nnew line\n"
109 "Hyperlink, this is\n?\nThis is more text\noutline mode\n?\nNew paragraph\n";
110 ::rtl::OString aTmp;
111 m_aTextOut.makeStringAndClear().convertToString( &aTmp,
112 RTL_TEXTENCODING_ASCII_US,
113 OUSTRING_TO_OSTRING_CVTFLAGS );
114 ASSERT_TRUE( sText == aTmp ) << "Imported text is \"This is a testtext New paragraph, new line"
115 " Hyperlink, this is * This is more text outline mode * New paragraph\"";
116
117 ASSERT_TRUE(m_bRedCircleSeen) << "red circle seen in input";
118 ASSERT_TRUE(m_bGreenStrokeSeen) << "green stroke seen in input";
119 ASSERT_TRUE(m_bDashedLineSeen) << "dashed line seen in input";
120 }
121
122 private:
getCurrentContext()123 GraphicsContext& getCurrentContext() { return m_aGCStack.back(); }
124
125 // ContentSink interface implementation
setPageNum(sal_Int32 nNumPages)126 virtual void setPageNum( sal_Int32 nNumPages )
127 {
128 m_nNumPages = nNumPages;
129 }
130
startPage(const geometry::RealSize2D & rSize)131 virtual void startPage( const geometry::RealSize2D& rSize )
132 {
133 m_aPageSize = rSize;
134 }
135
endPage()136 virtual void endPage()
137 {
138 m_bPageEnded = true;
139 }
140
hyperLink(const geometry::RealRectangle2D & rBounds,const::rtl::OUString & rURI)141 virtual void hyperLink( const geometry::RealRectangle2D& rBounds,
142 const ::rtl::OUString& rURI )
143 {
144 m_aHyperlinkBounds = rBounds;
145 m_aURI = rURI;
146 }
147
pushState()148 virtual void pushState()
149 {
150 m_aGCStack.push_back( m_aGCStack.back() );
151 }
152
popState()153 virtual void popState()
154 {
155 m_aGCStack.pop_back();
156 }
157
setTransformation(const geometry::AffineMatrix2D & rMatrix)158 virtual void setTransformation( const geometry::AffineMatrix2D& rMatrix )
159 {
160 basegfx::unotools::homMatrixFromAffineMatrix(
161 getCurrentContext().Transformation,
162 rMatrix );
163 }
164
setLineDash(const uno::Sequence<double> & dashes,double start)165 virtual void setLineDash( const uno::Sequence<double>& dashes,
166 double start )
167 {
168 GraphicsContext& rContext( getCurrentContext() );
169 if( dashes.getLength() )
170 comphelper::sequenceToContainer(rContext.DashArray,dashes);
171 ASSERT_TRUE(start == 0.0) << "line dashing start offset";
172 }
173
setFlatness(double nFlatness)174 virtual void setFlatness( double nFlatness )
175 {
176 getCurrentContext().Flatness = nFlatness;
177 }
178
setLineJoin(sal_Int8 nJoin)179 virtual void setLineJoin(sal_Int8 nJoin)
180 {
181 getCurrentContext().LineJoin = nJoin;
182 }
183
setLineCap(sal_Int8 nCap)184 virtual void setLineCap(sal_Int8 nCap)
185 {
186 getCurrentContext().LineCap = nCap;
187 }
188
setMiterLimit(double nVal)189 virtual void setMiterLimit(double nVal)
190 {
191 getCurrentContext().MiterLimit = nVal;
192 }
193
setLineWidth(double nVal)194 virtual void setLineWidth(double nVal)
195 {
196 getCurrentContext().LineWidth = nVal;
197 }
198
setFillColor(const rendering::ARGBColor & rColor)199 virtual void setFillColor( const rendering::ARGBColor& rColor )
200 {
201 getCurrentContext().FillColor = rColor;
202 }
203
setStrokeColor(const rendering::ARGBColor & rColor)204 virtual void setStrokeColor( const rendering::ARGBColor& rColor )
205 {
206 getCurrentContext().LineColor = rColor;
207 }
208
setBlendMode(sal_Int8 nMode)209 virtual void setBlendMode(sal_Int8 nMode)
210 {
211 getCurrentContext().BlendMode = nMode;
212 }
213
setFont(const FontAttributes & rFont)214 virtual void setFont( const FontAttributes& rFont )
215 {
216 FontToIdMap::const_iterator it = m_aFontToId.find( rFont );
217 if( it != m_aFontToId.end() )
218 getCurrentContext().FontId = it->second;
219 else
220 {
221 m_aFontToId[ rFont ] = m_nNextFontId;
222 m_aIdToFont[ m_nNextFontId ] = rFont;
223 getCurrentContext().FontId = m_nNextFontId;
224 m_nNextFontId++;
225 }
226 }
227
strokePath(const uno::Reference<rendering::XPolyPolygon2D> & rPath)228 virtual void strokePath( const uno::Reference<rendering::XPolyPolygon2D>& rPath )
229 {
230 GraphicsContext& rContext( getCurrentContext() );
231 basegfx::B2DPolyPolygon aPath = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
232 aPath.transform( rContext.Transformation );
233
234 if( rContext.DashArray.empty() )
235 {
236 ASSERT_TRUE(rContext.LineColor.Alpha == 1.0 &&
237 rContext.LineColor.Red == 0.0 &&
238 rContext.LineColor.Green == 1.0 &&
239 rContext.LineColor.Blue == 0.0) << "Line color is green";
240
241 ASSERT_TRUE(rtl::math::approxEqual(rContext.LineWidth, 28.3)) << "Line width is 0";
242
243 const char* sExportString = "m53570 7650-35430 24100";
244 ASSERT_TRUE(basegfx::tools::exportToSvgD( aPath, true, true, false ).compareToAscii(sExportString) == 0) << "Stroke is m535.7 518.5-354.3-241";
245
246 m_bGreenStrokeSeen = true;
247 }
248 else
249 {
250 ASSERT_TRUE(rContext.DashArray.size() == 4 &&
251 rtl::math::approxEqual(rContext.DashArray[0],14.3764) &&
252 rContext.DashArray[0] == rContext.DashArray[1] &&
253 rContext.DashArray[1] == rContext.DashArray[2] &&
254 rContext.DashArray[2] == rContext.DashArray[3]) << "Dash array cons ists of four entries";
255
256 ASSERT_TRUE(rContext.LineColor.Alpha == 1.0 &&
257 rContext.LineColor.Red == 0.0 &&
258 rContext.LineColor.Green == 0.0 &&
259 rContext.LineColor.Blue == 0.0) << "Line color is black";
260
261 ASSERT_TRUE(rContext.LineWidth == 0) << "Line width is 0";
262
263 const char* sExportString = "m49890 5670.00000000001-35430 24090";
264 ASSERT_TRUE(basegfx::tools::exportToSvgD( aPath, true, true, false ).compareToAscii(sExportString) == 0) << "Stroke is m49890 5670.00000000001-35430 24090";
265
266 m_bDashedLineSeen = true;
267 }
268 ASSERT_TRUE(rContext.BlendMode == rendering::BlendMode::NORMAL) << "Blend mode is normal";
269 ASSERT_TRUE(rContext.LineJoin == rendering::PathJoinType::ROUND) << "Join type is round";
270 ASSERT_TRUE(rContext.LineCap == rendering::PathCapType::BUTT) << "Cap type is butt";
271 ASSERT_TRUE(rContext.MiterLimit == 10) << "Line miter limit is 10";
272 ASSERT_TRUE(rContext.Flatness == 1) << "Flatness is 0";
273 ASSERT_TRUE(rContext.FontId == 0) << "Font id is 0";
274 }
275
fillPath(const uno::Reference<rendering::XPolyPolygon2D> & rPath)276 virtual void fillPath( const uno::Reference<rendering::XPolyPolygon2D>& rPath )
277 {
278 GraphicsContext& rContext( getCurrentContext() );
279 basegfx::B2DPolyPolygon aPath = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
280 aPath.transform( rContext.Transformation );
281
282 ASSERT_TRUE(rContext.FillColor.Alpha == 1.0 &&
283 rContext.FillColor.Red == 0.0 &&
284 rContext.FillColor.Green == 0.0 &&
285 rContext.FillColor.Blue == 0.0) << "Fill color is black";
286 ASSERT_TRUE(rContext.BlendMode == rendering::BlendMode::NORMAL) << "Blend mode is normal";
287 ASSERT_TRUE(rContext.Flatness == 10) << "Flatness is 10";
288 ASSERT_TRUE(rContext.FontId == 0) << "Font id is 0";
289 }
290
eoFillPath(const uno::Reference<rendering::XPolyPolygon2D> & rPath)291 virtual void eoFillPath( const uno::Reference<rendering::XPolyPolygon2D>& rPath )
292 {
293 GraphicsContext& rContext( getCurrentContext() );
294 basegfx::B2DPolyPolygon aPath = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
295 aPath.transform( rContext.Transformation );
296
297 ASSERT_TRUE(rContext.FillColor.Alpha == 1.0 &&
298 rContext.FillColor.Red == 1.0 &&
299 rContext.FillColor.Green == 0.0 &&
300 rContext.FillColor.Blue == 0.0) << "Fill color is black";
301 ASSERT_TRUE(rContext.BlendMode == rendering::BlendMode::NORMAL) << "Blend mode is normal";
302 ASSERT_TRUE(rContext.Flatness == 1) << "Flatness is 0";
303 ASSERT_TRUE(rContext.FontId == 0) << "Font id is 0";
304
305 const char* sExportString = "m12050 49610c-4310 0-7800-3490-7800-7800 0-4300 "
306 "3490-7790 7800-7790 4300 0 7790 3490 7790 7790 0 4310-3490 7800-7790 7800z";
307 ASSERT_TRUE(basegfx::tools::exportToSvgD( aPath, true, true, false ).compareToAscii(sExportString) == 0) << "Stroke is a 4-bezier circle";
308
309 m_bRedCircleSeen = true;
310 }
311
intersectClip(const uno::Reference<rendering::XPolyPolygon2D> & rPath)312 virtual void intersectClip(const uno::Reference<rendering::XPolyPolygon2D>& rPath)
313 {
314 basegfx::B2DPolyPolygon aNewClip = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
315 basegfx::B2DPolyPolygon aCurClip = getCurrentContext().Clip;
316
317 if( aCurClip.count() ) // #i92985# adapted API from (..., false, false) to (..., true, false)
318 aNewClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aCurClip, aNewClip, true, false );
319
320 getCurrentContext().Clip = aNewClip;
321 }
322
intersectEoClip(const uno::Reference<rendering::XPolyPolygon2D> & rPath)323 virtual void intersectEoClip(const uno::Reference<rendering::XPolyPolygon2D>& rPath)
324 {
325 basegfx::B2DPolyPolygon aNewClip = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
326 basegfx::B2DPolyPolygon aCurClip = getCurrentContext().Clip;
327
328 if( aCurClip.count() ) // #i92985# adapted API from (..., false, false) to (..., true, false)
329 aNewClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aCurClip, aNewClip, true, false );
330
331 getCurrentContext().Clip = aNewClip;
332 }
333
drawGlyphs(const rtl::OUString & rGlyphs,const geometry::RealRectangle2D &,const geometry::Matrix2D &)334 virtual void drawGlyphs( const rtl::OUString& rGlyphs,
335 const geometry::RealRectangle2D& /*rRect*/,
336 const geometry::Matrix2D& /*rFontMatrix*/ )
337 {
338 m_aTextOut.append(rGlyphs);
339 }
340
endText()341 virtual void endText()
342 {
343 m_aTextOut.append( ::rtl::OUString::createFromAscii("\n") );
344 }
345
drawMask(const uno::Sequence<beans::PropertyValue> & xBitmap,bool)346 virtual void drawMask(const uno::Sequence<beans::PropertyValue>& xBitmap,
347 bool /*bInvert*/ )
348 {
349 ASSERT_TRUE(xBitmap.getLength()==3) << "drawMask received two properties";
350 ASSERT_TRUE(xBitmap[0].Name.compareToAscii( "URL" ) == 0) << "drawMask got URL param";
351 ASSERT_TRUE(xBitmap[1].Name.compareToAscii( "InputStream" ) == 0) << "drawMask got InputStream param";
352 }
353
drawImage(const uno::Sequence<beans::PropertyValue> & xBitmap)354 virtual void drawImage(const uno::Sequence<beans::PropertyValue>& xBitmap )
355 {
356 ASSERT_TRUE(xBitmap.getLength()==3) << "drawImage received two properties";
357 ASSERT_TRUE(xBitmap[0].Name.compareToAscii( "URL" ) == 0) << "drawImage got URL param";
358 ASSERT_TRUE(xBitmap[1].Name.compareToAscii( "InputStream" ) == 0) << "drawImage got InputStream param";
359 }
360
drawColorMaskedImage(const uno::Sequence<beans::PropertyValue> & xBitmap,const uno::Sequence<uno::Any> &)361 virtual void drawColorMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
362 const uno::Sequence<uno::Any>& /*xMaskColors*/ )
363 {
364 ASSERT_TRUE(xBitmap.getLength()==3) << "drawColorMaskedImage received two properties";
365 ASSERT_TRUE(xBitmap[0].Name.compareToAscii( "URL" ) == 0) << "drawColorMaskedImage got URL param";
366 ASSERT_TRUE(xBitmap[1].Name.compareToAscii( "InputStream" ) == 0) << "drawColorMaskedImage got InputStream param";
367 }
368
drawMaskedImage(const uno::Sequence<beans::PropertyValue> & xBitmap,const uno::Sequence<beans::PropertyValue> & xMask,bool)369 virtual void drawMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
370 const uno::Sequence<beans::PropertyValue>& xMask,
371 bool /*bInvertMask*/)
372 {
373 ASSERT_TRUE(xBitmap.getLength()==3) << "drawMaskedImage received two properties #1";
374 ASSERT_TRUE(xBitmap[0].Name.compareToAscii( "URL" ) == 0) << "drawMaskedImage got URL param #1";
375 ASSERT_TRUE(xBitmap[1].Name.compareToAscii( "InputStream" ) == 0) << "drawMaskedImage got InputStream param #1";
376
377 ASSERT_TRUE(xMask.getLength()==3) << "drawMaskedImage received two properties #2";
378 ASSERT_TRUE(xMask[0].Name.compareToAscii( "URL" ) == 0) << "drawMaskedImage got URL param #2";
379 ASSERT_TRUE(xMask[1].Name.compareToAscii( "InputStream" ) == 0) << "drawMaskedImage got InputStream param #2";
380 }
381
drawAlphaMaskedImage(const uno::Sequence<beans::PropertyValue> & xBitmap,const uno::Sequence<beans::PropertyValue> & xMask)382 virtual void drawAlphaMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
383 const uno::Sequence<beans::PropertyValue>& xMask)
384 {
385 ASSERT_TRUE(xBitmap.getLength()==3) << "drawAlphaMaskedImage received two properties #1";
386 ASSERT_TRUE(xBitmap[0].Name.compareToAscii( "URL" ) == 0) << "drawAlphaMaskedImage got URL param #1";
387 ASSERT_TRUE(xBitmap[1].Name.compareToAscii( "InputStream" ) == 0) << "drawAlphaMaskedImage got InputStream param #1";
388
389 ASSERT_TRUE(xMask.getLength()==3) << "drawAlphaMaskedImage received two properties #2";
390 ASSERT_TRUE(xMask[0].Name.compareToAscii( "URL" ) == 0) << "drawAlphaMaskedImage got URL param #2";
391 ASSERT_TRUE(xMask[1].Name.compareToAscii( "InputStream" ) == 0) << "drawAlphaMaskedImage got InputStream param #2";
392 }
393
setTextRenderMode(sal_Int32)394 virtual void setTextRenderMode( sal_Int32 )
395 {
396 }
397
398 typedef std::hash_map<sal_Int32,FontAttributes> IdToFontMap;
399 typedef std::hash_map<FontAttributes,sal_Int32,FontAttrHash> FontToIdMap;
400
401 typedef std::hash_map<sal_Int32,GraphicsContext> IdToGCMap;
402 typedef std::hash_map<GraphicsContext,sal_Int32,GraphicsContextHash> GCToIdMap;
403
404 typedef std::vector<GraphicsContext> GraphicsContextStack;
405
406 sal_Int32 m_nNextFontId;
407 IdToFontMap m_aIdToFont;
408 FontToIdMap m_aFontToId;
409
410 GraphicsContextStack m_aGCStack;
411 geometry::RealSize2D m_aPageSize;
412 geometry::RealRectangle2D m_aHyperlinkBounds;
413 ::rtl::OUString m_aURI;
414 ::rtl::OUStringBuffer m_aTextOut;
415 sal_Int32 m_nNumPages;
416 bool m_bPageEnded;
417 bool m_bRedCircleSeen;
418 bool m_bGreenStrokeSeen;
419 bool m_bDashedLineSeen;
420 };
421
422 class PDFITest : public ::testing::Test
423 {
424 protected:
425 uno::Reference<uno::XComponentContext> mxCtx;
426 rtl::OUString msBaseDir;
427 bool mbUnoInitialized;
428
429 public:
PDFITest()430 PDFITest() : mxCtx(),msBaseDir(),mbUnoInitialized(false)
431 {}
432
SetUp()433 void SetUp()
434 {
435 if( !mbUnoInitialized )
436 {
437 const char* pArgs( getenv("TESTS_FORWARD_STRING") );
438 ASSERT_TRUE(pArgs) << "Test file parameter";
439
440 msBaseDir = rtl::OUString::createFromAscii(pArgs);
441
442 // bootstrap UNO
443 try
444 {
445 ::rtl::OUString aIniUrl;
446 ASSERT_TRUE(
447 osl_getFileURLFromSystemPath(
448 (msBaseDir+rtl::OUString::createFromAscii("pdfi_unittest_test.ini")).pData,
449 &aIniUrl.pData ) == osl_File_E_None )
450 << "Converting ini file to URL";
451
452 mxCtx = ::cppu::defaultBootstrap_InitialComponentContext(aIniUrl);
453 ASSERT_TRUE(mxCtx.is()) << "Getting component context";
454 }
455 catch( uno::Exception& )
456 {
457 FAIL() << "Bootstrapping UNO";
458 }
459
460 mbUnoInitialized = true;
461 }
462 }
TearDown()463 void TearDown()
464 {
465 }
466 };
467
TEST_F(PDFITest,testXPDFParser)468 TEST_F(PDFITest, testXPDFParser)
469 {
470 pdfi::ContentSinkSharedPtr pSink( new TestSink() );
471 pdfi::xpdf_ImportFromFile( msBaseDir + rtl::OUString::createFromAscii("pdfi_unittest_test.pdf"),
472 pSink,
473 uno::Reference< task::XInteractionHandler >(),
474 rtl::OUString(),
475 mxCtx );
476
477 // make destruction explicit, a bunch of things are
478 // checked in the destructor
479 pSink.reset();
480 }
481
TEST_F(PDFITest,testOdfDrawExport)482 TEST_F(PDFITest, testOdfDrawExport)
483 {
484 pdfi::PDFIRawAdaptor aAdaptor( mxCtx );
485 aAdaptor.setTreeVisitorFactory( createDrawTreeVisitorFactory() );
486
487 ::rtl::OUString aURL, aAbsURL, aBaseURL;
488 osl_getFileURLFromSystemPath( (msBaseDir + rtl::OUString::createFromAscii("pdfi_unittest_draw.xml")).pData,
489 &aURL.pData );
490 osl_getProcessWorkingDir(&aBaseURL.pData);
491 osl_getAbsoluteFileURL(aBaseURL.pData,aURL.pData,&aAbsURL.pData);
492 ASSERT_TRUE(aAdaptor.odfConvert( msBaseDir + rtl::OUString::createFromAscii("pdfi_unittest_test.pdf"),
493 new OutputWrap(aAbsURL),
494 NULL )) << "Exporting to ODF";
495 }
496
TEST_F(PDFITest,testOdfWriterExport)497 TEST_F(PDFITest, testOdfWriterExport)
498 {
499 pdfi::PDFIRawAdaptor aAdaptor( mxCtx );
500 aAdaptor.setTreeVisitorFactory( createWriterTreeVisitorFactory() );
501
502 ::rtl::OUString aURL, aAbsURL, aBaseURL;
503 osl_getFileURLFromSystemPath( (msBaseDir + rtl::OUString::createFromAscii("pdfi_unittest_writer.xml")).pData,
504 &aURL.pData );
505 osl_getProcessWorkingDir(&aBaseURL.pData);
506 osl_getAbsoluteFileURL(aBaseURL.pData,aURL.pData,&aAbsURL.pData);
507 ASSERT_TRUE(aAdaptor.odfConvert( msBaseDir + rtl::OUString::createFromAscii("pdfi_unittest_test.pdf"),
508 new OutputWrap(aAbsURL),
509 NULL )) << "Exporting to ODF";
510 }
511
512 }
513
main(int argc,char ** argv)514 int main(int argc, char **argv)
515 {
516 ::testing::InitGoogleTest(&argc, argv);
517 return RUN_ALL_TESTS();
518 }
519