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