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