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