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