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