LCOV - code coverage report
Current view: top level - sdext/source/pdfimport/wrapper - wrapper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 337 513 65.7 %
Date: 2012-08-25 Functions: 26 32 81.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 251 720 34.9 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include "contentsink.hxx"
      31                 :            : #include "pdfparse.hxx"
      32                 :            : #include "pdfihelper.hxx"
      33                 :            : 
      34                 :            : #include "osl/file.h"
      35                 :            : #include "osl/thread.h"
      36                 :            : #include "osl/process.h"
      37                 :            : #include "osl/diagnose.h"
      38                 :            : #include "rtl/ustring.hxx"
      39                 :            : #include "rtl/ustrbuf.hxx"
      40                 :            : #include "rtl/strbuf.hxx"
      41                 :            : #include "rtl/byteseq.hxx"
      42                 :            : 
      43                 :            : #include "cppuhelper/exc_hlp.hxx"
      44                 :            : #include "com/sun/star/io/XInputStream.hpp"
      45                 :            : #include "com/sun/star/uno/XComponentContext.hpp"
      46                 :            : #include "com/sun/star/awt/FontDescriptor.hpp"
      47                 :            : #include "com/sun/star/deployment/XPackageInformationProvider.hpp"
      48                 :            : #include "com/sun/star/beans/XMaterialHolder.hpp"
      49                 :            : #include "com/sun/star/rendering/PathCapType.hpp"
      50                 :            : #include "com/sun/star/rendering/PathJoinType.hpp"
      51                 :            : #include "com/sun/star/rendering/XColorSpace.hpp"
      52                 :            : #include "com/sun/star/rendering/XPolyPolygon2D.hpp"
      53                 :            : #include "com/sun/star/rendering/XBitmap.hpp"
      54                 :            : #include "com/sun/star/geometry/Matrix2D.hpp"
      55                 :            : #include "com/sun/star/geometry/AffineMatrix2D.hpp"
      56                 :            : #include "com/sun/star/geometry/RealRectangle2D.hpp"
      57                 :            : #include "com/sun/star/task/XInteractionHandler.hpp"
      58                 :            : 
      59                 :            : #include "basegfx/point/b2dpoint.hxx"
      60                 :            : #include "basegfx/polygon/b2dpolypolygon.hxx"
      61                 :            : #include "basegfx/polygon/b2dpolygon.hxx"
      62                 :            : #include "basegfx/tools/canvastools.hxx"
      63                 :            : #include "basegfx/tools/unopolypolygon.hxx"
      64                 :            : 
      65                 :            : #include <boost/scoped_ptr.hpp>
      66                 :            : #include <boost/unordered_map.hpp>
      67                 :            : #include <string.h>
      68                 :            : #ifdef WNT
      69                 :            : #include <stdlib.h>
      70                 :            : #include <ctype.h>
      71                 :            : #endif
      72                 :            : 
      73                 :            : #include "rtl/bootstrap.h"
      74                 :            : 
      75                 :            : #include <string.h> // memcmp
      76                 :            : 
      77                 :            : #ifndef PDFI_IMPL_IDENTIFIER
      78                 :            : # error define implementation name for pdfi extension, please!
      79                 :            : #endif
      80                 :            : 
      81                 :            : using namespace com::sun::star;
      82                 :            : 
      83                 :            : namespace pdfi
      84                 :            : {
      85                 :            : 
      86                 :            : namespace
      87                 :            : {
      88                 :            : 
      89                 :            : // identifier of the strings coming from the out-of-process xpdf
      90                 :            : // converter
      91                 :            : enum parseKey {
      92                 :            :     CLIPPATH,
      93                 :            :     DRAWCHAR,
      94                 :            :     DRAWIMAGE,
      95                 :            :     DRAWLINK,
      96                 :            :     DRAWMASK,
      97                 :            :     DRAWMASKEDIMAGE,
      98                 :            :     DRAWSOFTMASKEDIMAGE,
      99                 :            :     ENDPAGE,
     100                 :            :     ENDTEXTOBJECT,
     101                 :            :     EOCLIPPATH,
     102                 :            :     EOFILLPATH,
     103                 :            :     FILLPATH,
     104                 :            :     HYPERLINK,
     105                 :            :     INTERSECTCLIP,
     106                 :            :     INTERSECTEOCLIP,
     107                 :            :     POPSTATE,
     108                 :            :     PUSHSTATE,
     109                 :            :     RESTORESTATE,
     110                 :            :     SAVESTATE,
     111                 :            :     SETBLENDMODE,
     112                 :            :     SETFILLCOLOR,
     113                 :            :     SETFONT,
     114                 :            :     SETLINECAP,
     115                 :            :     SETLINEDASH,
     116                 :            :     SETLINEJOIN,
     117                 :            :     SETLINEWIDTH,
     118                 :            :     SETMITERLIMIT,
     119                 :            :     SETPAGENUM,
     120                 :            :     SETSTROKECOLOR,
     121                 :            :     SETTEXTRENDERMODE,
     122                 :            :     SETTRANSFORMATION,
     123                 :            :     STARTPAGE,
     124                 :            :     STROKEPATH,
     125                 :            :     UPDATEBLENDMODE,
     126                 :            :     UPDATECTM,
     127                 :            :     UPDATEFILLCOLOR,
     128                 :            :     UPDATEFILLOPACITY,
     129                 :            :     UPDATEFLATNESS,
     130                 :            :     UPDATEFONT,
     131                 :            :     UPDATELINECAP,
     132                 :            :     UPDATELINEDASH,
     133                 :            :     UPDATELINEJOIN,
     134                 :            :     UPDATELINEWIDTH,
     135                 :            :     UPDATEMITERLIMIT,
     136                 :            :     UPDATESTROKECOLOR,
     137                 :            :     UPDATESTROKEOPACITY,
     138                 :            :     NONE
     139                 :            : };
     140                 :            : 
     141                 :            : #include "hash.cxx"
     142                 :            : 
     143 [ +  - ][ +  - ]:          9 : class Parser
     144                 :            : {
     145                 :            :     typedef boost::unordered_map< sal_Int64,
     146                 :            :                            FontAttributes > FontMapType;
     147                 :            : 
     148                 :            :     const uno::Reference<uno::XComponentContext> m_xContext;
     149                 :            :     const ContentSinkSharedPtr                   m_pSink;
     150                 :            :     const oslFileHandle                          m_pErr;
     151                 :            :     ::rtl::OString                               m_aLine;
     152                 :            :     FontMapType                                  m_aFontMap;
     153                 :            :     sal_Int32                                    m_nNextToken;
     154                 :            :     sal_Int32                                    m_nCharIndex;
     155                 :            : 
     156                 :            :     const double                                 minAreaThreshold;
     157                 :            :     const double                                 minLineWidth;
     158                 :            : 
     159                 :            :     ::rtl::OString readNextToken();
     160                 :            :     void           readInt32( sal_Int32& o_Value );
     161                 :            :     sal_Int32      readInt32();
     162                 :            :     void           readInt64( sal_Int64& o_Value );
     163                 :            :     void           readDouble( double& o_Value );
     164                 :            :     double         readDouble();
     165                 :            :     void           readBinaryData( uno::Sequence<sal_Int8>& rBuf );
     166                 :            : 
     167                 :            :     uno::Reference<rendering::XPolyPolygon2D> readPath( double* );
     168                 :            : 
     169                 :            :     void                 readChar();
     170                 :            :     void                 readLineCap();
     171                 :            :     void                 readLineDash();
     172                 :            :     void                 readLineJoin();
     173                 :            :     void                 readTransformation();
     174                 :            :     rendering::ARGBColor readColor();
     175                 :            :     void                 parseFontFamilyName( FontAttributes& aResult );
     176                 :            :     void                 readFont();
     177                 :            :     uno::Sequence<beans::PropertyValue> readImageImpl();
     178                 :            : 
     179                 :            :     void                 readImage();
     180                 :            :     void                 readMask();
     181                 :            :     void                 readLink();
     182                 :            :     void                 readMaskedImage();
     183                 :            :     void                 readSoftMaskedImage();
     184                 :            :     int          parseFontCheckForString( const sal_Unicode* pCopy, const char* str, sal_Int32& nLen,
     185                 :            :                     FontAttributes& aResult, bool bItalic, bool bBold);
     186                 :            :     int          parseFontRemoveSuffix( const sal_Unicode* pCopy, const char* s, sal_Int32& nLen);
     187                 :            : 
     188                 :            : 
     189                 :            : public:
     190                 :          9 :     Parser( const ContentSinkSharedPtr&                   rSink,
     191                 :            :             oslFileHandle                                 pErr,
     192                 :            :             const uno::Reference<uno::XComponentContext>& xContext ) :
     193                 :            :         m_xContext(xContext),
     194                 :            :         m_pSink(rSink),
     195                 :            :         m_pErr(pErr),
     196                 :            :         m_aLine(),
     197                 :            :         m_aFontMap(101),
     198                 :            :         m_nNextToken(-1),
     199                 :            :         m_nCharIndex(-1),
     200                 :            :         minAreaThreshold( 300.0 ),
     201 [ +  - ][ +  - ]:          9 :         minLineWidth( 12 )
     202                 :          9 :     {}
     203                 :            : 
     204                 :            :     void parseLine( const ::rtl::OString& rLine );
     205                 :            : };
     206                 :            : 
     207                 :            : 
     208                 :            : namespace
     209                 :            : {
     210                 :            : 
     211                 :            :     /** Unescapes line-ending characters in input string. These
     212                 :            :         characters are encoded as pairs of characters: '\\' 'n', resp.
     213                 :            :         '\\' 'r'. This function converts them back to '\n', resp. '\r'.
     214                 :            :       */
     215                 :       1044 :     rtl::OString lcl_unescapeLineFeeds(const rtl::OString& i_rStr)
     216                 :            :     {
     217                 :       1044 :         const size_t nOrigLen(sal::static_int_cast<size_t>(i_rStr.getLength()));
     218                 :       1044 :         const sal_Char* const pOrig(i_rStr.getStr());
     219         [ +  - ]:       1044 :         sal_Char* const pBuffer(new sal_Char[nOrigLen + 1]);
     220                 :            : 
     221                 :       1044 :         const sal_Char* pRead(pOrig);
     222                 :       1044 :         sal_Char* pWrite(pBuffer);
     223                 :       1044 :         const sal_Char* pCur(pOrig);
     224         [ -  + ]:       1044 :         while ((pCur = strchr(pCur, '\\')) != 0)
     225                 :            :         {
     226                 :          0 :             const sal_Char cNext(pCur[1]);
     227 [ #  # ][ #  # ]:          0 :             if (cNext == 'n' || cNext == 'r' || cNext == '\\')
                 [ #  # ]
     228                 :            :             {
     229                 :          0 :                 const size_t nLen(pCur - pRead);
     230                 :          0 :                 strncpy(pWrite, pRead, nLen);
     231                 :          0 :                 pWrite += nLen;
     232 [ #  # ][ #  # ]:          0 :                 *pWrite = cNext == 'n' ? '\n' : (cNext == 'r' ? '\r' : '\\');
     233                 :          0 :                 ++pWrite;
     234                 :          0 :                 pCur = pRead = pCur + 2;
     235                 :            :             }
     236                 :            :             else
     237                 :            :             {
     238                 :            :                 // Just continue on the next character. The current
     239                 :            :                 // block will be copied the next time it goes through the
     240                 :            :                 // 'if' branch.
     241                 :          0 :                 ++pCur;
     242                 :            :             }
     243                 :            :         }
     244                 :            :         // maybe there are some data to copy yet
     245         [ +  - ]:       1044 :         if (sal::static_int_cast<size_t>(pRead - pOrig) < nOrigLen)
     246                 :            :         {
     247                 :       1044 :             const size_t nLen(nOrigLen - (pRead - pOrig));
     248                 :       1044 :             strncpy(pWrite, pRead, nLen);
     249                 :       1044 :             pWrite += nLen;
     250                 :            :         }
     251                 :       1044 :         *pWrite = '\0';
     252                 :            : 
     253                 :       1044 :         rtl::OString aResult(pBuffer);
     254         [ +  - ]:       1044 :         delete[] pBuffer;
     255                 :       1044 :         return aResult;
     256                 :            :     }
     257                 :            : 
     258                 :            : }
     259                 :            : 
     260                 :            : 
     261                 :      11790 : ::rtl::OString Parser::readNextToken()
     262                 :            : {
     263                 :            :     OSL_PRECOND(m_nCharIndex!=-1,"insufficient input");
     264                 :      11790 :     return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex);
     265                 :            : }
     266                 :            : 
     267                 :        783 : void Parser::readInt32( sal_Int32& o_Value )
     268                 :            : {
     269                 :        783 :     o_Value = readNextToken().toInt32();
     270                 :        783 : }
     271                 :            : 
     272                 :         72 : sal_Int32 Parser::readInt32()
     273                 :            : {
     274                 :         72 :     return readNextToken().toInt32();
     275                 :            : }
     276                 :            : 
     277                 :         99 : void Parser::readInt64( sal_Int64& o_Value )
     278                 :            : {
     279                 :         99 :     o_Value = readNextToken().toInt64();
     280                 :         99 : }
     281                 :            : 
     282                 :       8865 : void Parser::readDouble( double& o_Value )
     283                 :            : {
     284                 :       8865 :     o_Value = readNextToken().toDouble();
     285                 :       8865 : }
     286                 :            : 
     287                 :        117 : double Parser::readDouble()
     288                 :            : {
     289                 :        117 :     return readNextToken().toDouble();
     290                 :            : }
     291                 :            : 
     292                 :         27 : void Parser::readBinaryData( uno::Sequence<sal_Int8>& rBuf )
     293                 :            : {
     294                 :         27 :     sal_Int32 nFileLen( rBuf.getLength() );
     295         [ +  - ]:         27 :     sal_Int8*           pBuf( rBuf.getArray() );
     296                 :         27 :     sal_uInt64          nBytesRead(0);
     297                 :         27 :     oslFileError        nRes=osl_File_E_None;
     298 [ +  + ][ +  - ]:         54 :     while( nFileLen &&
         [ +  - ][ +  + ]
     299                 :         27 :            osl_File_E_None == (nRes=osl_readFile( m_pErr, pBuf, nFileLen, &nBytesRead )) )
     300                 :            :     {
     301                 :         27 :         pBuf += nBytesRead;
     302                 :         27 :         nFileLen -= sal::static_int_cast<sal_Int32>(nBytesRead);
     303                 :            :     }
     304                 :            : 
     305                 :            :     OSL_PRECOND(nRes==osl_File_E_None, "inconsistent data");
     306                 :         27 : }
     307                 :            : 
     308                 :         45 : uno::Reference<rendering::XPolyPolygon2D> Parser::readPath( double* pArea = NULL )
     309                 :            : {
     310                 :         45 :     const rtl::OString aSubPathMarker( "subpath" );
     311                 :            : 
     312                 :         45 :     if( 0 != readNextToken().compareTo( aSubPathMarker ) )
     313                 :            :         OSL_PRECOND(false, "broken path");
     314                 :            : 
     315         [ +  - ]:         45 :     basegfx::B2DPolyPolygon aResult;
     316         [ +  + ]:         90 :     while( m_nCharIndex != -1 )
     317                 :            :     {
     318         [ +  - ]:         45 :         basegfx::B2DPolygon aSubPath;
     319                 :            : 
     320                 :            :         sal_Int32 nClosedFlag;
     321                 :         45 :         readInt32( nClosedFlag );
     322         [ +  - ]:         45 :         aSubPath.setClosed( nClosedFlag != 0 );
     323                 :            : 
     324                 :         45 :         sal_Int32 nContiguousControlPoints(0);
     325                 :         45 :         sal_Int32 nDummy=m_nCharIndex;
     326                 :         45 :         rtl::OString aCurrToken( m_aLine.getToken(m_nNextToken,' ',nDummy) );
     327                 :            : 
     328 [ +  + ][ +  - ]:        288 :         while( m_nCharIndex != -1 && 0 != aCurrToken.compareTo(aSubPathMarker) )
                 [ +  + ]
     329                 :            :         {
     330                 :            :             sal_Int32 nCurveFlag;
     331                 :            :             double    nX, nY;
     332                 :        243 :             readDouble( nX );
     333                 :        243 :             readDouble( nY );
     334                 :        243 :             readInt32(  nCurveFlag );
     335                 :            : 
     336         [ +  - ]:        243 :             aSubPath.append(basegfx::B2DPoint(nX,nY));
     337         [ +  + ]:        243 :             if( nCurveFlag )
     338                 :            :             {
     339                 :         72 :                 ++nContiguousControlPoints;
     340                 :            :             }
     341         [ +  + ]:        171 :             else if( nContiguousControlPoints )
     342                 :            :             {
     343                 :            :                 OSL_PRECOND(nContiguousControlPoints==2,"broken bezier path");
     344                 :            : 
     345                 :            :                 // have two control points before us. the current one
     346                 :            :                 // is a normal point - thus, convert previous points
     347                 :            :                 // into bezier segment
     348         [ +  - ]:         36 :                 const sal_uInt32 nPoints( aSubPath.count() );
     349         [ +  - ]:         36 :                 const basegfx::B2DPoint aCtrlA( aSubPath.getB2DPoint(nPoints-3) );
     350         [ +  - ]:         36 :                 const basegfx::B2DPoint aCtrlB( aSubPath.getB2DPoint(nPoints-2) );
     351         [ +  - ]:         36 :                 const basegfx::B2DPoint aEnd( aSubPath.getB2DPoint(nPoints-1) );
     352         [ +  - ]:         36 :                 aSubPath.remove(nPoints-3, 3);
     353         [ +  - ]:         36 :                 aSubPath.appendBezierSegment(aCtrlA, aCtrlB, aEnd);
     354                 :            : 
     355                 :         36 :                 nContiguousControlPoints=0;
     356                 :            :             }
     357                 :            : 
     358                 :            :             // one token look-ahead (new subpath or more points?
     359                 :        243 :             nDummy=m_nCharIndex;
     360                 :        243 :             aCurrToken = m_aLine.getToken(m_nNextToken,' ',nDummy);
     361                 :            :         }
     362                 :            : 
     363         [ +  - ]:         45 :         aResult.append( aSubPath );
     364         [ -  + ]:         45 :         if( m_nCharIndex != -1 )
     365                 :          0 :             readNextToken();
     366         [ +  - ]:         45 :     }
     367                 :            : 
     368         [ +  + ]:         45 :     if( pArea )
     369                 :            :     {
     370         [ +  - ]:          9 :         basegfx::B2DRange aRange( aResult.getB2DRange() );
     371 [ +  - ][ +  - ]:          9 :         if( aRange.getWidth() <= minLineWidth || aRange.getHeight() <= minLineWidth)
         [ +  - ][ -  + ]
                 [ -  + ]
     372                 :          0 :             *pArea = 0.0;
     373                 :            :         else
     374 [ +  - ][ +  - ]:          9 :             *pArea = aRange.getWidth() * aRange.getHeight();
     375                 :            :     }
     376                 :            : 
     377                 :            :     return static_cast<rendering::XLinePolyPolygon2D*>(
     378 [ +  - ][ +  - ]:         45 :         new basegfx::unotools::UnoPolyPolygon(aResult));
         [ +  - ][ +  - ]
     379                 :            : }
     380                 :            : 
     381                 :        936 : void Parser::readChar()
     382                 :            : {
     383                 :        936 :     geometry::Matrix2D aUnoMatrix;
     384                 :        936 :     geometry::RealRectangle2D aRect;
     385                 :            : 
     386                 :        936 :     readDouble(aRect.X1);
     387                 :        936 :     readDouble(aRect.Y1);
     388                 :        936 :     readDouble(aRect.X2);
     389                 :        936 :     readDouble(aRect.Y2);
     390                 :        936 :     readDouble(aUnoMatrix.m00);
     391                 :        936 :     readDouble(aUnoMatrix.m01);
     392                 :        936 :     readDouble(aUnoMatrix.m10);
     393                 :        936 :     readDouble(aUnoMatrix.m11);
     394                 :            : 
     395         [ +  - ]:        936 :     rtl::OString aChars = lcl_unescapeLineFeeds( m_aLine.copy( m_nCharIndex ) );
     396                 :            : 
     397                 :            :     // chars gobble up rest of line
     398                 :        936 :     m_nCharIndex = -1;
     399                 :            : 
     400                 :        936 :     m_pSink->drawGlyphs( rtl::OStringToOUString( aChars,
     401                 :            :                                                  RTL_TEXTENCODING_UTF8 ),
     402 [ +  - ][ +  - ]:        936 :                          aRect, aUnoMatrix );
     403                 :        936 : }
     404                 :            : 
     405                 :         27 : void Parser::readLineCap()
     406                 :            : {
     407                 :         27 :     sal_Int8 nCap(rendering::PathCapType::BUTT);
     408      [ +  -  - ]:         27 :     switch( readInt32() )
     409                 :            :     {
     410                 :            :         default:
     411                 :            :             // FALLTHROUGH intended
     412                 :         27 :         case 0: nCap = rendering::PathCapType::BUTT; break;
     413                 :          0 :         case 1: nCap = rendering::PathCapType::ROUND; break;
     414                 :          0 :         case 2: nCap = rendering::PathCapType::SQUARE; break;
     415                 :            :     }
     416                 :         27 :     m_pSink->setLineCap(nCap);
     417                 :         27 : }
     418                 :            : 
     419                 :         18 : void Parser::readLineDash()
     420                 :            : {
     421         [ +  + ]:         18 :     if( m_nCharIndex == -1 )
     422                 :            :     {
     423 [ +  - ][ +  - ]:          9 :         m_pSink->setLineDash( uno::Sequence<double>(), 0.0 );
                 [ +  - ]
     424                 :         18 :         return;
     425                 :            :     }
     426                 :            : 
     427                 :          9 :     const double nOffset(readDouble());
     428                 :          9 :     const sal_Int32 nLen(readInt32());
     429                 :            : 
     430         [ +  - ]:          9 :     uno::Sequence<double> aDashArray(nLen);
     431         [ +  - ]:          9 :     double* pArray=aDashArray.getArray();
     432         [ +  + ]:         45 :     for( sal_Int32 i=0; i<nLen; ++i )
     433                 :         36 :         *pArray++ = readDouble();
     434                 :            : 
     435 [ +  - ][ +  - ]:          9 :     m_pSink->setLineDash( aDashArray, nOffset );
     436                 :            : }
     437                 :            : 
     438                 :         27 : void Parser::readLineJoin()
     439                 :            : {
     440                 :         27 :     sal_Int8 nJoin(rendering::PathJoinType::MITER);
     441      [ +  +  - ]:         27 :     switch( readInt32() )
     442                 :            :     {
     443                 :            :         default:
     444                 :            :             // FALLTHROUGH intended
     445                 :          9 :         case 0: nJoin = rendering::PathJoinType::MITER; break;
     446                 :         18 :         case 1: nJoin = rendering::PathJoinType::ROUND; break;
     447                 :          0 :         case 2: nJoin = rendering::PathJoinType::BEVEL; break;
     448                 :            :     }
     449                 :         27 :     m_pSink->setLineJoin(nJoin);
     450                 :         27 : }
     451                 :            : 
     452                 :         18 : void Parser::readTransformation()
     453                 :            : {
     454                 :         18 :     geometry::AffineMatrix2D aMat;
     455                 :         18 :     readDouble(aMat.m00);
     456                 :         18 :     readDouble(aMat.m10);
     457                 :         18 :     readDouble(aMat.m01);
     458                 :         18 :     readDouble(aMat.m11);
     459                 :         18 :     readDouble(aMat.m02);
     460                 :         18 :     readDouble(aMat.m12);
     461         [ +  - ]:         18 :     m_pSink->setTransformation( aMat );
     462                 :         18 : }
     463                 :            : 
     464                 :        162 : rendering::ARGBColor Parser::readColor()
     465                 :            : {
     466                 :        162 :     rendering::ARGBColor aRes;
     467                 :        162 :     readDouble(aRes.Red);
     468                 :        162 :     readDouble(aRes.Green);
     469                 :        162 :     readDouble(aRes.Blue);
     470                 :        162 :     readDouble(aRes.Alpha);
     471                 :        162 :     return aRes;
     472                 :            : }
     473                 :            : 
     474                 :       1800 : int Parser::parseFontCheckForString( const sal_Unicode* pCopy, const char* s, sal_Int32& nLen,
     475                 :            :         FontAttributes& aResult, bool bItalic, bool bBold)
     476                 :            : {
     477                 :       1800 :     int l = strlen(s);
     478         [ +  + ]:       1800 :     if (nLen < l)
     479                 :       1125 :         return 0;
     480         [ +  - ]:        684 :     for (int i = 0; i < l; i++)
     481 [ +  - ][ +  + ]:        684 :         if (tolower(pCopy[i]) != s[i]
     482                 :        684 :             && toupper(pCopy[i]) != s[i])
     483                 :        675 :             return 0;
     484                 :          0 :     aResult.isItalic = bItalic;
     485                 :          0 :     aResult.isBold = bBold;
     486                 :          0 :         nLen -= l;
     487                 :          0 :         pCopy += l;
     488                 :       1800 :     return l;
     489                 :            : }
     490                 :            : 
     491                 :        450 : int Parser::parseFontRemoveSuffix( const sal_Unicode* pCopy, const char* s, sal_Int32& nLen)
     492                 :            : {
     493                 :        450 :     int l = strlen(s);
     494         [ +  + ]:        450 :     if (nLen < l)
     495                 :        108 :         return 0;
     496         [ +  - ]:        342 :     for (int i = 0; i < l; i++)
     497         [ +  - ]:        342 :         if ( pCopy[nLen - l + i] != s[i] )
     498                 :        342 :             return 0;
     499                 :          0 :         nLen -= l;
     500                 :        450 :     return l;
     501                 :            : }
     502                 :            : 
     503                 :         27 : void Parser::parseFontFamilyName( FontAttributes& aResult )
     504                 :            : {
     505                 :         27 :     rtl::OUStringBuffer aNewFamilyName( aResult.familyName.getLength() );
     506                 :            : 
     507                 :         27 :     const sal_Unicode* pCopy = aResult.familyName.getStr();
     508                 :         27 :     sal_Int32 nLen = aResult.familyName.getLength();
     509                 :            :     // parse out truetype subsets (e.g. BAAAAA+Thorndale)
     510 [ +  - ][ +  - ]:         27 :     if( nLen > 8 && pCopy[6] == sal_Unicode('+') )
     511                 :            :     {
     512                 :         27 :         pCopy += 7;
     513                 :         27 :         nLen -= 7;
     514                 :            :     }
     515                 :            : 
     516         [ +  + ]:        252 :     while( nLen )
     517                 :            :     {
     518         [ +  - ]:        225 :     if (parseFontRemoveSuffix( pCopy, "PSMT", nLen)) {}
     519                 :        225 :     else if (parseFontRemoveSuffix( pCopy, "MT", nLen)) {}
     520                 :            : 
     521         [ +  - ]:        225 :     if (parseFontCheckForString( pCopy, "Italic", nLen, aResult, true, false)) {}
     522         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "-Bold", nLen, aResult, false, true)) {}
     523         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "Bold", nLen, aResult, false, true)) {}
     524         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "-Roman", nLen, aResult, false, false)) {}
     525         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "-LightOblique", nLen, aResult, true, false)) {}
     526         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "-BoldOblique", nLen, aResult, true, true)) {}
     527         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "-Light", nLen, aResult, false, false)) {}
     528         [ +  - ]:        225 :     else if (parseFontCheckForString( pCopy, "-Reg", nLen, aResult, false, false)) {}
     529                 :            :         else
     530                 :            :         {
     531         [ +  - ]:        225 :             if( *pCopy != '-' )
     532         [ +  - ]:        225 :                 aNewFamilyName.append( *pCopy );
     533                 :        225 :             pCopy++;
     534                 :        225 :             nLen--;
     535                 :            :         }
     536                 :            :     }
     537         [ +  - ]:         27 :     aResult.familyName = aNewFamilyName.makeStringAndClear();
     538                 :         27 : }
     539                 :            : 
     540                 :         99 : void Parser::readFont()
     541                 :            : {
     542                 :         99 :     ::rtl::OString aFontName;
     543                 :            :     sal_Int64      nFontID;
     544                 :            :     sal_Int32      nIsEmbedded, nIsBold, nIsItalic, nIsUnderline, nFileLen;
     545                 :            :     double         nSize;
     546                 :            : 
     547                 :         99 :     readInt64(nFontID);
     548                 :         99 :     readInt32(nIsEmbedded);
     549                 :         99 :     readInt32(nIsBold);
     550                 :         99 :     readInt32(nIsItalic);
     551                 :         99 :     readInt32(nIsUnderline);
     552                 :         99 :     readDouble(nSize);
     553                 :         99 :     readInt32(nFileLen);
     554                 :            : 
     555         [ -  + ]:         99 :     nSize = nSize < 0.0 ? -nSize : nSize;
     556         [ +  - ]:         99 :     aFontName = lcl_unescapeLineFeeds( m_aLine.copy( m_nCharIndex ) );
     557                 :            : 
     558                 :            :     // name gobbles up rest of line
     559                 :         99 :     m_nCharIndex = -1;
     560                 :            : 
     561         [ +  - ]:         99 :     FontMapType::const_iterator pFont( m_aFontMap.find(nFontID) );
     562 [ +  + ][ +  - ]:         99 :     if( pFont != m_aFontMap.end() )
     563                 :            :     {
     564                 :            :         OSL_PRECOND(nFileLen==0,"font data for known font");
     565         [ +  - ]:         72 :         FontAttributes aRes(pFont->second);
     566                 :         72 :         aRes.size = nSize;
     567         [ +  - ]:         72 :         m_pSink->setFont( aRes );
     568                 :            : 
     569                 :        171 :         return;
     570                 :            :     }
     571                 :            : 
     572                 :            :     // yet unknown font - get info and add to map
     573                 :            :     FontAttributes aResult( rtl::OStringToOUString( aFontName,
     574                 :            :                                                     RTL_TEXTENCODING_UTF8 ),
     575                 :            :                             nIsBold != 0,
     576                 :            :                             nIsItalic != 0,
     577                 :            :                             nIsUnderline != 0,
     578                 :            :                             false,
     579         [ +  - ]:         27 :                             nSize );
     580                 :            : 
     581                 :            :     // extract textual attributes (bold, italic in the name, etc.)
     582         [ +  - ]:         27 :     parseFontFamilyName(aResult);
     583                 :            :     // need to read font file?
     584         [ +  - ]:         27 :     if( nFileLen )
     585                 :            :     {
     586         [ +  - ]:         27 :         uno::Sequence<sal_Int8> aFontFile(nFileLen);
     587         [ +  - ]:         27 :         readBinaryData( aFontFile );
     588                 :            : 
     589                 :         27 :         awt::FontDescriptor aFD;
     590         [ +  - ]:         27 :         uno::Sequence< uno::Any > aArgs(1);
     591 [ +  - ][ +  - ]:         27 :         aArgs[0] <<= aFontFile;
     592                 :            : 
     593                 :            :         try
     594                 :            :         {
     595                 :            :             uno::Reference< beans::XMaterialHolder > xMat(
     596 [ +  - ][ +  - ]:         54 :                 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
                 [ +  - ]
     597                 :            :                     rtl::OUString( "com.sun.star.awt.FontIdentificator"  ),
     598                 :            :                     aArgs,
     599                 :         27 :                     m_xContext ),
     600 [ +  - ][ +  - ]:         27 :                 uno::UNO_QUERY );
     601         [ -  + ]:         27 :             if( xMat.is() )
     602                 :            :             {
     603 [ #  # ][ #  # ]:          0 :                 uno::Any aRes( xMat->getMaterial() );
     604 [ #  # ][ #  # ]:          0 :                 if( aRes >>= aFD )
     605                 :            :                 {
     606                 :          0 :                     aResult.familyName  = aFD.Name;
     607         [ #  # ]:          0 :                 parseFontFamilyName(aResult);
     608                 :          0 :                     aResult.isBold      = (aFD.Weight > 100.0);
     609                 :            :                     aResult.isItalic    = (aFD.Slant == awt::FontSlant_OBLIQUE ||
     610 [ #  # ][ #  # ]:          0 :                                            aFD.Slant == awt::FontSlant_ITALIC );
     611                 :          0 :                     aResult.isUnderline = false;
     612                 :          0 :                     aResult.size        = 0;
     613                 :          0 :                 }
     614         [ #  # ]:         27 :             }
     615                 :            :         }
     616         [ #  # ]:          0 :         catch( uno::Exception& )
     617                 :            :         {
     618                 :            :         }
     619                 :            : 
     620         [ -  + ]:         27 :         if( aResult.familyName.isEmpty() )
     621                 :            :         {
     622                 :            :             // last fallback
     623                 :          0 :             aResult.familyName  = ::rtl::OUString( "Arial"  );
     624                 :          0 :             aResult.isUnderline = false;
     625 [ +  - ][ +  - ]:         27 :         }
     626                 :            : 
     627                 :            :     }
     628         [ +  - ]:         27 :     m_aFontMap[nFontID] = aResult;
     629                 :            : 
     630                 :         27 :     aResult.size = nSize;
     631 [ +  + ][ +  - ]:         99 :     m_pSink->setFont(aResult);
     632                 :            : }
     633                 :            : 
     634                 :          0 : uno::Sequence<beans::PropertyValue> Parser::readImageImpl()
     635                 :            : {
     636 [ #  # ][ #  # ]:          0 :     static const rtl::OString aJpegMarker( "JPEG" );
     637 [ #  # ][ #  # ]:          0 :     static const rtl::OString aPbmMarker( "PBM" );
     638 [ #  # ][ #  # ]:          0 :     static const rtl::OString aPpmMarker( "PPM" );
     639 [ #  # ][ #  # ]:          0 :     static const rtl::OString aPngMarker( "PNG" );
     640 [ #  # ][ #  # ]:          0 :     static const rtl::OUString aJpegFile( "DUMMY.JPEG" );
     641 [ #  # ][ #  # ]:          0 :     static const rtl::OUString aPbmFile( "DUMMY.PBM" );
     642 [ #  # ][ #  # ]:          0 :     static const rtl::OUString aPpmFile( "DUMMY.PPM" );
     643 [ #  # ][ #  # ]:          0 :     static const rtl::OUString aPngFile( "DUMMY.PNG" );
     644                 :            : 
     645                 :          0 :     rtl::OString aToken = readNextToken();
     646                 :          0 :     const sal_Int32 nImageSize( readInt32() );
     647                 :            : 
     648                 :          0 :     rtl::OUString           aFileName;
     649         [ #  # ]:          0 :     if( aToken.compareTo( aPngMarker ) == 0 )
     650                 :          0 :         aFileName = aPngFile;
     651         [ #  # ]:          0 :     else if( aToken.compareTo( aJpegMarker ) == 0 )
     652                 :          0 :         aFileName = aJpegFile;
     653         [ #  # ]:          0 :     else if( aToken.compareTo( aPbmMarker ) == 0 )
     654                 :          0 :         aFileName = aPbmFile;
     655                 :            :     else
     656                 :            :     {
     657                 :            :         OSL_PRECOND( aToken.compareTo( aPpmMarker ) == 0,
     658                 :            :                      "Invalid bitmap format" );
     659                 :          0 :         aFileName = aPpmFile;
     660                 :            :     }
     661                 :            : 
     662         [ #  # ]:          0 :     uno::Sequence<sal_Int8> aDataSequence(nImageSize);
     663         [ #  # ]:          0 :     readBinaryData( aDataSequence );
     664                 :            : 
     665         [ #  # ]:          0 :     uno::Sequence< uno::Any > aStreamCreationArgs(1);
     666 [ #  # ][ #  # ]:          0 :     aStreamCreationArgs[0] <<= aDataSequence;
     667                 :            : 
     668         [ #  # ]:          0 :     uno::Reference< uno::XComponentContext > xContext( m_xContext, uno::UNO_SET_THROW );
     669 [ #  # ][ #  # ]:          0 :     uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
                 [ #  # ]
     670         [ #  # ]:          0 :     uno::Reference< io::XInputStream > xDataStream( xFactory->createInstanceWithArgumentsAndContext(
     671                 :            :         ::rtl::OUString( "com.sun.star.io.SequenceInputStream"  ),
     672 [ #  # ][ #  # ]:          0 :         aStreamCreationArgs, m_xContext ), uno::UNO_QUERY_THROW );
     673                 :            : 
     674         [ #  # ]:          0 :     uno::Sequence<beans::PropertyValue> aSequence(3);
     675         [ #  # ]:          0 :     aSequence[0] = beans::PropertyValue( ::rtl::OUString("URL"),
     676                 :            :                                          0,
     677                 :            :                                          uno::makeAny(aFileName),
     678         [ #  # ]:          0 :                                          beans::PropertyState_DIRECT_VALUE );
     679         [ #  # ]:          0 :     aSequence[1] = beans::PropertyValue( ::rtl::OUString("InputStream"),
     680                 :            :                                          0,
     681                 :            :                                          uno::makeAny( xDataStream ),
     682         [ #  # ]:          0 :                                          beans::PropertyState_DIRECT_VALUE );
     683         [ #  # ]:          0 :     aSequence[2] = beans::PropertyValue( ::rtl::OUString("InputSequence"),
     684                 :            :                                          0,
     685                 :            :                                          uno::makeAny(aDataSequence),
     686         [ #  # ]:          0 :                                          beans::PropertyState_DIRECT_VALUE );
     687                 :            : 
     688 [ #  # ][ #  # ]:          0 :     return aSequence;
     689                 :            : }
     690                 :            : 
     691                 :          0 : void Parser::readImage()
     692                 :            : {
     693                 :            :     sal_Int32 nWidth, nHeight,nMaskColors;
     694                 :          0 :     readInt32(nWidth);
     695                 :          0 :     readInt32(nHeight);
     696                 :          0 :     readInt32(nMaskColors);
     697                 :            : 
     698         [ #  # ]:          0 :     uno::Sequence<beans::PropertyValue> aImg( readImageImpl() );
     699                 :            : 
     700         [ #  # ]:          0 :     if( nMaskColors )
     701                 :            :     {
     702         [ #  # ]:          0 :         uno::Sequence<sal_Int8> aDataSequence(nMaskColors);
     703         [ #  # ]:          0 :         readBinaryData( aDataSequence );
     704                 :            : 
     705         [ #  # ]:          0 :         uno::Sequence<uno::Any> aMaskRanges(2);
     706                 :            : 
     707         [ #  # ]:          0 :         uno::Sequence<double> aMinRange(nMaskColors/2);
     708         [ #  # ]:          0 :         uno::Sequence<double> aMaxRange(nMaskColors/2);
     709         [ #  # ]:          0 :         for( sal_Int32 i=0; i<nMaskColors/2; ++i )
     710                 :            :         {
     711 [ #  # ][ #  # ]:          0 :             aMinRange[i] = aDataSequence[i] / 255.0;
     712 [ #  # ][ #  # ]:          0 :             aMaxRange[i] = aDataSequence[i+nMaskColors/2] / 255.0;
     713                 :            :         }
     714                 :            : 
     715 [ #  # ][ #  # ]:          0 :         aMaskRanges[0] = uno::makeAny(aMinRange);
     716 [ #  # ][ #  # ]:          0 :         aMaskRanges[1] = uno::makeAny(aMaxRange);
     717                 :            : 
     718 [ #  # ][ #  # ]:          0 :         m_pSink->drawColorMaskedImage( aImg, aMaskRanges );
         [ #  # ][ #  # ]
                 [ #  # ]
     719                 :            :     }
     720                 :            :     else
     721 [ #  # ][ #  # ]:          0 :         m_pSink->drawImage( aImg );
     722                 :          0 : }
     723                 :            : 
     724                 :          0 : void Parser::readMask()
     725                 :            : {
     726                 :            :     sal_Int32 nWidth, nHeight, nInvert;
     727                 :          0 :     readInt32(nWidth);
     728                 :          0 :     readInt32(nHeight);
     729                 :          0 :     readInt32(nInvert);
     730                 :            : 
     731 [ #  # ][ #  # ]:          0 :     m_pSink->drawMask( readImageImpl(), nInvert );
                 [ #  # ]
     732                 :          0 : }
     733                 :            : 
     734                 :          9 : void Parser::readLink()
     735                 :            : {
     736                 :          9 :     geometry::RealRectangle2D aBounds;
     737                 :          9 :     readDouble(aBounds.X1);
     738                 :          9 :     readDouble(aBounds.Y1);
     739                 :          9 :     readDouble(aBounds.X2);
     740                 :          9 :     readDouble(aBounds.Y2);
     741                 :            : 
     742                 :          9 :     m_pSink->hyperLink( aBounds,
     743                 :            :                         rtl::OStringToOUString( lcl_unescapeLineFeeds(
     744                 :            :                                 m_aLine.copy(m_nCharIndex) ),
     745 [ +  - ][ +  - ]:          9 :                                 RTL_TEXTENCODING_UTF8 ) );
                 [ +  - ]
     746                 :            :     // name gobbles up rest of line
     747                 :          9 :     m_nCharIndex = -1;
     748                 :          9 : }
     749                 :            : 
     750                 :          0 : void Parser::readMaskedImage()
     751                 :            : {
     752                 :            :     sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight, nMaskInvert;
     753                 :          0 :     readInt32(nWidth);
     754                 :          0 :     readInt32(nHeight);
     755                 :          0 :     readInt32(nMaskWidth);
     756                 :          0 :     readInt32(nMaskHeight);
     757                 :          0 :     readInt32(nMaskInvert);
     758                 :            : 
     759         [ #  # ]:          0 :     const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
     760         [ #  # ]:          0 :     const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
     761 [ #  # ][ #  # ]:          0 :     m_pSink->drawMaskedImage( aImage, aMask, nMaskInvert != 0 );
                 [ #  # ]
     762                 :          0 : }
     763                 :            : 
     764                 :          0 : void Parser::readSoftMaskedImage()
     765                 :            : {
     766                 :            :     sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight;
     767                 :          0 :     readInt32(nWidth);
     768                 :          0 :     readInt32(nHeight);
     769                 :          0 :     readInt32(nMaskWidth);
     770                 :          0 :     readInt32(nMaskHeight);
     771                 :            : 
     772         [ #  # ]:          0 :     const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
     773         [ #  # ]:          0 :     const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
     774 [ #  # ][ #  # ]:          0 :     m_pSink->drawAlphaMaskedImage( aImage, aMask );
                 [ #  # ]
     775                 :          0 : }
     776                 :            : 
     777                 :       1809 : void Parser::parseLine( const ::rtl::OString& rLine )
     778                 :            : {
     779                 :            :     OSL_PRECOND( m_pSink,         "Invalid sink" );
     780                 :            :     OSL_PRECOND( m_pErr,          "Invalid filehandle" );
     781                 :            :     OSL_PRECOND( m_xContext.is(), "Invalid service factory" );
     782                 :            : 
     783                 :       1809 :     m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine;
     784                 :       1809 :     uno::Reference<rendering::XPolyPolygon2D> xPoly;
     785                 :       1809 :     const ::rtl::OString& rCmd = readNextToken();
     786                 :            :     const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.getStr(),
     787                 :       1809 :                                                             rCmd.getLength() );
     788                 :            :     OSL_ASSERT(pEntry);
     789   [ +  +  -  +  :       1809 :     switch( pEntry->eKey )
          -  -  -  +  +  
          +  +  -  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  -  -  
                      - ]
     790                 :            :     {
     791                 :            :         case CLIPPATH:
     792 [ +  - ][ +  - ]:          9 :             m_pSink->intersectClip(readPath()); break;
     793                 :            :         case DRAWCHAR:
     794         [ +  - ]:        936 :             readChar(); break;
     795                 :            :         case DRAWIMAGE:
     796         [ #  # ]:          0 :             readImage(); break;
     797                 :            :         case DRAWLINK:
     798         [ +  - ]:          9 :             readLink(); break;
     799                 :            :         case DRAWMASK:
     800         [ #  # ]:          0 :             readMask(); break;
     801                 :            :         case DRAWMASKEDIMAGE:
     802         [ #  # ]:          0 :             readMaskedImage(); break;
     803                 :            :         case DRAWSOFTMASKEDIMAGE:
     804         [ #  # ]:          0 :             readSoftMaskedImage(); break;
     805                 :            :         case ENDPAGE:
     806         [ +  - ]:          9 :             m_pSink->endPage(); break;
     807                 :            :         case ENDTEXTOBJECT:
     808         [ +  - ]:         99 :             m_pSink->endText(); break;
     809                 :            :         case EOCLIPPATH:
     810 [ +  - ][ +  - ]:          9 :             m_pSink->intersectEoClip(readPath()); break;
     811                 :            :         case EOFILLPATH:
     812                 :            :         {
     813                 :          9 :             double area = 0.0;
     814         [ +  - ]:          9 :             uno::Reference<rendering::XPolyPolygon2D> path = readPath( &area );
     815         [ +  - ]:          9 :             m_pSink->eoFillPath(path);
     816                 :            :             // if area is smaller than required, add borders.
     817         [ -  + ]:          9 :             if(area < minAreaThreshold)
     818         [ #  # ]:          9 :                 m_pSink->strokePath(path);
     819                 :            :         }
     820                 :          9 :         break;
     821                 :            :         case FILLPATH:
     822                 :            :         {
     823                 :          0 :             double area = 0.0;
     824         [ #  # ]:          0 :             uno::Reference<rendering::XPolyPolygon2D> path = readPath( &area );
     825         [ #  # ]:          0 :             m_pSink->fillPath(path);
     826                 :            :             // if area is smaller than required, add borders.
     827         [ #  # ]:          0 :             if(area < minAreaThreshold)
     828         [ #  # ]:          0 :                 m_pSink->strokePath(path);
     829                 :            :         }
     830                 :          0 :         break;
     831                 :            :         case RESTORESTATE:
     832         [ +  - ]:        144 :             m_pSink->popState(); break;
     833                 :            :         case SAVESTATE:
     834         [ +  - ]:        144 :             m_pSink->pushState(); break;
     835                 :            :         case SETPAGENUM:
     836         [ +  - ]:          9 :             m_pSink->setPageNum( readInt32() ); break;
     837                 :            :         case STARTPAGE:
     838                 :            :         {
     839                 :          9 :             const double nWidth ( readDouble() );
     840                 :          9 :             const double nHeight( readDouble() );
     841         [ +  - ]:          9 :             m_pSink->startPage( geometry::RealSize2D( nWidth, nHeight ) );
     842                 :            :             break;
     843                 :            :         }
     844                 :            :         case STROKEPATH:
     845 [ +  - ][ +  - ]:         18 :             m_pSink->strokePath(readPath()); break;
     846                 :            :         case UPDATECTM:
     847         [ +  - ]:         18 :             readTransformation(); break;
     848                 :            :         case UPDATEFILLCOLOR:
     849         [ +  - ]:        126 :             m_pSink->setFillColor( readColor() ); break;
     850                 :            :         case UPDATEFLATNESS:
     851         [ +  - ]:          9 :             m_pSink->setFlatness( readDouble( ) ); break;
     852                 :            :         case UPDATEFONT:
     853         [ +  - ]:         99 :             readFont(); break;
     854                 :            :         case UPDATELINECAP:
     855         [ +  - ]:         27 :             readLineCap(); break;
     856                 :            :         case UPDATELINEDASH:
     857         [ +  - ]:         18 :             readLineDash(); break;
     858                 :            :         case UPDATELINEJOIN:
     859         [ +  - ]:         27 :             readLineJoin(); break;
     860                 :            :         case UPDATELINEWIDTH:
     861         [ +  - ]:         36 :             m_pSink->setLineWidth( readDouble() );break;
     862                 :            :         case UPDATEMITERLIMIT:
     863         [ +  - ]:          9 :             m_pSink->setMiterLimit( readDouble() ); break;
     864                 :            :         case UPDATESTROKECOLOR:
     865         [ +  - ]:         36 :             m_pSink->setStrokeColor( readColor() ); break;
     866                 :            :         case UPDATESTROKEOPACITY:
     867                 :          0 :             break;
     868                 :            :         case SETTEXTRENDERMODE:
     869         [ #  # ]:          0 :             m_pSink->setTextRenderMode( readInt32() ); break;
     870                 :            : 
     871                 :            :         case NONE:
     872                 :            :         default:
     873                 :            :             OSL_PRECOND(false,"Unknown input");
     874                 :          0 :             break;
     875                 :            :     }
     876                 :            : 
     877                 :            :     // all consumed?
     878                 :       1809 :     OSL_POSTCOND(m_nCharIndex==-1,"leftover scanner input");
     879                 :       1809 : }
     880                 :            : 
     881                 :       1818 : oslFileError readLine( oslFileHandle pFile, ::rtl::OStringBuffer& line )
     882                 :            : {
     883                 :            :     OSL_PRECOND( line.getLength() == 0, "line buf not empty" );
     884                 :            : 
     885                 :            :     // TODO(P3): read larger chunks
     886                 :       1818 :     sal_Char aChar('\n');
     887                 :            :     sal_uInt64 nBytesRead;
     888                 :            :     oslFileError nRes;
     889                 :            : 
     890                 :            :     // skip garbage \r \n at start of line
     891 [ +  - ][ +  - ]:       1818 :     while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
     892                 :            :            nBytesRead == 1 &&
     893                 :            :            (aChar == '\n' || aChar == '\r') ) ;
     894                 :            : 
     895 [ +  + ][ +  - ]:       1818 :     if( aChar != '\n' && aChar != '\r' )
     896         [ +  - ]:       1809 :         line.append( aChar );
     897                 :            : 
     898 [ +  - ][ +  - ]:     113256 :     while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
     899                 :            :            nBytesRead == 1 && aChar != '\n' && aChar != '\r' )
     900                 :            :     {
     901         [ +  - ]:     111438 :         line.append( aChar );
     902                 :            :     }
     903                 :            : 
     904                 :       1818 :     return nRes;
     905                 :            : }
     906                 :            : 
     907                 :            : } // namespace
     908                 :            : 
     909                 :          9 : static bool checkEncryption( const rtl::OUString&                               i_rPath,
     910                 :            :                              const uno::Reference< task::XInteractionHandler >& i_xIHdl,
     911                 :            :                              rtl::OUString&                                     io_rPwd,
     912                 :            :                              bool&                                              o_rIsEncrypted,
     913                 :            :                              const rtl::OUString&                               i_rDocName
     914                 :            :                              )
     915                 :            : {
     916                 :          9 :     bool bSuccess = false;
     917                 :          9 :     rtl::OString aPDFFile;
     918 [ +  - ][ +  - ]:          9 :     aPDFFile = rtl::OUStringToOString( i_rPath, osl_getThreadTextEncoding() );
     919                 :            : 
     920                 :          9 :     pdfparse::PDFReader aParser;
     921         [ +  - ]:          9 :     boost::scoped_ptr<pdfparse::PDFEntry> pEntry( aParser.read( aPDFFile.getStr() ));
     922         [ +  - ]:          9 :     if( pEntry )
     923                 :            :     {
     924         [ -  + ]:          9 :         pdfparse::PDFFile* pPDFFile = dynamic_cast<pdfparse::PDFFile*>(pEntry.get());
     925         [ +  - ]:          9 :         if( pPDFFile )
     926                 :            :         {
     927         [ +  - ]:          9 :             o_rIsEncrypted = pPDFFile->isEncrypted();
     928         [ -  + ]:          9 :             if( o_rIsEncrypted )
     929                 :            :             {
     930                 :          0 :                 bool bAuthenticated = false;
     931         [ #  # ]:          0 :                 if( !io_rPwd.isEmpty() )
     932                 :            :                 {
     933                 :            :                     rtl::OString aIsoPwd = rtl::OUStringToOString( io_rPwd,
     934         [ #  # ]:          0 :                                                                    RTL_TEXTENCODING_ISO_8859_1 );
     935         [ #  # ]:          0 :                     bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
     936                 :            :                     // trash password string on heap
     937         [ #  # ]:          0 :                     rtl_zeroMemory( (void*)aIsoPwd.getStr(), aIsoPwd.getLength() );
     938                 :            :                 }
     939         [ #  # ]:          0 :                 if( bAuthenticated )
     940                 :          0 :                     bSuccess = true;
     941                 :            :                 else
     942                 :            :                 {
     943         [ #  # ]:          0 :                     if( i_xIHdl.is() )
     944                 :            :                     {
     945                 :          0 :                         bool bEntered = false;
     946 [ #  # ][ #  # ]:          0 :                         do
                 [ #  # ]
     947                 :            :                         {
     948         [ #  # ]:          0 :                             bEntered = getPassword( i_xIHdl, io_rPwd, ! bEntered, i_rDocName );
     949                 :            :                             rtl::OString aIsoPwd = rtl::OUStringToOString( io_rPwd,
     950         [ #  # ]:          0 :                                                                            RTL_TEXTENCODING_ISO_8859_1 );
     951         [ #  # ]:          0 :                             bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
     952                 :            :                             // trash password string on heap
     953         [ #  # ]:          0 :                             rtl_zeroMemory( (void*)aIsoPwd.getStr(), aIsoPwd.getLength() );
     954                 :          0 :                         } while( bEntered && ! bAuthenticated );
     955                 :            :                     }
     956                 :            : 
     957                 :            :                     OSL_TRACE( "password: %s", bAuthenticated ? "matches" : "does not match" );
     958                 :          0 :                     bSuccess = bAuthenticated;
     959                 :            :                 }
     960                 :            :                 // trash password string on heap
     961         [ #  # ]:          0 :                 rtl_zeroMemory( (void*)io_rPwd.getStr(), io_rPwd.getLength()*sizeof(sal_Unicode) );
     962         [ #  # ]:          0 :                 if( bAuthenticated )
     963                 :            :                 {
     964                 :          0 :                     rtl::OUStringBuffer aBuf( 128 );
     965         [ #  # ]:          0 :                     aBuf.appendAscii( "_OOO_pdfi_Credentials_" );
     966 [ #  # ][ #  # ]:          0 :                     aBuf.append( pPDFFile->getDecryptionKey() );
     967         [ #  # ]:          0 :                     io_rPwd = aBuf.makeStringAndClear();
     968                 :            :                 }
     969                 :            :             }
     970                 :            :             else
     971                 :          9 :                 bSuccess = true;
     972                 :            :         }
     973                 :            :     }
     974         [ +  - ]:          9 :     return bSuccess;
     975                 :            : }
     976                 :            : 
     977                 :          9 : bool xpdf_ImportFromFile( const ::rtl::OUString&                             rURL,
     978                 :            :                           const ContentSinkSharedPtr&                        rSink,
     979                 :            :                           const uno::Reference< task::XInteractionHandler >& xIHdl,
     980                 :            :                           const rtl::OUString&                               rPwd,
     981                 :            :                           const uno::Reference< uno::XComponentContext >&    xContext )
     982                 :            : {
     983                 :            :     OSL_ASSERT(rSink);
     984                 :            : 
     985                 :          9 :     ::rtl::OUString aSysUPath;
     986 [ -  + ][ +  - ]:          9 :     if( osl_getSystemPathFromFileURL( rURL.pData, &aSysUPath.pData ) != osl_File_E_None )
     987                 :          0 :         return false;
     988                 :          9 :     rtl::OUString aDocName( rURL.copy( rURL.lastIndexOf( sal_Unicode('/') )+1 ) );
     989                 :            : 
     990                 :            :     // check for encryption, if necessary get password
     991                 :          9 :     rtl::OUString aPwd( rPwd );
     992                 :          9 :     bool bIsEncrypted = false;
     993 [ -  + ][ +  - ]:          9 :     if( checkEncryption( aSysUPath, xIHdl, aPwd, bIsEncrypted, aDocName ) == false )
     994                 :          0 :         return false;
     995                 :            : 
     996         [ +  - ]:          9 :     rtl::OUStringBuffer converterURL = rtl::OUString("xpdfimport");
     997                 :            : 
     998                 :            :     // retrieve package location url (xpdfimport executable is located there)
     999                 :            :     // ---------------------------------------------------
    1000                 :            :     uno::Reference<deployment::XPackageInformationProvider> xProvider(
    1001         [ +  - ]:          9 :         xContext->getValueByName(
    1002                 :          9 :             rtl::OUString("/singletons/com.sun.star.deployment.PackageInformationProvider")),
    1003 [ +  - ][ +  - ]:          9 :         uno::UNO_QUERY);
    1004         [ +  - ]:          9 :     if( xProvider.is() )
    1005                 :            :     {
    1006                 :            :         converterURL.insert(
    1007                 :            :             0,
    1008         [ +  - ]:          9 :             rtl::OUString("/"));
    1009                 :            :         converterURL.insert(
    1010                 :            :             0,
    1011         [ +  - ]:          9 :             xProvider->getPackageLocation(
    1012 [ +  - ][ +  - ]:          9 :                 rtl::OUString::createFromAscii(PDFI_IMPL_IDENTIFIER)));
    1013                 :            :     }
    1014                 :            : 
    1015                 :            :     // spawn separate process to keep LGPL/GPL code apart.
    1016                 :            :     // ---------------------------------------------------
    1017                 :          9 :     rtl_uString** ppEnv = NULL;
    1018                 :          9 :     sal_uInt32 nEnv = 0;
    1019                 :            : 
    1020                 :            :     #if defined UNX && ! defined MACOSX
    1021                 :          9 :     rtl::OUString aStr( "$URE_LIB_DIR"  );
    1022                 :          9 :     rtl_bootstrap_expandMacros( &aStr.pData );
    1023                 :          9 :     rtl::OUString aSysPath;
    1024         [ +  - ]:          9 :     osl_getSystemPathFromFileURL( aStr.pData, &aSysPath.pData );
    1025                 :          9 :     rtl::OUStringBuffer aEnvBuf( aStr.getLength() + 20 );
    1026         [ +  - ]:          9 :     aEnvBuf.appendAscii( "LD_LIBRARY_PATH=" );
    1027         [ +  - ]:          9 :     aEnvBuf.append( aSysPath );
    1028         [ +  - ]:          9 :     aStr = aEnvBuf.makeStringAndClear();
    1029                 :          9 :     ppEnv = &aStr.pData;
    1030                 :          9 :     nEnv = 1;
    1031                 :            :     #endif
    1032                 :            : 
    1033                 :          9 :     rtl_uString*  args[] = { aSysUPath.pData };
    1034                 :          9 :     sal_Int32 nArgs = 1;
    1035                 :            : 
    1036                 :            :     oslProcess    aProcess;
    1037                 :          9 :     oslFileHandle pIn  = NULL;
    1038                 :          9 :     oslFileHandle pOut = NULL;
    1039                 :          9 :     oslFileHandle pErr = NULL;
    1040                 :            :     const oslProcessError eErr =
    1041                 :            :         osl_executeProcess_WithRedirectedIO(converterURL.makeStringAndClear().pData,
    1042                 :            :                                             args,
    1043                 :            :                                             nArgs,
    1044                 :            :                                             osl_Process_SEARCHPATH|osl_Process_HIDDEN,
    1045                 :            :                                             osl_getCurrentSecurity(),
    1046                 :            :                                             0, ppEnv, nEnv,
    1047 [ +  - ][ +  - ]:          9 :                                             &aProcess, &pIn, &pOut, &pErr);
                 [ +  - ]
    1048                 :            : 
    1049                 :          9 :     bool bRet=true;
    1050                 :            :     try
    1051                 :            :     {
    1052         [ -  + ]:          9 :         if( eErr!=osl_Process_E_None )
    1053                 :          0 :             return false;
    1054                 :            : 
    1055         [ +  - ]:          9 :         if( pIn )
    1056                 :            :         {
    1057                 :          9 :             rtl::OStringBuffer aBuf(256);
    1058         [ -  + ]:          9 :             if( bIsEncrypted )
    1059 [ #  # ][ #  # ]:          0 :                 aBuf.append( rtl::OUStringToOString( aPwd, RTL_TEXTENCODING_ISO_8859_1 ) );
    1060         [ +  - ]:          9 :             aBuf.append( '\n' );
    1061                 :            : 
    1062                 :          9 :             sal_uInt64 nWritten = 0;
    1063         [ +  - ]:          9 :             osl_writeFile( pIn, aBuf.getStr(), sal_uInt64(aBuf.getLength()), &nWritten );
    1064                 :            :         }
    1065                 :            : 
    1066 [ +  - ][ +  - ]:          9 :         if( pOut && pErr )
    1067                 :            :         {
    1068                 :            :             // read results of PDF parser. One line - one call to
    1069                 :            :             // OutputDev. stderr is used for alternate streams, like
    1070                 :            :             // embedded fonts and bitmaps
    1071         [ +  - ]:          9 :             Parser aParser(rSink,pErr,xContext);
    1072                 :          9 :             ::rtl::OStringBuffer line;
    1073 [ +  - ][ +  - ]:       1818 :             while( osl_File_E_None == readLine(pOut, line) && line.getLength() )
         [ +  + ][ +  + ]
    1074 [ +  - ][ +  - ]:       1818 :                 aParser.parseLine(line.makeStringAndClear());
                 [ #  # ]
    1075                 :            :         }
    1076                 :            :     }
    1077         [ #  # ]:          0 :     catch( uno::Exception& )
    1078                 :            :     {
    1079                 :            :         // crappy C file interface. need manual resource dealloc
    1080                 :          0 :         bRet = false;
    1081                 :            :     }
    1082                 :            : 
    1083         [ +  - ]:          9 :     if( pIn )
    1084         [ +  - ]:          9 :         osl_closeFile(pIn);
    1085         [ +  - ]:          9 :     if( pOut )
    1086         [ +  - ]:          9 :         osl_closeFile(pOut);
    1087         [ +  - ]:          9 :     if( pErr )
    1088         [ +  - ]:          9 :         osl_closeFile(pErr);
    1089         [ +  - ]:          9 :     osl_freeProcessHandle(aProcess);
    1090                 :          9 :     return bRet;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : 
    1094                 :          0 : bool xpdf_ImportFromStream( const uno::Reference< io::XInputStream >&         xInput,
    1095                 :            :                             const ContentSinkSharedPtr&                       rSink,
    1096                 :            :                             const uno::Reference<task::XInteractionHandler >& xIHdl,
    1097                 :            :                             const rtl::OUString&                              rPwd,
    1098                 :            :                             const uno::Reference< uno::XComponentContext >&   xContext )
    1099                 :            : {
    1100                 :            :     OSL_ASSERT(xInput.is());
    1101                 :            :     OSL_ASSERT(rSink);
    1102                 :            : 
    1103                 :            :     // convert XInputStream to local temp file
    1104                 :          0 :     oslFileHandle aFile = NULL;
    1105                 :          0 :     rtl::OUString aURL;
    1106 [ #  # ][ #  # ]:          0 :     if( osl_createTempFile( NULL, &aFile, &aURL.pData ) != osl_File_E_None )
    1107                 :          0 :         return false;
    1108                 :            : 
    1109                 :            :     // copy content, buffered...
    1110                 :          0 :     const sal_uInt32 nBufSize = 4096;
    1111         [ #  # ]:          0 :     uno::Sequence<sal_Int8> aBuf( nBufSize );
    1112                 :          0 :     sal_uInt64 nBytes = 0;
    1113                 :          0 :     sal_uInt64 nWritten = 0;
    1114                 :          0 :     bool bSuccess = true;
    1115         [ #  # ]:          0 :     do
    1116                 :            :     {
    1117                 :            :         try
    1118                 :            :         {
    1119 [ #  # ][ #  # ]:          0 :             nBytes = xInput->readBytes( aBuf, nBufSize );
    1120                 :            :         }
    1121         [ #  # ]:          0 :         catch( com::sun::star::uno::Exception& )
    1122                 :            :         {
    1123         [ #  # ]:          0 :             osl_closeFile( aFile );
    1124                 :          0 :             throw;
    1125                 :            :         }
    1126         [ #  # ]:          0 :         if( nBytes > 0 )
    1127                 :            :         {
    1128         [ #  # ]:          0 :             osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
    1129         [ #  # ]:          0 :             if( nWritten != nBytes )
    1130                 :            :             {
    1131                 :          0 :                 bSuccess = false;
    1132                 :          0 :                 break;
    1133                 :            :             }
    1134                 :            :         }
    1135                 :            :     }
    1136                 :            :     while( nBytes == nBufSize );
    1137                 :            : 
    1138         [ #  # ]:          0 :     osl_closeFile( aFile );
    1139                 :            : 
    1140         [ #  # ]:          0 :     if ( bSuccess )
    1141         [ #  # ]:          0 :         bSuccess = xpdf_ImportFromFile( aURL, rSink, xIHdl, rPwd, xContext );
    1142         [ #  # ]:          0 :     osl_removeFile( aURL.pData );
    1143                 :            : 
    1144         [ #  # ]:          0 :     return bSuccess;
    1145                 :            : }
    1146                 :            : 
    1147                 :            : }
    1148                 :            : 
    1149                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10