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