summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2008-08-14 16:14:57 +0000
committerKurt Zenker <kz@openoffice.org>2008-08-14 16:14:57 +0000
commit47ece984fed99face79df8b96cbb1f465bed8a30 (patch)
tree65dba79414223303e275691196ec0d9dc208f6a6
parent280c78ed5d1a74eb49f807e608529597a321e9c8 (diff)
INTEGRATION: CWS pdf25 (1.1.2); FILE ADDED
2008/08/05 09:59:17 akhva 1.1.2.2: #i90061 2008/07/24 11:37:44 akhva 1.1.2.1: #90061
-rwxr-xr-xsdext/source/pdfimport/wrapper/makefile.mk52
-rwxr-xr-xsdext/source/pdfimport/wrapper/wrapper.cxx961
2 files changed, 1013 insertions, 0 deletions
diff --git a/sdext/source/pdfimport/wrapper/makefile.mk b/sdext/source/pdfimport/wrapper/makefile.mk
new file mode 100755
index 0000000..2eeb913
--- /dev/null
+++ b/sdext/source/pdfimport/wrapper/makefile.mk
@@ -0,0 +1,52 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.2 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sdext
+TARGET=xpdfwrapper
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+.INCLUDE: ../pdfisettings.pmk
+
+CDEFS+= -DPDFI_IMPL_IDENTIFIER=$(IMPLEMENTATION_IDENTIFIER)
+
+# --- Files --------------------------------------------------------
+
+SLOFILES=\
+ $(SLO)$/wrapper.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/sdext/source/pdfimport/wrapper/wrapper.cxx b/sdext/source/pdfimport/wrapper/wrapper.cxx
new file mode 100755
index 0000000..7fb7301
--- /dev/null
+++ b/sdext/source/pdfimport/wrapper/wrapper.cxx
@@ -0,0 +1,961 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wrapper.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sdext.hxx"
+
+#include "contentsink.hxx"
+
+#include <osl/file.h>
+#include <osl/thread.h>
+#include <osl/process.h>
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/byteseq.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/deployment/XPackageInformationProvider.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/XColorSpace.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/geometry/AffineMatrix2D.hpp>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+
+#include <boost/bind.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+
+#include <hash_map>
+#include <string.h>
+
+#include "rtl/bootstrap.h"
+
+#include <string.h> // memcmp
+
+#ifndef PDFI_IMPL_IDENTIFIER
+# error define implementation name for pdfi extension, please!
+#endif
+
+using namespace com::sun::star;
+
+namespace pdfi
+{
+
+namespace
+{
+
+// identifier of the strings coming from the out-of-process xpdf
+// converter
+enum parseKey {
+ CLIPPATH,
+ DRAWCHAR,
+ DRAWIMAGE,
+ DRAWLINK,
+ DRAWMASK,
+ DRAWMASKEDIMAGE,
+ DRAWSOFTMASKEDIMAGE,
+ ENDPAGE,
+ ENDTEXTOBJECT,
+ EOCLIPPATH,
+ EOFILLPATH,
+ FILLPATH,
+ HYPERLINK,
+ INTERSECTCLIP,
+ INTERSECTEOCLIP,
+ POPSTATE,
+ PUSHSTATE,
+ RESTORESTATE,
+ SAVESTATE,
+ SETBLENDMODE,
+ SETFILLCOLOR,
+ SETFONT,
+ SETLINECAP,
+ SETLINEDASH,
+ SETLINEJOIN,
+ SETLINEWIDTH,
+ SETMITERLIMIT,
+ SETPAGENUM,
+ SETSTROKECOLOR,
+ SETTRANSFORMATION,
+ STARTPAGE,
+ STROKEPATH,
+ UPDATEBLENDMODE,
+ UPDATECTM,
+ UPDATEFILLCOLOR,
+ UPDATEFILLOPACITY,
+ UPDATEFLATNESS,
+ UPDATEFONT,
+ UPDATELINECAP,
+ UPDATELINEDASH,
+ UPDATELINEJOIN,
+ UPDATELINEWIDTH,
+ UPDATEMITERLIMIT,
+ UPDATESTROKECOLOR,
+ UPDATESTROKEOPACITY,
+ NONE
+};
+
+#include "hash.cxx"
+
+class Parser
+{
+ typedef std::hash_map< sal_Int64,
+ FontAttributes > FontMapType;
+
+ const uno::Reference<uno::XComponentContext> m_xContext;
+ const ContentSinkSharedPtr m_pSink;
+ const oslFileHandle m_pErr;
+ ::rtl::OString m_aLine;
+ FontMapType m_aFontMap;
+ sal_Int32 m_nNextToken;
+ sal_Int32 m_nCharIndex;
+
+
+ ::rtl::OString readNextToken();
+ void readInt32( sal_Int32& o_Value );
+ sal_Int32 readInt32();
+ void readInt64( sal_Int64& o_Value );
+ sal_Int64 readInt64();
+ void readDouble( double& o_Value );
+ double readDouble();
+ void readBinaryData( uno::Sequence<sal_Int8>& rBuf );
+
+ uno::Reference<rendering::XPolyPolygon2D> readPath();
+
+ void readChar();
+ void readLineCap();
+ void readLineDash();
+ void readLineJoin();
+ void readTransformation();
+ rendering::ARGBColor readColor();
+ void parseFontFamilyName( FontAttributes& aResult );
+ void readFont();
+ uno::Sequence<beans::PropertyValue> readImageImpl();
+
+ void readImage();
+ void readMask();
+ void readLink();
+ void readMaskedImage();
+ void readSoftMaskedImage();
+
+public:
+ Parser( const ContentSinkSharedPtr& rSink,
+ oslFileHandle pErr,
+ const uno::Reference<uno::XComponentContext>& xContext ) :
+ m_xContext(xContext),
+ m_pSink(rSink),
+ m_pErr(pErr),
+ m_aLine(),
+ m_aFontMap(101),
+ m_nNextToken(-1),
+ m_nCharIndex(-1)
+ {}
+
+ void parseLine( const ::rtl::OString& rLine );
+};
+
+::rtl::OString Parser::readNextToken()
+{
+ OSL_PRECOND(m_nCharIndex!=-1,"insufficient input");
+ return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex);
+}
+
+void Parser::readInt32( sal_Int32& o_Value )
+{
+ o_Value = readNextToken().toInt32();
+}
+
+sal_Int32 Parser::readInt32()
+{
+ return readNextToken().toInt32();
+}
+
+void Parser::readInt64( sal_Int64& o_Value )
+{
+ o_Value = readNextToken().toInt64();
+}
+
+sal_Int64 Parser::readInt64()
+{
+ return readNextToken().toInt64();
+}
+
+void Parser::readDouble( double& o_Value )
+{
+ o_Value = readNextToken().toDouble();
+}
+
+double Parser::readDouble()
+{
+ return readNextToken().toDouble();
+}
+
+void Parser::readBinaryData( uno::Sequence<sal_Int8>& rBuf )
+{
+ sal_Int32 nFileLen( rBuf.getLength() );
+ sal_Int8* pBuf( rBuf.getArray() );
+ sal_uInt64 nBytesRead(0);
+ oslFileError nRes=osl_File_E_None;
+ while( nFileLen &&
+ osl_File_E_None == (nRes=osl_readFile( m_pErr, pBuf, nFileLen, &nBytesRead )) )
+ {
+ pBuf += nBytesRead;
+ nFileLen -= sal::static_int_cast<sal_Int32>(nBytesRead);
+ }
+
+ OSL_PRECOND(nRes==osl_File_E_None, "inconsistent data");
+}
+
+uno::Reference<rendering::XPolyPolygon2D> Parser::readPath()
+{
+ const rtl::OString aSubPathMarker( "subpath" );
+
+ if( 0 != readNextToken().compareTo( aSubPathMarker ) )
+ OSL_PRECOND(false, "broken path");
+
+ basegfx::B2DPolyPolygon aResult;
+ while( m_nCharIndex != -1 )
+ {
+ basegfx::B2DPolygon aSubPath;
+
+ sal_Int32 nClosedFlag;
+ readInt32( nClosedFlag );
+ aSubPath.setClosed( nClosedFlag != 0 );
+
+ sal_Int32 nContiguousControlPoints(0);
+ sal_Int32 nDummy=m_nCharIndex;
+ rtl::OString aCurrToken( m_aLine.getToken(m_nNextToken,' ',nDummy) );
+
+ while( m_nCharIndex != -1 && 0 != aCurrToken.compareTo(aSubPathMarker) )
+ {
+ sal_Int32 nCurveFlag;
+ double nX, nY;
+ readDouble( nX );
+ readDouble( nY );
+ readInt32( nCurveFlag );
+
+ aSubPath.append(basegfx::B2DPoint(nX,nY));
+ if( nCurveFlag )
+ {
+ ++nContiguousControlPoints;
+ }
+ else if( nContiguousControlPoints )
+ {
+ OSL_PRECOND(nContiguousControlPoints==2,"broken bezier path");
+
+ // have two control points before us. the current one
+ // is a normal point - thus, convert previous points
+ // into bezier segment
+ const sal_uInt32 nPoints( aSubPath.count() );
+ const basegfx::B2DPoint aCtrlA( aSubPath.getB2DPoint(nPoints-3) );
+ const basegfx::B2DPoint aCtrlB( aSubPath.getB2DPoint(nPoints-2) );
+ const basegfx::B2DPoint aEnd( aSubPath.getB2DPoint(nPoints-1) );
+ aSubPath.remove(nPoints-3, 3);
+ aSubPath.appendBezierSegment(aCtrlA, aCtrlB, aEnd);
+
+ nContiguousControlPoints=0;
+ }
+
+ // one token look-ahead (new subpath or more points?
+ nDummy=m_nCharIndex;
+ aCurrToken = m_aLine.getToken(m_nNextToken,' ',nDummy);
+ }
+
+ aResult.append( aSubPath );
+ if( m_nCharIndex != -1 )
+ readNextToken();
+ }
+
+ return static_cast<rendering::XLinePolyPolygon2D*>(
+ new basegfx::unotools::UnoPolyPolygon(aResult));
+}
+
+void Parser::readChar()
+{
+ geometry::Matrix2D aUnoMatrix;
+ geometry::RealRectangle2D aRect;
+
+ readDouble(aRect.X1);
+ readDouble(aRect.Y1);
+ readDouble(aRect.X2);
+ readDouble(aRect.Y2);
+ readDouble(aUnoMatrix.m00);
+ readDouble(aUnoMatrix.m01);
+ readDouble(aUnoMatrix.m10);
+ readDouble(aUnoMatrix.m11);
+
+ rtl::OString aChars = m_aLine.copy( m_nCharIndex );
+
+ // chars gobble up rest of line
+ m_nCharIndex = -1;
+
+ m_pSink->drawGlyphs( rtl::OStringToOUString( aChars,
+ RTL_TEXTENCODING_UTF8 ),
+ aRect, aUnoMatrix );
+}
+
+void Parser::readLineCap()
+{
+ sal_Int8 nCap(rendering::PathCapType::BUTT);
+ switch( readInt32() )
+ {
+ default:
+ // FALLTHROUGH intended
+ case 0: nCap = rendering::PathCapType::BUTT; break;
+ case 1: nCap = rendering::PathCapType::ROUND; break;
+ case 2: nCap = rendering::PathCapType::SQUARE; break;
+ }
+ m_pSink->setLineCap(nCap);
+}
+
+void Parser::readLineDash()
+{
+ if( m_nCharIndex == -1 )
+ {
+ m_pSink->setLineDash( uno::Sequence<double>(), 0.0 );
+ return;
+ }
+
+ const double nOffset(readDouble());
+ const sal_Int32 nLen(readInt32());
+
+ uno::Sequence<double> aDashArray(nLen);
+ double* pArray=aDashArray.getArray();
+ for( sal_Int32 i=0; i<nLen; ++i )
+ *pArray++ = readDouble();
+
+ m_pSink->setLineDash( aDashArray, nOffset );
+}
+
+void Parser::readLineJoin()
+{
+ sal_Int8 nJoin(rendering::PathJoinType::MITER);
+ switch( readInt32() )
+ {
+ default:
+ // FALLTHROUGH intended
+ case 0: nJoin = rendering::PathJoinType::MITER; break;
+ case 1: nJoin = rendering::PathJoinType::ROUND; break;
+ case 2: nJoin = rendering::PathJoinType::BEVEL; break;
+ }
+ m_pSink->setLineJoin(nJoin);
+}
+
+void Parser::readTransformation()
+{
+ geometry::AffineMatrix2D aMat;
+ readDouble(aMat.m00);
+ readDouble(aMat.m10);
+ readDouble(aMat.m01);
+ readDouble(aMat.m11);
+ readDouble(aMat.m02);
+ readDouble(aMat.m12);
+ m_pSink->setTransformation( aMat );
+}
+
+rendering::ARGBColor Parser::readColor()
+{
+ rendering::ARGBColor aRes;
+ readDouble(aRes.Red);
+ readDouble(aRes.Green);
+ readDouble(aRes.Blue);
+ readDouble(aRes.Alpha);
+ return aRes;
+}
+
+void Parser::parseFontFamilyName( FontAttributes& aResult )
+{
+ rtl::OUStringBuffer aNewFamilyName( aResult.familyName.getLength() );
+
+ const sal_Unicode* pCopy = aResult.familyName.getStr();
+ sal_Int32 nLen = aResult.familyName.getLength();
+ // parse out truetype subsets (e.g. BAAAAA+Thorndale)
+ if( nLen > 8 && pCopy[6] == sal_Unicode('+') )
+ {
+ pCopy += 7;
+ nLen -= 7;
+ }
+
+ while( nLen )
+ {
+ if( nLen > 5 &&
+ ( *pCopy == 'i' || *pCopy == 'I' ) &&
+ pCopy[1] == 't' &&
+ pCopy[2] == 'a' &&
+ pCopy[3] == 'l' &&
+ pCopy[4] == 'i' &&
+ pCopy[5] == 'c' )
+ {
+ aResult.isItalic = true;
+ nLen -=6;
+ pCopy += 6;
+ }
+ else if( nLen > 3 &&
+ ( *pCopy == 'B' || *pCopy == 'b' ) &&
+ pCopy[1] == 'o' &&
+ pCopy[2] == 'l' &&
+ pCopy[3] == 'd' )
+ {
+ aResult.isBold = true;
+ nLen -=4;
+ pCopy += 4;
+ }
+ else if( nLen > 5 &&
+ *pCopy == '-' &&
+ ( pCopy[1] == 'R' || pCopy[1] == 'r' ) &&
+ pCopy[2] == 'o' &&
+ pCopy[3] == 'm' &&
+ pCopy[4] == 'a' &&
+ pCopy[5] == 'n' )
+ {
+ nLen -= 6;
+ pCopy += 6;
+ }
+ else
+ {
+ if( *pCopy != '-' )
+ aNewFamilyName.append( *pCopy );
+ pCopy++;
+ nLen--;
+ }
+ }
+ aResult.familyName = aNewFamilyName.makeStringAndClear();
+}
+
+void Parser::readFont()
+{
+ ::rtl::OString aFontName;
+ sal_Int64 nFontID;
+ sal_Int32 nIsEmbedded, nIsBold, nIsItalic, nIsUnderline, nFileLen;
+ double nSize;
+
+ readInt64(nFontID);
+ readInt32(nIsEmbedded);
+ readInt32(nIsBold);
+ readInt32(nIsItalic);
+ readInt32(nIsUnderline);
+ readDouble(nSize);
+ readInt32(nFileLen);
+
+ nSize = nSize < 0.0 ? -nSize : nSize;
+ aFontName = m_aLine.copy( m_nCharIndex );
+
+ // name gobbles up rest of line
+ m_nCharIndex = -1;
+
+ FontMapType::const_iterator pFont( m_aFontMap.find(nFontID) );
+ if( pFont != m_aFontMap.end() )
+ {
+ OSL_PRECOND(nFileLen==0,"font data for known font");
+ FontAttributes aRes(pFont->second);
+ aRes.size = nSize;
+ m_pSink->setFont( aRes );
+
+ return;
+ }
+
+ // yet unknown font - get info and add to map
+ FontAttributes aResult( rtl::OStringToOUString( aFontName,
+ RTL_TEXTENCODING_UTF8 ),
+ nIsBold != 0,
+ nIsItalic != 0,
+ nIsUnderline != 0,
+ nSize );
+
+ // extract textual attributes (bold, italic in the name, etc.)
+ parseFontFamilyName(aResult);
+
+ // need to read font file?
+ if( nFileLen )
+ {
+ uno::Sequence<sal_Int8> aFontFile(nFileLen);
+ readBinaryData( aFontFile );
+
+ awt::FontDescriptor aFD;
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[0] <<= aFontFile;
+
+ try
+ {
+ uno::Reference< beans::XMaterialHolder > xMat(
+ m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.FontIdentificator" ) ),
+ aArgs,
+ m_xContext ),
+ uno::UNO_QUERY );
+ if( xMat.is() )
+ {
+ uno::Any aRes( xMat->getMaterial() );
+ if( aRes >>= aFD )
+ {
+ aResult.familyName = aFD.Name;
+ aResult.isBold = (aFD.Weight > 100.0);
+ aResult.isItalic = (aFD.Slant == awt::FontSlant_OBLIQUE ||
+ aFD.Slant == awt::FontSlant_ITALIC );
+ aResult.isUnderline = false;
+ aResult.size = 0;
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ if( !aResult.familyName.getLength() )
+ {
+ // last fallback
+ aResult.familyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Arial" ) );
+ aResult.isUnderline = false;
+ }
+
+ }
+
+ m_aFontMap[nFontID] = aResult;
+
+ aResult.size = nSize;
+ m_pSink->setFont(aResult);
+}
+
+uno::Sequence<beans::PropertyValue> Parser::readImageImpl()
+{
+ static const rtl::OString aJpegMarker( "JPEG" );
+ static const rtl::OString aPbmMarker( "PBM" );
+ static const rtl::OString aPpmMarker( "PPM" );
+ static const rtl::OUString aJpegFile(
+ RTL_CONSTASCII_USTRINGPARAM( "DUMMY.JPEG" ));
+ static const rtl::OUString aPbmFile(
+ RTL_CONSTASCII_USTRINGPARAM( "DUMMY.PBM" ));
+ static const rtl::OUString aPpmFile(
+ RTL_CONSTASCII_USTRINGPARAM( "DUMMY.PPM" ));
+
+ rtl::OString aToken = readNextToken();
+ const sal_Int32 nImageSize( readInt32() );
+
+ rtl::OUString aFileName;
+ if( aToken.compareTo( aJpegMarker ) == 0 )
+ aFileName = aJpegFile;
+ else if( aToken.compareTo( aPbmMarker ) == 0 )
+ aFileName = aPbmFile;
+ else
+ {
+ OSL_PRECOND( aToken.compareTo( aPpmMarker ) == 0,
+ "Invalid bitmap format" );
+ aFileName = aPpmFile;
+ }
+
+ uno::Sequence<sal_Int8> aDataSequence(nImageSize);
+ readBinaryData( aDataSequence );
+
+ uno::Sequence< uno::Any > aStreamCreationArgs(1);
+ aStreamCreationArgs[0] <<= aDataSequence;
+
+ uno::Reference< uno::XComponentContext > xContext( m_xContext, uno::UNO_SET_THROW );
+ uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
+ uno::Reference< io::XInputStream > xDataStream( xFactory->createInstanceWithArgumentsAndContext(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.SequenceInputStream" ) ),
+ aStreamCreationArgs, m_xContext ), uno::UNO_QUERY_THROW );
+
+ uno::Sequence<beans::PropertyValue> aSequence(3);
+ aSequence[0] = beans::PropertyValue( ::rtl::OUString::createFromAscii("URL"),
+ 0,
+ uno::makeAny(aFileName),
+ beans::PropertyState_DIRECT_VALUE );
+ aSequence[1] = beans::PropertyValue( ::rtl::OUString::createFromAscii("InputStream"),
+ 0,
+ uno::makeAny( xDataStream ),
+ beans::PropertyState_DIRECT_VALUE );
+ aSequence[2] = beans::PropertyValue( ::rtl::OUString::createFromAscii("InputSequence"),
+ 0,
+ uno::makeAny(aDataSequence),
+ beans::PropertyState_DIRECT_VALUE );
+
+ return aSequence;
+}
+
+void Parser::readImage()
+{
+ sal_Int32 nWidth, nHeight,nMaskColors;
+ readInt32(nWidth);
+ readInt32(nHeight);
+ readInt32(nMaskColors);
+
+ uno::Sequence<beans::PropertyValue> aImg( readImageImpl() );
+
+ if( nMaskColors )
+ {
+ uno::Sequence<sal_Int8> aDataSequence(nMaskColors);
+ readBinaryData( aDataSequence );
+
+ uno::Sequence<uno::Any> aMaskRanges(2);
+
+ uno::Sequence<double> aMinRange(nMaskColors/2);
+ uno::Sequence<double> aMaxRange(nMaskColors/2);
+ for( sal_Int32 i=0; i<nMaskColors/2; ++i )
+ {
+ aMinRange[i] = aDataSequence[i] / 255.0;
+ aMaxRange[i] = aDataSequence[i+nMaskColors/2] / 255.0;
+ }
+
+ aMaskRanges[0] = uno::makeAny(aMinRange);
+ aMaskRanges[1] = uno::makeAny(aMaxRange);
+
+ m_pSink->drawColorMaskedImage( aImg, aMaskRanges );
+ }
+ else
+ m_pSink->drawImage( aImg );
+}
+
+void Parser::readMask()
+{
+ sal_Int32 nWidth, nHeight, nInvert;
+ readInt32(nWidth);
+ readInt32(nHeight);
+ readInt32(nInvert);
+
+ m_pSink->drawMask( readImageImpl(), nInvert );
+}
+
+void Parser::readLink()
+{
+ geometry::RealRectangle2D aBounds;
+ readDouble(aBounds.X1);
+ readDouble(aBounds.Y1);
+ readDouble(aBounds.X2);
+ readDouble(aBounds.Y2);
+
+ m_pSink->hyperLink( aBounds,
+ rtl::OStringToOUString( m_aLine.copy(m_nCharIndex),
+ RTL_TEXTENCODING_UTF8 ));
+ // name gobbles up rest of line
+ m_nCharIndex = -1;
+}
+
+void Parser::readMaskedImage()
+{
+ sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight, nMaskInvert;
+ readInt32(nWidth);
+ readInt32(nHeight);
+ readInt32(nMaskWidth);
+ readInt32(nMaskHeight);
+ readInt32(nMaskInvert);
+
+ const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
+ const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
+ m_pSink->drawMaskedImage( aImage, aMask, nMaskInvert != 0 );
+}
+
+void Parser::readSoftMaskedImage()
+{
+ sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight;
+ readInt32(nWidth);
+ readInt32(nHeight);
+ readInt32(nMaskWidth);
+ readInt32(nMaskHeight);
+
+ const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
+ const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
+ m_pSink->drawAlphaMaskedImage( aImage, aMask );
+}
+
+void Parser::parseLine( const ::rtl::OString& rLine )
+{
+ OSL_PRECOND( m_pSink, "Invalid sink" );
+ OSL_PRECOND( m_pErr, "Invalid filehandle" );
+ OSL_PRECOND( m_xContext.is(), "Invalid service factory" );
+
+ m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine;
+ uno::Reference<rendering::XPolyPolygon2D> xPoly;
+ const ::rtl::OString& rCmd = readNextToken();
+ const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.getStr(),
+ rCmd.getLength() );
+ OSL_ASSERT(pEntry);
+ switch( pEntry->eKey )
+ {
+ case CLIPPATH:
+ m_pSink->intersectClip(readPath()); break;
+ case DRAWCHAR:
+ readChar(); break;
+ case DRAWIMAGE:
+ readImage(); break;
+ case DRAWLINK:
+ readLink(); break;
+ case DRAWMASK:
+ readMask(); break;
+ case DRAWMASKEDIMAGE:
+ readMaskedImage(); break;
+ case DRAWSOFTMASKEDIMAGE:
+ readSoftMaskedImage(); break;
+ case ENDPAGE:
+ m_pSink->endPage(); break;
+ case ENDTEXTOBJECT:
+ m_pSink->endText(); break;
+ case EOCLIPPATH:
+ m_pSink->intersectEoClip(readPath()); break;
+ case EOFILLPATH:
+ m_pSink->eoFillPath(readPath()); break;
+ case FILLPATH:
+ m_pSink->fillPath(readPath()); break;
+ case RESTORESTATE:
+ m_pSink->popState(); break;
+ case SAVESTATE:
+ m_pSink->pushState(); break;
+ case SETPAGENUM:
+ m_pSink->setPageNum( readInt32() ); break;
+ case STARTPAGE:
+ {
+ const double nWidth ( readDouble() );
+ const double nHeight( readDouble() );
+ m_pSink->startPage( geometry::RealSize2D( nWidth, nHeight ) );
+ break;
+ }
+ case STROKEPATH:
+ m_pSink->strokePath(readPath()); break;
+ case UPDATECTM:
+ readTransformation(); break;
+ case UPDATEFILLCOLOR:
+ m_pSink->setFillColor( readColor() ); break;
+ case UPDATEFLATNESS:
+ m_pSink->setFlatness( readDouble( ) ); break;
+ case UPDATEFONT:
+ readFont(); break;
+ case UPDATELINECAP:
+ readLineCap(); break;
+ case UPDATELINEDASH:
+ readLineDash(); break;
+ case UPDATELINEJOIN:
+ readLineJoin(); break;
+ case UPDATELINEWIDTH:
+ m_pSink->setLineWidth( readDouble() );break;
+ case UPDATEMITERLIMIT:
+ m_pSink->setMiterLimit( readDouble() ); break;
+ case UPDATESTROKECOLOR:
+ m_pSink->setStrokeColor( readColor() ); break;
+ case UPDATESTROKEOPACITY:
+ break;
+
+ case NONE:
+ default:
+ OSL_PRECOND(false,"Unknown input");
+ break;
+ }
+
+ // all consumed?
+ OSL_POSTCOND(m_nCharIndex==-1,"leftover scanner input");
+}
+
+oslFileError readLine( oslFileHandle pFile, ::rtl::OStringBuffer& line )
+{
+ OSL_PRECOND( line.getLength() == 0, "line buf not empty" );
+
+ // TODO(P3): read larger chunks
+ sal_Char aChar('\n');
+ sal_uInt64 nBytesRead;
+ oslFileError nRes;
+
+ // skip garbage \r \n at start of line
+ while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
+ nBytesRead == 1 &&
+ (aChar == '\n' || aChar == '\r') );
+
+ if( aChar != '\n' && aChar != '\r' )
+ line.append( aChar );
+
+ while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
+ nBytesRead == 1 && aChar != '\n' && aChar != '\r' )
+ {
+ line.append( aChar );
+ }
+
+ return nRes;
+}
+
+} // namespace
+
+bool xpdf_ImportFromFile( const ::rtl::OUString& rURL,
+ const ContentSinkSharedPtr& rSink,
+ const uno::Reference< uno::XComponentContext >& xContext )
+{
+ OSL_ASSERT(rSink);
+
+ ::rtl::OUString aSysUPath;
+ if( osl_getSystemPathFromFileURL( rURL.pData, &aSysUPath.pData ) != osl_File_E_None )
+ return false;
+
+ rtl::OUStringBuffer converterURL = rtl::OUString::createFromAscii("xpdfimport");
+
+ // retrieve package location url (xpdfimport executable is located there)
+ // ---------------------------------------------------
+ uno::Reference<deployment::XPackageInformationProvider> xProvider(
+ xContext->getValueByName(
+ rtl::OUString::createFromAscii("/singletons/com.sun.star.deployment.PackageInformationProvider" )),
+ uno::UNO_QUERY);
+ if( xProvider.is() )
+ {
+ converterURL.insert(
+ 0,
+ rtl::OUString::createFromAscii("/"));
+ converterURL.insert(
+ 0,
+ xProvider->getPackageLocation(
+ rtl::OUString::createFromAscii(
+ BOOST_PP_STRINGIZE(PDFI_IMPL_IDENTIFIER))));
+ }
+
+ // spawn separate process to keep LGPL/GPL code apart.
+ // ---------------------------------------------------
+ rtl_uString** ppEnv = NULL;
+ sal_uInt32 nEnv = 0;
+
+ #if defined UNX && ! defined MACOSX
+ rtl::OUString aStr( RTL_CONSTASCII_USTRINGPARAM( "$URE_LIB_DIR" ) );
+ rtl_bootstrap_expandMacros( &aStr.pData );
+ rtl::OUString aSysPath;
+ osl_getSystemPathFromFileURL( aStr.pData, &aSysPath.pData );
+ rtl::OUStringBuffer aBuf( aStr.getLength() + 20 );
+ aBuf.appendAscii( "LD_LIBRARY_PATH=" );
+ aBuf.append( aSysPath );
+ aStr = aBuf.makeStringAndClear();
+ ppEnv = &aStr.pData;
+ nEnv = 1;
+ #endif
+
+ rtl_uString* args[] = { aSysUPath.pData };
+ oslProcess aProcess;
+ oslFileHandle pIn = NULL;
+ oslFileHandle pOut = NULL;
+ oslFileHandle pErr = NULL;
+ const oslProcessError eErr =
+ osl_executeProcess_WithRedirectedIO(converterURL.makeStringAndClear().pData,
+ args,
+ sizeof(args)/sizeof(*args),
+ osl_Process_SEARCHPATH|osl_Process_HIDDEN,
+ osl_getCurrentSecurity(),
+ 0, ppEnv, nEnv,
+ &aProcess, &pIn, &pOut, &pErr);
+
+ bool bRet=true;
+ try
+ {
+ if( eErr!=osl_Process_E_None )
+ return false;
+
+ if( pOut && pErr )
+ {
+ // read results of PDF parser. One line - one call to
+ // OutputDev. stderr is used for alternate streams, like
+ // embedded fonts and bitmaps
+ Parser aParser(rSink,pErr,xContext);
+ ::rtl::OStringBuffer line;
+ while( osl_File_E_None == readLine(pOut, line) && line.getLength() )
+ aParser.parseLine(line.makeStringAndClear());
+ }
+ }
+ catch( uno::Exception& )
+ {
+ // crappy C file interface. need manual resource dealloc
+ bRet = false;
+ }
+
+ if( pIn )
+ osl_closeFile(pIn);
+ if( pOut )
+ osl_closeFile(pOut);
+ if( pErr )
+ osl_closeFile(pErr);
+ osl_freeProcessHandle(aProcess);
+ return bRet;
+}
+
+bool xpdf_ImportFromStream( const uno::Reference< io::XInputStream >& xInput,
+ const ContentSinkSharedPtr& rSink,
+ const uno::Reference< uno::XComponentContext >& xContext )
+{
+ OSL_ASSERT(xInput.is());
+ OSL_ASSERT(rSink);
+
+ // convert XInputStream to local temp file
+ oslFileHandle aFile = NULL;
+ rtl::OUString aURL;
+ if( osl_createTempFile( NULL, &aFile, &aURL.pData ) != osl_File_E_None )
+ return false;
+
+ // copy content, buffered...
+ const sal_uInt32 nBufSize = 4096;
+ uno::Sequence<sal_Int8> aBuf( nBufSize );
+ sal_uInt64 nBytes = 0;
+ sal_uInt64 nWritten = 0;
+ bool bSuccess = true;
+ do
+ {
+ try
+ {
+ nBytes = xInput->readBytes( aBuf, nBufSize );
+ }
+ catch( com::sun::star::uno::Exception& )
+ {
+ osl_closeFile( aFile );
+ throw;
+ }
+ if( nBytes > 0 )
+ {
+ osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
+ if( nWritten != nBytes )
+ {
+ bSuccess = false;
+ break;
+ }
+ }
+ }
+ while( nBytes == nBufSize );
+
+ osl_closeFile( aFile );
+
+ return bSuccess && xpdf_ImportFromFile( aURL, rSink, xContext );
+}
+
+}
+