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