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