Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <stdio.h>
22 :
23 : #include <tools/solar.h>
24 : #include <vcl/svapp.hxx>
25 : #include <vcl/bitmap.hxx>
26 : #include <vcl/bitmapex.hxx>
27 : #include <vcl/animate.hxx>
28 : #include <vcl/gdimtf.hxx>
29 : #include <vcl/graph.h>
30 : #include <vcl/window.hxx>
31 : #include <vcl/graph.hxx>
32 : #include <vcl/metaact.hxx>
33 : #include <vcl/virdev.hxx>
34 : #include <vcl/cvtgrf.hxx>
35 : #include <vcl/bmpacc.hxx>
36 : #include <tools/tempfile.hxx>
37 : #include <osl/process.h>
38 : #include <osl/file.hxx>
39 :
40 : class FilterConfigItem;
41 :
42 : /*************************************************************************
43 : |*
44 : |* ImpSearchEntry()
45 : |*
46 : |* Description Checks if there is a string(pDest) of length nSize
47 : |* inside the memory area pSource which is nComp bytes long.
48 : |* Check is NON-CASE-SENSITIVE. The return value ist the
49 : |* address where the string is found or NULL
50 : |*
51 : *************************************************************************/
52 :
53 0 : static sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize )
54 : {
55 0 : while ( nComp-- >= nSize )
56 : {
57 : sal_uLong i;
58 0 : for ( i = 0; i < nSize; i++ )
59 : {
60 0 : if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
61 0 : break;
62 : }
63 0 : if ( i == nSize )
64 0 : return pSource;
65 0 : pSource++;
66 : }
67 0 : return NULL;
68 : }
69 :
70 : //--------------------------------------------------------------------------
71 : // SecurityCount is the buffersize of the buffer in which we will parse for a number
72 0 : static long ImplGetNumber( sal_uInt8 **pBuf, int& nSecurityCount )
73 : {
74 0 : sal_Bool bValid = sal_True;
75 0 : sal_Bool bNegative = sal_False;
76 0 : long nRetValue = 0;
77 0 : while ( ( --nSecurityCount ) && ( ( **pBuf == ' ' ) || ( **pBuf == 0x9 ) ) )
78 0 : (*pBuf)++;
79 0 : sal_uInt8 nByte = **pBuf;
80 0 : while ( nSecurityCount && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
81 : {
82 0 : switch ( nByte )
83 : {
84 : case '.' :
85 : // we'll only use the integer format
86 0 : bValid = sal_False;
87 0 : break;
88 : case '-' :
89 0 : bNegative = sal_True;
90 0 : break;
91 : default :
92 0 : if ( ( nByte < '0' ) || ( nByte > '9' ) )
93 0 : nSecurityCount = 1; // error parsing the bounding box values
94 0 : else if ( bValid )
95 : {
96 0 : nRetValue *= 10;
97 0 : nRetValue += nByte - '0';
98 : }
99 0 : break;
100 : }
101 0 : nSecurityCount--;
102 0 : nByte = *(++(*pBuf));
103 : }
104 0 : if ( bNegative )
105 0 : nRetValue = -nRetValue;
106 0 : return nRetValue;
107 : }
108 :
109 : //--------------------------------------------------------------------------
110 :
111 0 : static int ImplGetLen( sal_uInt8* pBuf, int nMax )
112 : {
113 0 : int nLen = 0;
114 0 : while( nLen != nMax )
115 : {
116 0 : sal_uInt8 nDat = *pBuf++;
117 0 : if ( nDat == 0x0a || nDat == 0x25 )
118 : break;
119 0 : nLen++;
120 : }
121 0 : return nLen;
122 : }
123 :
124 0 : static void MakeAsMeta(Graphic &rGraphic)
125 : {
126 0 : VirtualDevice aVDev;
127 0 : GDIMetaFile aMtf;
128 0 : Bitmap aBmp( rGraphic.GetBitmap() );
129 0 : Size aSize = aBmp.GetPrefSize();
130 :
131 0 : if( !aSize.Width() || !aSize.Height() )
132 : aSize = Application::GetDefaultDevice()->PixelToLogic(
133 0 : aBmp.GetSizePixel(), MAP_100TH_MM );
134 : else
135 0 : aSize = Application::GetDefaultDevice()->LogicToLogic( aSize,
136 0 : aBmp.GetPrefMapMode(), MAP_100TH_MM );
137 :
138 0 : aVDev.EnableOutput( sal_False );
139 0 : aMtf.Record( &aVDev );
140 0 : aVDev.DrawBitmap( Point(), aSize, rGraphic.GetBitmap() );
141 0 : aMtf.Stop();
142 0 : aMtf.WindStart();
143 0 : aMtf.SetPrefMapMode( MAP_100TH_MM );
144 0 : aMtf.SetPrefSize( aSize );
145 0 : rGraphic = aMtf;
146 0 : }
147 :
148 0 : static oslProcessError runProcessWithPathSearch(const OUString &rProgName,
149 : rtl_uString* pArgs[], sal_uInt32 nArgs, oslProcess *pProcess,
150 : oslFileHandle *pIn, oslFileHandle *pOut, oslFileHandle *pErr)
151 : {
152 : #ifdef WNT
153 : /*
154 : * ooo#72096
155 : * On Window the underlying SearchPath searches in order of...
156 : * The directory from which the application loaded.
157 : * The current directory.
158 : * The Windows system directory.
159 : * The Windows directory.
160 : * The directories that are listed in the PATH environment variable.
161 : *
162 : * Because one of our programs is called "convert" and there is a convert
163 : * in the windows system directory, we want to explicitly search the PATH
164 : * to avoid picking up on that one if ImageMagick's convert preceeds it in
165 : * PATH.
166 : *
167 : */
168 : OUString url;
169 : OUString path(reinterpret_cast<const sal_Unicode*>(_wgetenv(L"PATH")));
170 :
171 : oslFileError err = osl_searchFileURL(rProgName.pData, path.pData, &url.pData);
172 : if (err != osl_File_E_None)
173 : return osl_Process_E_NotFound;
174 : return osl_executeProcess_WithRedirectedIO(url.pData,
175 : pArgs, nArgs, osl_Process_HIDDEN,
176 : osl_getCurrentSecurity(), 0, 0, 0, pProcess, pIn, pOut, pErr);
177 : #else
178 : return osl_executeProcess_WithRedirectedIO(rProgName.pData,
179 : pArgs, nArgs, osl_Process_SEARCHPATH | osl_Process_HIDDEN,
180 0 : osl_getCurrentSecurity(), 0, 0, 0, pProcess, pIn, pOut, pErr);
181 : #endif
182 : }
183 :
184 : #if defined(WNT)
185 : # define EXESUFFIX ".exe"
186 : #else
187 : # define EXESUFFIX ""
188 : #endif
189 :
190 0 : static bool RenderAsEMF(const sal_uInt8* pBuf, sal_uInt32 nBytesRead, Graphic &rGraphic)
191 : {
192 0 : TempFile aTemp;
193 0 : aTemp.EnableKillingFile();
194 0 : OUString fileName("pstoedit" EXESUFFIX);
195 0 : OUString arg1("-f");
196 0 : OUString arg2("emf:-OO");
197 0 : OUString arg3("-");
198 0 : OUString output;
199 0 : osl::FileBase::getSystemPathFromFileURL(aTemp.GetName(), output);
200 : rtl_uString *args[] =
201 : {
202 : arg1.pData, arg2.pData, arg3.pData, output.pData
203 0 : };
204 : oslProcess aProcess;
205 0 : oslFileHandle pIn = NULL;
206 0 : oslFileHandle pOut = NULL;
207 0 : oslFileHandle pErr = NULL;
208 : oslProcessError eErr = runProcessWithPathSearch(fileName,
209 0 : args, sizeof(args)/sizeof(rtl_uString *),
210 0 : &aProcess, &pIn, &pOut, &pErr);
211 :
212 0 : if (eErr!=osl_Process_E_None)
213 0 : return false;
214 :
215 0 : bool bRet = false;
216 : sal_uInt64 nCount;
217 0 : osl_writeFile(pIn, pBuf, nBytesRead, &nCount);
218 0 : if (pIn) osl_closeFile(pIn);
219 0 : bool bEMFSupported=true;
220 0 : if (pOut)
221 : {
222 0 : rtl::ByteSequence seq;
223 0 : if (osl_File_E_None == osl_readLine(pOut, (sal_Sequence **)&seq))
224 : {
225 0 : OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() );
226 0 : if (line.indexOf(OString("Unsupported output format")) == 0)
227 0 : bEMFSupported=false;
228 : }
229 0 : osl_closeFile(pOut);
230 : }
231 0 : if (pErr) osl_closeFile(pErr);
232 0 : if (nCount == nBytesRead && bEMFSupported)
233 : {
234 0 : SvFileStream aFile(output, STREAM_READ);
235 0 : if (GraphicConverter::Import(aFile, rGraphic, CVT_EMF) == ERRCODE_NONE)
236 0 : bRet = true;
237 : }
238 0 : osl_joinProcess(aProcess);
239 0 : osl_freeProcessHandle(aProcess);
240 0 : return bRet;
241 : }
242 :
243 0 : static bool RenderAsPNGThroughHelper(const sal_uInt8* pBuf, sal_uInt32 nBytesRead,
244 : Graphic &rGraphic, OUString &rProgName, rtl_uString *pArgs[], size_t nArgs)
245 : {
246 : oslProcess aProcess;
247 0 : oslFileHandle pIn = NULL;
248 0 : oslFileHandle pOut = NULL;
249 0 : oslFileHandle pErr = NULL;
250 : oslProcessError eErr = runProcessWithPathSearch(rProgName,
251 : pArgs, nArgs,
252 0 : &aProcess, &pIn, &pOut, &pErr);
253 0 : if (eErr!=osl_Process_E_None)
254 0 : return false;
255 :
256 0 : bool bRet = false;
257 : sal_uInt64 nCount;
258 0 : osl_writeFile(pIn, pBuf, nBytesRead, &nCount);
259 0 : if (pIn) osl_closeFile(pIn);
260 0 : if (nCount == nBytesRead)
261 : {
262 0 : SvMemoryStream aMemStm;
263 : sal_uInt8 aBuf[32000];
264 0 : oslFileError eFileErr = osl_readFile(pOut, aBuf, 32000, &nCount);
265 0 : while (eFileErr == osl_File_E_None && nCount)
266 : {
267 0 : aMemStm.Write(aBuf, sal::static_int_cast< sal_Size >(nCount));
268 0 : eFileErr = osl_readFile(pOut, aBuf, 32000, &nCount);
269 : }
270 :
271 0 : aMemStm.Seek(0);
272 0 : if (
273 0 : aMemStm.GetEndOfData() &&
274 0 : GraphicConverter::Import(aMemStm, rGraphic, CVT_PNG) == ERRCODE_NONE
275 : )
276 : {
277 0 : MakeAsMeta(rGraphic);
278 0 : bRet = true;
279 0 : }
280 : }
281 0 : if (pOut) osl_closeFile(pOut);
282 0 : if (pErr) osl_closeFile(pErr);
283 0 : osl_joinProcess(aProcess);
284 0 : osl_freeProcessHandle(aProcess);
285 0 : return bRet;
286 : }
287 :
288 0 : static bool RenderAsPNGThroughConvert(const sal_uInt8* pBuf, sal_uInt32 nBytesRead,
289 : Graphic &rGraphic)
290 : {
291 0 : OUString fileName("convert" EXESUFFIX);
292 : // density in pixel/inch
293 0 : OUString arg1("-density");
294 : // since the preview is also used for PDF-Export & printing on non-PS-printers,
295 : // use some better quality - 300x300 should allow some resizing as well
296 0 : OUString arg2("300x300");
297 : // read eps from STDIN
298 0 : OUString arg3("eps:-");
299 : // write png to STDOUT
300 0 : OUString arg4("png:-");
301 : rtl_uString *args[] =
302 : {
303 : arg1.pData, arg2.pData, arg3.pData, arg4.pData
304 0 : };
305 : return RenderAsPNGThroughHelper(pBuf, nBytesRead, rGraphic, fileName, args,
306 0 : sizeof(args)/sizeof(rtl_uString *));
307 : }
308 :
309 0 : static bool RenderAsPNGThroughGS(const sal_uInt8* pBuf, sal_uInt32 nBytesRead,
310 : Graphic &rGraphic)
311 : {
312 : #ifdef WNT
313 : OUString fileName("gswin32c" EXESUFFIX);
314 : #else
315 0 : OUString fileName("gs" EXESUFFIX);
316 : #endif
317 0 : OUString arg1("-q");
318 0 : OUString arg2("-dBATCH");
319 0 : OUString arg3("-dNOPAUSE");
320 0 : OUString arg4("-dPARANOIDSAFER");
321 0 : OUString arg5("-dEPSCrop");
322 0 : OUString arg6("-dTextAlphaBits=4");
323 0 : OUString arg7("-dGraphicsAlphaBits=4");
324 0 : OUString arg8("-r300x300");
325 0 : OUString arg9("-sDEVICE=png256");
326 0 : OUString arg10("-sOutputFile=-");
327 0 : OUString arg11("-");
328 : rtl_uString *args[] =
329 : {
330 : arg1.pData, arg2.pData, arg3.pData, arg4.pData, arg5.pData,
331 : arg6.pData, arg7.pData, arg8.pData, arg9.pData, arg10.pData,
332 : arg11.pData
333 0 : };
334 : return RenderAsPNGThroughHelper(pBuf, nBytesRead, rGraphic, fileName, args,
335 0 : sizeof(args)/sizeof(rtl_uString *));
336 : }
337 :
338 0 : static bool RenderAsPNG(const sal_uInt8* pBuf, sal_uInt32 nBytesRead, Graphic &rGraphic)
339 : {
340 0 : if (RenderAsPNGThroughConvert(pBuf, nBytesRead, rGraphic))
341 0 : return true;
342 : else
343 0 : return RenderAsPNGThroughGS(pBuf, nBytesRead, rGraphic);
344 : }
345 :
346 : // this method adds a replacement action containing the original wmf or tiff replacement,
347 : // so the original eps can be written when storing to ODF.
348 0 : void CreateMtfReplacementAction( GDIMetaFile& rMtf, SvStream& rStrm, sal_uInt32 nOrigPos, sal_uInt32 nPSSize,
349 : sal_uInt32 nPosWMF, sal_uInt32 nSizeWMF, sal_uInt32 nPosTIFF, sal_uInt32 nSizeTIFF )
350 : {
351 0 : OString aComment("EPSReplacementGraphic");
352 0 : if ( nSizeWMF || nSizeTIFF )
353 : {
354 0 : SvMemoryStream aReplacement( nSizeWMF + nSizeTIFF + 28 );
355 0 : sal_uInt32 nMagic = 0xc6d3d0c5;
356 0 : sal_uInt32 nPPos = 28 + nSizeWMF + nSizeTIFF;
357 0 : sal_uInt32 nWPos = nSizeWMF ? 28 : 0;
358 0 : sal_uInt32 nTPos = nSizeTIFF ? 28 + nSizeWMF : 0;
359 :
360 0 : aReplacement << nMagic << nPPos << nPSSize
361 0 : << nWPos << nSizeWMF
362 0 : << nTPos << nSizeTIFF;
363 0 : if ( nSizeWMF )
364 : {
365 0 : sal_uInt8* pBuf = new sal_uInt8[ nSizeWMF ];
366 0 : rStrm.Seek( nOrigPos + nPosWMF );
367 0 : rStrm.Read( pBuf, nSizeWMF );
368 0 : aReplacement.Write( pBuf, nSizeWMF );
369 0 : delete[] pBuf;
370 : }
371 0 : if ( nSizeTIFF )
372 : {
373 0 : sal_uInt8* pBuf = new sal_uInt8[ nSizeTIFF ];
374 0 : rStrm.Seek( nOrigPos + nPosTIFF );
375 0 : rStrm.Read( pBuf, nSizeTIFF );
376 0 : aReplacement.Write( pBuf, nSizeTIFF );
377 0 : delete[] pBuf;
378 : }
379 0 : rMtf.AddAction( (MetaAction*)( new MetaCommentAction( aComment, 0, (const sal_uInt8*)aReplacement.GetData(), aReplacement.Tell() ) ) );
380 : }
381 : else
382 0 : rMtf.AddAction( (MetaAction*)( new MetaCommentAction( aComment, 0, NULL, 0 ) ) );
383 0 : }
384 :
385 : //there is no preview -> make a red box
386 0 : void MakePreview(sal_uInt8* pBuf, sal_uInt32 nBytesRead,
387 : long nWidth, long nHeight, Graphic &rGraphic)
388 : {
389 0 : GDIMetaFile aMtf;
390 0 : VirtualDevice aVDev;
391 0 : Font aFont;
392 :
393 0 : aVDev.EnableOutput( sal_False );
394 0 : aMtf.Record( &aVDev );
395 0 : aVDev.SetLineColor( Color( COL_RED ) );
396 0 : aVDev.SetFillColor();
397 :
398 0 : aFont.SetColor( COL_LIGHTRED );
399 : // aFont.SetSize( Size( 0, 32 ) );
400 :
401 0 : aVDev.Push( PUSH_FONT );
402 0 : aVDev.SetFont( aFont );
403 :
404 0 : Rectangle aRect( Point( 1, 1 ), Size( nWidth - 2, nHeight - 2 ) );
405 0 : aVDev.DrawRect( aRect );
406 :
407 0 : OUString aString;
408 : int nLen;
409 0 : sal_uInt8* pDest = ImplSearchEntry( pBuf, (sal_uInt8*)"%%Title:", nBytesRead - 32, 8 );
410 0 : if ( pDest )
411 : {
412 0 : pDest += 8;
413 0 : if ( *pDest == ' ' )
414 0 : pDest++;
415 0 : nLen = ImplGetLen( pDest, 32 );
416 0 : sal_uInt8 aOldValue(pDest[ nLen ]); pDest[ nLen ] = 0;
417 0 : if ( strcmp( (const char*)pDest, "none" ) != 0 )
418 : {
419 0 : aString += " Title:" + OUString::createFromAscii( (char*)pDest ) + "\n";
420 : }
421 0 : pDest[ nLen ] = aOldValue;
422 : }
423 0 : pDest = ImplSearchEntry( pBuf, (sal_uInt8*)"%%Creator:", nBytesRead - 32, 10 );
424 0 : if ( pDest )
425 : {
426 0 : pDest += 10;
427 0 : if ( *pDest == ' ' )
428 0 : pDest++;
429 0 : nLen = ImplGetLen( pDest, 32 );
430 0 : sal_uInt8 aOldValue(pDest[ nLen ]); pDest[ nLen ] = 0;
431 0 : aString += " Creator:" + OUString::createFromAscii( (char*)pDest ) + "\n";
432 0 : pDest[ nLen ] = aOldValue;
433 : }
434 0 : pDest = ImplSearchEntry( pBuf, (sal_uInt8*)"%%CreationDate:", nBytesRead - 32, 15 );
435 0 : if ( pDest )
436 : {
437 0 : pDest += 15;
438 0 : if ( *pDest == ' ' )
439 0 : pDest++;
440 0 : nLen = ImplGetLen( pDest, 32 );
441 0 : sal_uInt8 aOldValue(pDest[ nLen ]); pDest[ nLen ] = 0;
442 0 : if ( strcmp( (const char*)pDest, "none" ) != 0 )
443 : {
444 0 : aString += " CreationDate:" + OUString::createFromAscii( (char*)pDest ) + "\n";
445 : }
446 0 : pDest[ nLen ] = aOldValue;
447 : }
448 0 : pDest = ImplSearchEntry( pBuf, (sal_uInt8*)"%%LanguageLevel:", nBytesRead - 4, 16 );
449 0 : if ( pDest )
450 : {
451 0 : pDest += 16;
452 0 : int nCount = 4;
453 0 : long nNumber = ImplGetNumber( &pDest, nCount );
454 0 : if ( nCount && ( (sal_uInt32)nNumber < 10 ) )
455 : {
456 0 : aString += " LanguageLevel:" + OUString::valueOf( nNumber );
457 : }
458 : }
459 0 : aVDev.DrawText( aRect, aString, TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE );
460 0 : aVDev.Pop();
461 0 : aMtf.Stop();
462 0 : aMtf.WindStart();
463 0 : aMtf.SetPrefMapMode( MAP_POINT );
464 0 : aMtf.SetPrefSize( Size( nWidth, nHeight ) );
465 0 : rGraphic = aMtf;
466 0 : }
467 :
468 :
469 : //================== GraphicImport - the exported function ================
470 :
471 : #if defined(DISABLE_DYNLOADING) || defined(LIBO_MERGELIBS)
472 : #define GraphicImport ipsGraphicImport
473 : #endif
474 :
475 : extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
476 0 : GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool)
477 : {
478 0 : if ( rStream.GetError() )
479 0 : return sal_False;
480 :
481 0 : Graphic aGraphic;
482 0 : sal_Bool bRetValue = sal_False;
483 0 : sal_Bool bHasPreview = sal_False;
484 0 : sal_Bool bGraphicLinkCreated = sal_False;
485 : sal_uInt32 nSignature, nPSStreamPos, nPSSize;
486 0 : sal_uInt32 nSizeWMF = 0;
487 0 : sal_uInt32 nPosWMF = 0;
488 0 : sal_uInt32 nSizeTIFF = 0;
489 0 : sal_uInt32 nPosTIFF = 0;
490 0 : sal_uInt32 nOrigPos = nPSStreamPos = rStream.Tell();
491 0 : sal_uInt16 nOldFormat = rStream.GetNumberFormatInt();
492 0 : rStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
493 0 : rStream >> nSignature;
494 0 : if ( nSignature == 0xc6d3d0c5 )
495 : {
496 0 : rStream >> nPSStreamPos >> nPSSize >> nPosWMF >> nSizeWMF;
497 :
498 : // first we try to get the metafile grafix
499 :
500 0 : if ( nSizeWMF )
501 : {
502 0 : if ( nPosWMF != 0 )
503 : {
504 0 : rStream.Seek( nOrigPos + nPosWMF );
505 0 : if ( GraphicConverter::Import( rStream, aGraphic, CVT_WMF ) == ERRCODE_NONE )
506 0 : bHasPreview = bRetValue = sal_True;
507 : }
508 : }
509 : else
510 : {
511 0 : rStream >> nPosTIFF >> nSizeTIFF;
512 :
513 : // else we have to get the tiff grafix
514 :
515 0 : if ( nPosTIFF && nSizeTIFF )
516 : {
517 0 : rStream.Seek( nOrigPos + nPosTIFF );
518 0 : if ( GraphicConverter::Import( rStream, aGraphic, CVT_TIF ) == ERRCODE_NONE )
519 : {
520 0 : MakeAsMeta(aGraphic);
521 0 : rStream.Seek( nOrigPos + nPosTIFF );
522 0 : bHasPreview = bRetValue = sal_True;
523 : }
524 : }
525 : }
526 : }
527 : else
528 : {
529 0 : nPSStreamPos = nOrigPos; // no preview available _>so we must get the size manually
530 0 : nPSSize = rStream.Seek( STREAM_SEEK_TO_END ) - nOrigPos;
531 : }
532 0 : sal_uInt8* pHeader = new sal_uInt8[ 22 ];
533 0 : rStream.Seek( nPSStreamPos );
534 0 : rStream.Read( pHeader, 22 ); // check PostScript header
535 0 : if ( ImplSearchEntry( pHeader, (sal_uInt8*)"%!PS-Adobe", 10, 10 ) &&
536 0 : ImplSearchEntry( &pHeader[ 15 ], (sal_uInt8*)"EPS", 3, 3 ) )
537 : {
538 0 : rStream.Seek( nPSStreamPos );
539 0 : sal_uInt8* pBuf = new sal_uInt8[ nPSSize ];
540 0 : if ( pBuf )
541 : {
542 0 : sal_uInt32 nBufStartPos = rStream.Tell();
543 0 : sal_uInt32 nBytesRead = rStream.Read( pBuf, nPSSize );
544 0 : if ( nBytesRead == nPSSize )
545 : {
546 0 : int nSecurityCount = 32;
547 0 : if ( !bHasPreview ) // if there is no tiff/wmf preview, we will parse for an preview in the eps prolog
548 : {
549 0 : sal_uInt8* pDest = ImplSearchEntry( pBuf, (sal_uInt8*)"%%BeginPreview:", nBytesRead - 32, 15 );
550 0 : if ( pDest )
551 : {
552 0 : pDest += 15;
553 0 : long nWidth = ImplGetNumber( &pDest, nSecurityCount );
554 0 : long nHeight = ImplGetNumber( &pDest, nSecurityCount );
555 0 : long nBitDepth = ImplGetNumber( &pDest, nSecurityCount );
556 0 : long nScanLines = ImplGetNumber( &pDest, nSecurityCount );
557 0 : pDest = ImplSearchEntry( pDest, (sal_uInt8*)"%", 16, 1 ); // go to the first Scanline
558 0 : if ( nSecurityCount && pDest && nWidth && nHeight && ( ( nBitDepth == 1 ) || ( nBitDepth == 8 ) ) && nScanLines )
559 : {
560 0 : rStream.Seek( nBufStartPos + ( pDest - pBuf ) );
561 :
562 0 : Bitmap aBitmap( Size( nWidth, nHeight ), 1 );
563 0 : BitmapWriteAccess* pAcc = aBitmap.AcquireWriteAccess();
564 0 : if ( pAcc )
565 : {
566 : int nBitsLeft;
567 0 : sal_Bool bIsValid = sal_True;
568 0 : sal_uInt8 nDat = 0;
569 : char nByte;
570 0 : for ( long y = 0; bIsValid && ( y < nHeight ); y++ )
571 : {
572 0 : nBitsLeft = 0;
573 0 : for ( long x = 0; x < nWidth; x++ )
574 : {
575 0 : if ( --nBitsLeft < 0 )
576 : {
577 0 : while ( bIsValid && ( nBitsLeft != 7 ) )
578 : {
579 0 : rStream >> nByte;
580 0 : switch ( nByte )
581 : {
582 : case 0x0a :
583 0 : if ( --nScanLines < 0 )
584 0 : bIsValid = sal_False;
585 : case 0x09 :
586 : case 0x0d :
587 : case 0x20 :
588 : case 0x25 :
589 0 : break;
590 : default:
591 : {
592 0 : if ( nByte >= '0' )
593 : {
594 0 : if ( nByte > '9' )
595 : {
596 0 : nByte &=~0x20; // case none sensitive for hexadezimal values
597 0 : nByte -= ( 'A' - 10 );
598 0 : if ( nByte > 15 )
599 0 : bIsValid = sal_False;
600 : }
601 : else
602 0 : nByte -= '0';
603 0 : nBitsLeft += 4;
604 0 : nDat <<= 4;
605 0 : nDat |= ( nByte ^ 0xf ); // in epsi a zero bit represents white color
606 : }
607 : else
608 0 : bIsValid = sal_False;
609 : }
610 0 : break;
611 : }
612 : }
613 : }
614 0 : if ( nBitDepth == 1 )
615 0 : pAcc->SetPixelIndex( y, x, static_cast<sal_uInt8>(nDat >> nBitsLeft) & 1 );
616 : else
617 : {
618 0 : pAcc->SetPixelIndex( y, x, nDat ? 1 : 0 ); // nBitDepth == 8
619 0 : nBitsLeft = 0;
620 : }
621 : }
622 : }
623 0 : if ( bIsValid )
624 : {
625 0 : VirtualDevice aVDev;
626 0 : GDIMetaFile aMtf;
627 0 : Size aSize;
628 0 : aVDev.EnableOutput( sal_False );
629 0 : aMtf.Record( &aVDev );
630 0 : aSize = aBitmap.GetPrefSize();
631 0 : if( !aSize.Width() || !aSize.Height() )
632 0 : aSize = Application::GetDefaultDevice()->PixelToLogic( aBitmap.GetSizePixel(), MAP_100TH_MM );
633 : else
634 0 : aSize = Application::GetDefaultDevice()->LogicToLogic( aSize, aBitmap.GetPrefMapMode(), MAP_100TH_MM );
635 0 : aVDev.DrawBitmap( Point(), aSize, aBitmap );
636 0 : aMtf.Stop();
637 0 : aMtf.WindStart();
638 0 : aMtf.SetPrefMapMode( MAP_100TH_MM );
639 0 : aMtf.SetPrefSize( aSize );
640 0 : aGraphic = aMtf;
641 0 : bHasPreview = bRetValue = sal_True;
642 : }
643 0 : aBitmap.ReleaseAccess( pAcc );
644 0 : }
645 : }
646 : }
647 : }
648 :
649 0 : sal_uInt8* pDest = ImplSearchEntry( pBuf, (sal_uInt8*)"%%BoundingBox:", nBytesRead, 14 );
650 0 : if ( pDest )
651 : {
652 0 : nSecurityCount = 100;
653 : long nNumb[4];
654 0 : nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
655 0 : pDest += 14;
656 0 : for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
657 : {
658 0 : nNumb[ i ] = ImplGetNumber( &pDest, nSecurityCount );
659 : }
660 0 : if ( nSecurityCount)
661 : {
662 0 : bGraphicLinkCreated = sal_True;
663 0 : GfxLink aGfxLink( pBuf, nPSSize, GFX_LINK_TYPE_EPS_BUFFER, sal_True ) ;
664 0 : GDIMetaFile aMtf;
665 :
666 0 : long nWidth = nNumb[2] - nNumb[0] + 1;
667 0 : long nHeight = nNumb[3] - nNumb[1] + 1;
668 :
669 : // if there is no preview -> try with gs to make one
670 0 : if( !bHasPreview )
671 : {
672 0 : bHasPreview = RenderAsEMF(pBuf, nBytesRead, aGraphic);
673 0 : if (!bHasPreview)
674 0 : bHasPreview = RenderAsPNG(pBuf, nBytesRead, aGraphic);
675 : }
676 :
677 : // if there is no preview -> make a red box
678 0 : if( !bHasPreview )
679 : {
680 : MakePreview(pBuf, nBytesRead, nWidth, nHeight,
681 0 : aGraphic);
682 : }
683 :
684 : aMtf.AddAction( (MetaAction*)( new MetaEPSAction( Point(), Size( nWidth, nHeight ),
685 0 : aGfxLink, aGraphic.GetGDIMetaFile() ) ) );
686 0 : CreateMtfReplacementAction( aMtf, rStream, nOrigPos, nPSSize, nPosWMF, nSizeWMF, nPosTIFF, nSizeTIFF );
687 0 : aMtf.WindStart();
688 0 : aMtf.SetPrefMapMode( MAP_POINT );
689 0 : aMtf.SetPrefSize( Size( nWidth, nHeight ) );
690 0 : rGraphic = aMtf;
691 0 : bRetValue = sal_True;
692 : }
693 : }
694 : }
695 : }
696 0 : if ( !bGraphicLinkCreated )
697 0 : delete[] pBuf;
698 : }
699 0 : delete[] pHeader;
700 0 : rStream.SetNumberFormatInt(nOldFormat);
701 0 : rStream.Seek( nOrigPos );
702 0 : return ( bRetValue );
703 0 : }
704 :
705 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|