update credits
[LibreOffice.git] / vcl / source / filter / graphicfilter.cxx
blobd354aca77794caf80ad42b04a11a43dede6fb87b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/mutex.hxx>
21 #include <comphelper/processfactory.hxx>
22 #include <comphelper/string.hxx>
23 #include <ucbhelper/content.hxx>
24 #include <cppuhelper/implbase1.hxx>
25 #include <tools/urlobj.hxx>
26 #include <vcl/salctype.hxx>
27 #include <vcl/pngread.hxx>
28 #include <vcl/pngwrite.hxx>
29 #include <vcl/svgdata.hxx>
30 #include <vcl/virdev.hxx>
31 #include <vcl/svapp.hxx>
32 #include <osl/file.hxx>
33 #include <vcl/graphicfilter.hxx>
34 #include <vcl/FilterConfigItem.hxx>
35 #include <vcl/wmf.hxx>
36 #include "igif/gifread.hxx"
37 #include "jpeg/jpeg.hxx"
38 #include "ixbm/xbmread.hxx"
39 #include "ixpm/xpmread.hxx"
40 #include "sgffilt.hxx"
41 #include "osl/module.hxx"
42 #include <com/sun/star/uno/Reference.h>
43 #include <com/sun/star/awt/Size.hpp>
44 #include <com/sun/star/uno/XInterface.hpp>
45 #include <com/sun/star/uno/XWeak.hpp>
46 #include <com/sun/star/uno/XAggregation.hpp>
47 #include <com/sun/star/lang/XTypeProvider.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/io/XActiveDataSource.hpp>
50 #include <com/sun/star/io/XOutputStream.hpp>
51 #include <com/sun/star/svg/XSVGWriter.hpp>
52 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
53 #include <com/sun/star/xml/sax/Writer.hpp>
54 #include <com/sun/star/ucb/CommandAbortedException.hpp>
55 #include <unotools/ucbstreamhelper.hxx>
56 #include <unotools/localfilehelper.hxx>
57 #include <rtl/bootstrap.hxx>
58 #include <rtl/instance.hxx>
59 #include <rtl/logfile.hxx>
60 #include <vcl/metaact.hxx>
61 #include <vector>
63 #include "FilterConfigCache.hxx"
65 #define PMGCHUNG_msOG 0x6d734f47 // Microsoft Office Animated GIF
67 #ifndef DISABLE_DYNLOADING
68 #define IMPORT_FUNCTION_NAME "GraphicImport"
69 #define EXPORT_FUNCTION_NAME "GraphicExport"
70 #endif
72 using namespace ::rtl;
73 using namespace ::com::sun::star;
75 using comphelper::string::getTokenCount;
76 using comphelper::string::getToken;
78 typedef ::std::vector< GraphicFilter* > FilterList_impl;
79 static FilterList_impl* pFilterHdlList = NULL;
81 static ::osl::Mutex& getListMutex()
83 static ::osl::Mutex s_aListProtection;
84 return s_aListProtection;
87 class ImpFilterOutputStream : public ::cppu::WeakImplHelper1< css::io::XOutputStream >
89 protected:
91 SvStream& mrStm;
93 virtual void SAL_CALL writeBytes( const css::uno::Sequence< sal_Int8 >& rData )
94 throw (css::io::NotConnectedException, css::io::BufferSizeExceededException, css::io::IOException, css::uno::RuntimeException)
95 { mrStm.Write( rData.getConstArray(), rData.getLength() ); }
96 virtual void SAL_CALL flush()
97 throw (css::io::NotConnectedException, css::io::BufferSizeExceededException, css::io::IOException, css::uno::RuntimeException)
98 { mrStm.Flush(); }
99 virtual void SAL_CALL closeOutput() throw() {}
101 public:
103 ImpFilterOutputStream( SvStream& rStm ) : mrStm( rStm ) {}
104 ~ImpFilterOutputStream() {}
107 #ifndef DISABLE_EXPORT
109 static sal_Bool DirEntryExists( const INetURLObject& rObj )
111 sal_Bool bExists = sal_False;
115 ::ucbhelper::Content aCnt( rObj.GetMainURL( INetURLObject::NO_DECODE ),
116 css::uno::Reference< css::ucb::XCommandEnvironment >(),
117 comphelper::getProcessComponentContext() );
119 bExists = aCnt.isDocument();
121 catch(const css::ucb::CommandAbortedException&)
123 SAL_WARN( "svtools.filter", "CommandAbortedException" );
125 catch(const css::ucb::ContentCreationException&)
127 SAL_WARN( "svtools.filter", "ContentCreationException" );
129 catch( ... )
131 SAL_WARN( "svtools.filter", "Any other exception" );
133 return bExists;
136 static void KillDirEntry( const String& rMainUrl )
140 ::ucbhelper::Content aCnt( rMainUrl,
141 css::uno::Reference< css::ucb::XCommandEnvironment >(),
142 comphelper::getProcessComponentContext() );
144 aCnt.executeCommand( "delete",
145 css::uno::makeAny( sal_Bool( sal_True ) ) );
147 catch(const css::ucb::CommandAbortedException&)
149 SAL_WARN( "svtools.filter", "CommandAbortedException" );
151 catch( ... )
153 SAL_WARN( "svtools.filter", "Any other exception" );
157 #endif // !DISABLE_EXPORT
159 // Helper functions
161 sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize )
163 while ( nComp-- >= nSize )
165 sal_uLong i;
166 for ( i = 0; i < nSize; i++ )
168 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
169 break;
171 if ( i == nSize )
172 return pSource;
173 pSource++;
175 return NULL;
179 inline String ImpGetExtension( const String &rPath )
181 String aExt;
182 INetURLObject aURL( rPath );
183 aExt = aURL.GetFileExtension().toAsciiUpperCase();
184 return aExt;
187 bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
189 sal_uInt8 sBuf[3];
190 // store number format
191 sal_uInt16 oldNumberFormat = rStream.GetNumberFormatInt();
192 sal_uInt32 nOffset; // in MS documents the pict format is used without the first 512 bytes
193 for ( nOffset = 0; ( nOffset <= 512 ) && ( ( nStreamPos + nOffset + 14 ) <= nStreamLen ); nOffset += 512 )
195 short y1,x1,y2,x2;
196 sal_Bool bdBoxOk = sal_True;
198 rStream.Seek( nStreamPos + nOffset);
199 // size of the pict in version 1 pict ( 2bytes) : ignored
200 rStream.SeekRel(2);
201 // bounding box (bytes 2 -> 9)
202 rStream.SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
203 rStream >> y1 >> x1 >> y2 >> x2;
204 rStream.SetNumberFormatInt(oldNumberFormat); // reset format
206 if (x1 > x2 || y1 > y2 || // bad bdbox
207 (x1 == x2 && y1 == y2) || // 1 pixel picture
208 x2-x1 > 2048 || y2-y1 > 2048 ) // picture anormaly big
209 bdBoxOk = sal_False;
211 // read version op
212 rStream.Read( sBuf,3 );
213 // see http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Imaging_With_QuickDraw/Appendix_A.pdf
214 // normal version 2 - page A23 and A24
215 if ( sBuf[ 0 ] == 0x00 && sBuf[ 1 ] == 0x11 && sBuf[ 2 ] == 0x02)
216 return true;
217 // normal version 1 - page A25
218 else if (sBuf[ 0 ] == 0x11 && sBuf[ 1 ] == 0x01 && bdBoxOk)
219 return true;
221 return false;
225 /*************************************************************************
227 * ImpPeekGraphicFormat()
229 * Description:
230 * This function is two-fold:
231 * 1.) Start reading file, determine the file format:
232 * Input parameters:
233 * rPath - file path
234 * rFormatExtension - content matter
235 * bTest - set sal_False
236 * Output parameters:
237 * Return value - sal_True if success
238 * rFormatExtension - on success: normal file extension in capitals
239 * 2.) Start reading file, verify file format
240 * Input parameters:
241 * rPath - file path
242 * rFormatExtension - normal file extension in capitals
243 * bTest - set sal_True
244 * Output parameters:
245 * Return value - sal_False, if cannot verify the file type
246 * passed to the function
247 * sal_True, when the format is PROBABLY verified or
248 * WHEN THE FORMAT IS NOT KNOWN!
250 *************************************************************************/
252 static sal_Bool ImpPeekGraphicFormat( SvStream& rStream, String& rFormatExtension, sal_Bool bTest )
254 sal_uInt16 i;
255 sal_uInt8 sFirstBytes[ 256 ];
256 sal_uLong nFirstLong,nSecondLong;
257 sal_uLong nStreamPos = rStream.Tell();
259 rStream.Seek( STREAM_SEEK_TO_END );
260 sal_uLong nStreamLen = rStream.Tell() - nStreamPos;
261 rStream.Seek( nStreamPos );
263 if ( !nStreamLen )
265 SvLockBytes* pLockBytes = rStream.GetLockBytes();
266 if ( pLockBytes )
267 pLockBytes->SetSynchronMode( sal_True );
269 rStream.Seek( STREAM_SEEK_TO_END );
270 nStreamLen = rStream.Tell() - nStreamPos;
271 rStream.Seek( nStreamPos );
273 if (!nStreamLen)
275 return false; // this prevents at least a STL assertion
277 else if (nStreamLen >= 256)
278 { // load first 256 bytes into a buffer
279 rStream.Read( sFirstBytes, 256 );
281 else
283 rStream.Read( sFirstBytes, nStreamLen );
285 for( i = (sal_uInt16) nStreamLen; i < 256; i++ )
286 sFirstBytes[ i ]=0;
289 if( rStream.GetError() )
290 return sal_False;
292 // Accommodate the first 8 bytes in nFirstLong, nSecondLong
293 // Big-Endian:
294 for( i = 0, nFirstLong = 0L, nSecondLong = 0L; i < 4; i++ )
296 nFirstLong=(nFirstLong<<8)|(sal_uLong)sFirstBytes[i];
297 nSecondLong=(nSecondLong<<8)|(sal_uLong)sFirstBytes[i+4];
300 // The following variable is used when bTest == sal_True. It remains sal_False
301 // if the format (rFormatExtension) has not yet been set.
302 sal_Bool bSomethingTested = sal_False;
304 // Now the different formats are checked. The order *does* matter. e.g. a MET file
305 // could also go through the BMP test, howeve a BMP file can hardly go through the MET test.
306 // So MET should be tested prior to BMP. However, theoretically a BMP file could conceivably
307 // go through the MET test. These problems are of course not only in MET and BMP.
308 // Therefore, in the case of a format check (bTest == sal_True) we only test *exactly* this
309 // format. Everything else could have fatal consequences, for example if the user says it is
310 // a BMP file (and it is a BMP) file, and the file would go through the MET test ...
311 //--------------------------- MET ------------------------------------
312 if( !bTest || ( rFormatExtension.CompareToAscii( "MET", 3 ) == COMPARE_EQUAL ) )
314 bSomethingTested=sal_True;
315 if( sFirstBytes[2] == 0xd3 )
317 rStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
318 rStream.Seek( nStreamPos );
319 sal_uInt16 nFieldSize;
320 sal_uInt8 nMagic;
321 sal_Bool bOK=sal_True;
322 rStream >> nFieldSize >> nMagic;
323 for (i=0; i<3; i++) {
324 if (nFieldSize<6) { bOK=sal_False; break; }
325 if (nStreamLen < rStream.Tell() + nFieldSize ) { bOK=sal_False; break; }
326 rStream.SeekRel(nFieldSize-3);
327 rStream >> nFieldSize >> nMagic;
328 if (nMagic!=0xd3) { bOK=sal_False; break; }
330 rStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
331 if (bOK && !rStream.GetError()) {
332 rFormatExtension = OUString("MET");
333 return sal_True;
338 //--------------------------- BMP ------------------------------------
339 if( !bTest || ( rFormatExtension.CompareToAscii( "BMP", 3 ) == COMPARE_EQUAL ) )
341 sal_uInt8 nOffs;
343 bSomethingTested=sal_True;
345 // We're possibly also able to read an OS/2 bitmap array
346 // ('BA'), therefore we must adjust the offset to discover the
347 // first bitmap in the array
348 if ( sFirstBytes[0] == 0x42 && sFirstBytes[1] == 0x41 )
349 nOffs = 14;
350 else
351 nOffs = 0;
353 // Now we initially test on 'BM'
354 if ( sFirstBytes[0+nOffs]==0x42 && sFirstBytes[1+nOffs]==0x4d )
357 // OS/2 can set the Reserved flags to a value other than 0
358 // (which they really should not do...);
359 // In this case we test the size of the BmpInfoHeaders
360 if ( ( sFirstBytes[6+nOffs]==0x00 &&
361 sFirstBytes[7+nOffs]==0x00 &&
362 sFirstBytes[8+nOffs]==0x00 &&
363 sFirstBytes[9+nOffs]==0x00 ) ||
364 sFirstBytes[14+nOffs] == 0x28 ||
365 sFirstBytes[14+nOffs] == 0x0c )
367 rFormatExtension = OUString("BMP");
368 return sal_True;
373 //--------------------------- WMF/EMF ------------------------------------
375 if( !bTest ||
376 ( rFormatExtension.CompareToAscii( "WMF", 3 ) == COMPARE_EQUAL ) ||
377 ( rFormatExtension.CompareToAscii( "EMF", 3 ) == COMPARE_EQUAL ) )
379 bSomethingTested = sal_True;
381 if ( nFirstLong==0xd7cdc69a || nFirstLong==0x01000900 )
383 rFormatExtension = OUString("WMF");
384 return sal_True;
386 else if( nFirstLong == 0x01000000 && sFirstBytes[ 40 ] == 0x20 && sFirstBytes[ 41 ] == 0x45 &&
387 sFirstBytes[ 42 ] == 0x4d && sFirstBytes[ 43 ] == 0x46 )
389 rFormatExtension = OUString("EMF");
390 return sal_True;
394 //--------------------------- PCX ------------------------------------
395 if( !bTest || ( rFormatExtension.CompareToAscii( "PCX", 3 ) == COMPARE_EQUAL ) )
397 bSomethingTested=sal_True;
398 if (sFirstBytes[0]==0x0a)
400 sal_uInt8 nVersion=sFirstBytes[1];
401 sal_uInt8 nEncoding=sFirstBytes[2];
402 if( ( nVersion==0 || nVersion==2 || nVersion==3 || nVersion==5 ) && nEncoding<=1 )
404 rFormatExtension = OUString("PCX");
405 return sal_True;
410 //--------------------------- TIF ------------------------------------
411 if( !bTest || ( rFormatExtension.CompareToAscii( "TIF", 3 ) == COMPARE_EQUAL ) )
413 bSomethingTested=sal_True;
414 if ( nFirstLong==0x49492a00 || nFirstLong==0x4d4d002a )
416 rFormatExtension = OUString("TIF");
417 return sal_True;
421 //--------------------------- GIF ------------------------------------
422 if( !bTest || ( rFormatExtension.CompareToAscii( "GIF", 3 ) == COMPARE_EQUAL ) )
424 bSomethingTested=sal_True;
425 if ( nFirstLong==0x47494638 && (sFirstBytes[4]==0x37 || sFirstBytes[4]==0x39) && sFirstBytes[5]==0x61 )
427 rFormatExtension = OUString("GIF");
428 return sal_True;
432 //--------------------------- PNG ------------------------------------
433 if( !bTest || ( rFormatExtension.CompareToAscii( "PNG", 3 ) == COMPARE_EQUAL ) )
435 bSomethingTested=sal_True;
436 if (nFirstLong==0x89504e47 && nSecondLong==0x0d0a1a0a)
438 rFormatExtension = OUString("PNG");
439 return sal_True;
443 //--------------------------- JPG ------------------------------------
444 if( !bTest || ( rFormatExtension.CompareToAscii( "JPG", 3 ) == COMPARE_EQUAL ) )
446 bSomethingTested=sal_True;
447 if ( ( nFirstLong==0xffd8ffe0 && sFirstBytes[6]==0x4a && sFirstBytes[7]==0x46 && sFirstBytes[8]==0x49 && sFirstBytes[9]==0x46 ) ||
448 ( nFirstLong==0xffd8fffe ) || ( 0xffd8ff00 == ( nFirstLong & 0xffffff00 ) ) )
450 rFormatExtension = OUString("JPG");
451 return sal_True;
455 //--------------------------- SVM ------------------------------------
456 if( !bTest || ( rFormatExtension.CompareToAscii( "SVM", 3 ) == COMPARE_EQUAL ) )
458 bSomethingTested=sal_True;
459 if( nFirstLong==0x53564744 && sFirstBytes[4]==0x49 )
461 rFormatExtension = OUString("SVM");
462 return sal_True;
464 else if( sFirstBytes[0]==0x56 && sFirstBytes[1]==0x43 && sFirstBytes[2]==0x4C &&
465 sFirstBytes[3]==0x4D && sFirstBytes[4]==0x54 && sFirstBytes[5]==0x46 )
467 rFormatExtension = OUString("SVM");
468 return sal_True;
472 //--------------------------- PCD ------------------------------------
473 if( !bTest || ( rFormatExtension.CompareToAscii( "PCD", 3 ) == COMPARE_EQUAL ) )
475 bSomethingTested = sal_True;
476 if( nStreamLen >= 2055 )
478 char sBuf[8];
479 rStream.Seek( nStreamPos + 2048 );
480 rStream.Read( sBuf, 7 );
482 if( strncmp( sBuf, "PCD_IPI", 7 ) == 0 )
484 rFormatExtension = OUString("PCD");
485 return sal_True;
490 //--------------------------- PSD ------------------------------------
491 if( !bTest || ( rFormatExtension.CompareToAscii( "PSD", 3 ) == COMPARE_EQUAL ) )
493 bSomethingTested = sal_True;
494 if ( ( nFirstLong == 0x38425053 ) && ( (nSecondLong >> 16 ) == 1 ) )
496 rFormatExtension = OUString("PSD");
497 return sal_True;
501 //--------------------------- EPS ------------------------------------
502 if( !bTest || ( rFormatExtension.CompareToAscii( "EPS", 3 ) == COMPARE_EQUAL ) )
504 bSomethingTested = sal_True;
505 if ( ( nFirstLong == 0xC5D0D3C6 ) || ( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"%!PS-Adobe", 10, 10 ) &&
506 ImplSearchEntry( &sFirstBytes[15], (sal_uInt8*)"EPS", 3, 3 ) ) )
508 rFormatExtension = OUString("EPS");
509 return sal_True;
513 //--------------------------- DXF ------------------------------------
514 if( !bTest || ( rFormatExtension.CompareToAscii( "DXF", 3 ) == COMPARE_EQUAL ) )
516 // Binary DXF File Format
517 if( strncmp( (const char*) sFirstBytes, "AutoCAD Binary DXF", 18 ) == 0 )
519 rFormatExtension = OUString("DXF");
520 return sal_True;
523 // ASCII DXF File Format
524 i=0;
525 while (i<256 && sFirstBytes[i]<=32)
526 ++i;
528 if (i<256 && sFirstBytes[i]=='0')
530 ++i;
532 // only now do we have sufficient data to make a judgement
533 // based on a '0' + 'SECTION' == DXF argument
534 bSomethingTested=sal_True;
536 while( i<256 && sFirstBytes[i]<=32 )
537 ++i;
539 if (i+7<256 && (strncmp((const char*)(sFirstBytes+i),"SECTION",7)==0))
541 rFormatExtension = OUString("DXF");
542 return sal_True;
548 //--------------------------- PCT ------------------------------------
549 if( !bTest || ( rFormatExtension.CompareToAscii( "PCT", 3 ) == COMPARE_EQUAL ) )
551 bSomethingTested = sal_True;
552 if (isPCT(rStream, nStreamPos, nStreamLen))
554 rFormatExtension = OUString("PCT");
555 return sal_True;
559 //------------------------- PBM + PGM + PPM ---------------------------
560 if( !bTest ||
561 ( rFormatExtension.CompareToAscii( "PBM", 3 ) == COMPARE_EQUAL ) ||
562 ( rFormatExtension.CompareToAscii( "PGM", 3 ) == COMPARE_EQUAL ) ||
563 ( rFormatExtension.CompareToAscii( "PPM", 3 ) == COMPARE_EQUAL ) )
565 bSomethingTested=sal_True;
566 if ( sFirstBytes[ 0 ] == 'P' )
568 switch( sFirstBytes[ 1 ] )
570 case '1' :
571 case '4' :
572 rFormatExtension = OUString("PBM");
573 return sal_True;
575 case '2' :
576 case '5' :
577 rFormatExtension = OUString("PGM");
578 return sal_True;
580 case '3' :
581 case '6' :
582 rFormatExtension = OUString("PPM");
583 return sal_True;
588 //--------------------------- RAS( SUN RasterFile )------------------
589 if( !bTest || ( rFormatExtension.CompareToAscii( "RAS", 3 ) == COMPARE_EQUAL ) )
591 bSomethingTested=sal_True;
592 if( nFirstLong == 0x59a66a95 )
594 rFormatExtension = OUString("RAS");
595 return sal_True;
599 //--------------------------- XPM ------------------------------------
600 if( !bTest )
602 bSomethingTested = sal_True;
603 if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"/* XPM */", 256, 9 ) )
605 rFormatExtension = OUString("XPM");
606 return sal_True;
609 else if( rFormatExtension.CompareToAscii( "XPM", 3 ) == COMPARE_EQUAL )
611 bSomethingTested = sal_True;
612 return sal_True;
615 //--------------------------- XBM ------------------------------------
616 if( !bTest )
618 sal_uLong nSize = ( nStreamLen > 2048 ) ? 2048 : nStreamLen;
619 sal_uInt8* pBuf = new sal_uInt8 [ nSize ];
621 rStream.Seek( nStreamPos );
622 rStream.Read( pBuf, nSize );
623 sal_uInt8* pPtr = ImplSearchEntry( pBuf, (sal_uInt8*)"#define", nSize, 7 );
625 if( pPtr )
627 if( ImplSearchEntry( pPtr, (sal_uInt8*)"_width", pBuf + nSize - pPtr, 6 ) )
629 rFormatExtension = OUString("XBM");
630 delete[] pBuf;
631 return sal_True;
634 delete[] pBuf;
636 else if( rFormatExtension.CompareToAscii( "XBM", 3 ) == COMPARE_EQUAL )
638 bSomethingTested = sal_True;
639 return sal_True;
642 //--------------------------- SVG ------------------------------------
643 if( !bTest )
645 // check for Xml
646 if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<?xml", 256, 5 ) // is it xml
647 && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"version", 256, 7 )) // does it have a version (required for xml)
649 bool bIsSvg(false);
651 // check for DOCTYPE svg combination
652 if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"DOCTYPE", 256, 7 ) // 'DOCTYPE' is there
653 && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"svg", 256, 3 )) // 'svg' is there
655 bIsSvg = true;
658 // check for svg element in 1st 256 bytes
659 if(!bIsSvg && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
661 bIsSvg = true;
664 if(!bIsSvg)
666 // it's a xml, look for '<svg' in full file. Should not happen too
667 // often since the tests above will handle most cases, but can happen
668 // with Svg files containing big comment headers or Svg as the host
669 // language
670 const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
671 sal_uInt8* pBuf = new sal_uInt8[nSize];
673 rStream.Seek(nStreamPos);
674 rStream.Read(pBuf, nSize);
676 if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
678 bIsSvg = true;
681 delete[] pBuf;
684 if(bIsSvg)
686 rFormatExtension = OUString( "SVG" );
687 return sal_True;
690 else
692 // #119176# SVG files which have no xml header at all have shown up,
693 // detect those, too
694 bool bIsSvg(false);
696 // check for svg element in 1st 256 bytes
697 if(ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
699 bIsSvg = true;
702 if(!bIsSvg)
704 // look for '<svg' in full file. Should not happen too
705 // often since the tests above will handle most cases, but can happen
706 // with SVG files containing big comment headers or SVG as the host
707 // language
708 const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
709 sal_uInt8* pBuf = new sal_uInt8[nSize];
711 rStream.Seek(nStreamPos);
712 rStream.Read(pBuf, nSize);
714 if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
716 bIsSvg = true;
719 delete[] pBuf;
722 if(bIsSvg)
724 rFormatExtension = OUString( "SVG" );
725 return sal_True;
729 else if( rFormatExtension.CompareToAscii( "SVG", 3 ) == COMPARE_EQUAL )
731 bSomethingTested = sal_True;
732 return sal_True;
735 //--------------------------- TGA ------------------------------------
736 if( !bTest || ( rFormatExtension.CompareToAscii( "TGA", 3 ) == COMPARE_EQUAL ) )
738 bSomethingTested = sal_True;
740 // just a simple test for the extension
741 if( rFormatExtension.CompareToAscii( "TGA", 3 ) == COMPARE_EQUAL )
742 return sal_True;
745 //--------------------------- SGV ------------------------------------
746 if( !bTest || ( rFormatExtension.CompareToAscii( "SGV", 3 ) == COMPARE_EQUAL ) )
748 bSomethingTested = sal_True;
750 // just a simple test for the extension
751 if( rFormatExtension.CompareToAscii( "SGV", 3 ) == COMPARE_EQUAL )
752 return sal_True;
755 //--------------------------- SGF ------------------------------------
756 if( !bTest || ( rFormatExtension.CompareToAscii( "SGF", 3 ) == COMPARE_EQUAL ) )
758 bSomethingTested=sal_True;
759 if( sFirstBytes[ 0 ] == 'J' && sFirstBytes[ 1 ] == 'J' )
761 rFormatExtension = OUString("SGF");
762 return sal_True;
766 return bTest && !bSomethingTested;
769 //--------------------------------------------------------------------------
771 sal_uInt16 GraphicFilter::ImpTestOrFindFormat( const String& rPath, SvStream& rStream, sal_uInt16& rFormat )
773 // determine or check the filter/format by reading into it
774 if( rFormat == GRFILTER_FORMAT_DONTKNOW )
776 String aFormatExt;
777 if( ImpPeekGraphicFormat( rStream, aFormatExt, sal_False ) )
779 rFormat = pConfig->GetImportFormatNumberForExtension( aFormatExt );
780 if( rFormat != GRFILTER_FORMAT_DONTKNOW )
781 return GRFILTER_OK;
783 // determine filter by file extension
784 if( rPath.Len() )
786 String aExt( ImpGetExtension( rPath ) );
787 rFormat = pConfig->GetImportFormatNumberForExtension( aExt );
788 if( rFormat != GRFILTER_FORMAT_DONTKNOW )
789 return GRFILTER_OK;
791 return GRFILTER_FORMATERROR;
793 else
795 String aTmpStr( pConfig->GetImportFormatExtension( rFormat ) );
796 if( !ImpPeekGraphicFormat( rStream, aTmpStr.ToUpperAscii(), sal_True ) )
797 return GRFILTER_FORMATERROR;
798 if ( pConfig->GetImportFormatExtension( rFormat ).EqualsIgnoreCaseAscii( "pcd" ) )
800 sal_Int32 nBase = 2; // default Base0
801 if ( pConfig->GetImportFilterType( rFormat ).EqualsIgnoreCaseAscii( "pcd_Photo_CD_Base4" ) )
802 nBase = 1;
803 else if ( pConfig->GetImportFilterType( rFormat ).EqualsIgnoreCaseAscii( "pcd_Photo_CD_Base16" ) )
804 nBase = 0;
805 String aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
806 FilterConfigItem aFilterConfigItem( aFilterConfigPath );
807 aFilterConfigItem.WriteInt32( "Resolution", nBase );
811 return GRFILTER_OK;
814 //--------------------------------------------------------------------------
816 #ifndef DISABLE_EXPORT
818 static Graphic ImpGetScaledGraphic( const Graphic& rGraphic, FilterConfigItem& rConfigItem )
820 Graphic aGraphic;
822 ResMgr* pResMgr = ResMgr::CreateResMgr( "svt", Application::GetSettings().GetUILanguageTag() );
824 sal_Int32 nLogicalWidth = rConfigItem.ReadInt32( "LogicalWidth", 0 );
825 sal_Int32 nLogicalHeight = rConfigItem.ReadInt32( "LogicalHeight", 0 );
827 if ( rGraphic.GetType() != GRAPHIC_NONE )
829 sal_Int32 nMode = rConfigItem.ReadInt32( "ExportMode", -1 );
831 if ( nMode == -1 ) // the property is not there, this is possible, if the graphic filter
832 { // is called via UnoGraphicExporter and not from a graphic export Dialog
833 nMode = 0; // then we are defaulting this mode to 0
834 if ( nLogicalWidth || nLogicalHeight )
835 nMode = 2;
839 Size aOriginalSize;
840 Size aPrefSize( rGraphic.GetPrefSize() );
841 MapMode aPrefMapMode( rGraphic.GetPrefMapMode() );
842 if ( aPrefMapMode == MAP_PIXEL )
843 aOriginalSize = Application::GetDefaultDevice()->PixelToLogic( aPrefSize, MAP_100TH_MM );
844 else
845 aOriginalSize = Application::GetDefaultDevice()->LogicToLogic( aPrefSize, aPrefMapMode, MAP_100TH_MM );
846 if ( !nLogicalWidth )
847 nLogicalWidth = aOriginalSize.Width();
848 if ( !nLogicalHeight )
849 nLogicalHeight = aOriginalSize.Height();
850 if( rGraphic.GetType() == GRAPHIC_BITMAP )
853 // Resolution is set
854 if( nMode == 1 )
856 Bitmap aBitmap( rGraphic.GetBitmap() );
857 MapMode aMap( MAP_100TH_INCH );
859 sal_Int32 nDPI = rConfigItem.ReadInt32( "Resolution", 75 );
860 Fraction aFrac( 1, std::min( std::max( nDPI, sal_Int32( 75 ) ), sal_Int32( 600 ) ) );
862 aMap.SetScaleX( aFrac );
863 aMap.SetScaleY( aFrac );
865 Size aOldSize = aBitmap.GetSizePixel();
866 aGraphic = rGraphic;
867 aGraphic.SetPrefMapMode( aMap );
868 aGraphic.SetPrefSize( Size( aOldSize.Width() * 100,
869 aOldSize.Height() * 100 ) );
871 // Size is set
872 else if( nMode == 2 )
874 aGraphic = rGraphic;
875 aGraphic.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
876 aGraphic.SetPrefSize( Size( nLogicalWidth, nLogicalHeight ) );
878 else
879 aGraphic = rGraphic;
881 sal_Int32 nColors = rConfigItem.ReadInt32( "Color", 0 ); // #92767#
882 if ( nColors ) // graphic conversion necessary ?
884 BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
885 aBmpEx.Convert( (BmpConversion)nColors ); // the entries in the xml section have the same meaning as
886 aGraphic = aBmpEx; // they have in the BmpConversion enum, so it should be
887 } // allowed to cast them
889 else
891 if( ( nMode == 1 ) || ( nMode == 2 ) )
893 GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
894 css::awt::Size aDefaultSize( 10000, 10000 );
895 Size aNewSize( OutputDevice::LogicToLogic( Size( nLogicalWidth, nLogicalHeight ), MAP_100TH_MM, aMtf.GetPrefMapMode() ) );
897 if( aNewSize.Width() && aNewSize.Height() )
899 const Size aPreferredSize( aMtf.GetPrefSize() );
900 aMtf.Scale( Fraction( aNewSize.Width(), aPreferredSize.Width() ),
901 Fraction( aNewSize.Height(), aPreferredSize.Height() ) );
903 aGraphic = Graphic( aMtf );
905 else
906 aGraphic = rGraphic;
910 else
911 aGraphic = rGraphic;
913 delete pResMgr;
915 return aGraphic;
918 #endif
920 static String ImpCreateFullFilterPath( const String& rPath, const String& rFilterName )
922 OUString aPathURL;
924 ::osl::FileBase::getFileURLFromSystemPath( rPath, aPathURL );
925 aPathURL += OUString( '/' );
927 OUString aSystemPath;
928 ::osl::FileBase::getSystemPathFromFileURL( aPathURL, aSystemPath );
929 aSystemPath += OUString( rFilterName );
931 return String( aSystemPath );
934 class ImpFilterLibCache;
936 struct ImpFilterLibCacheEntry
938 ImpFilterLibCacheEntry* mpNext;
939 #ifndef DISABLE_DYNLOADING
940 osl::Module maLibrary;
941 #endif
942 String maFiltername;
943 PFilterCall mpfnImport;
944 PFilterDlgCall mpfnImportDlg;
946 ImpFilterLibCacheEntry( const String& rPathname, const String& rFiltername );
947 int operator==( const String& rFiltername ) const { return maFiltername == rFiltername; }
949 PFilterCall GetImportFunction();
952 ImpFilterLibCacheEntry::ImpFilterLibCacheEntry( const String& rPathname, const String& rFiltername ) :
953 mpNext ( NULL ),
954 #ifndef DISABLE_DYNLOADING
955 maLibrary ( rPathname ),
956 #endif
957 maFiltername ( rFiltername ),
958 mpfnImport ( NULL ),
959 mpfnImportDlg ( NULL )
961 #ifdef DISABLE_DYNLOADING
962 (void) rPathname;
963 #endif
966 #ifdef DISABLE_DYNLOADING
968 extern "C" sal_Bool icdGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
969 extern "C" sal_Bool idxGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
970 extern "C" sal_Bool imeGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
971 extern "C" sal_Bool ipbGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
972 extern "C" sal_Bool ipdGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
973 extern "C" sal_Bool ipsGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
974 extern "C" sal_Bool iptGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
975 extern "C" sal_Bool ipxGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
976 extern "C" sal_Bool iraGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
977 extern "C" sal_Bool itgGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
978 extern "C" sal_Bool itiGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
980 #endif
982 PFilterCall ImpFilterLibCacheEntry::GetImportFunction()
984 if( !mpfnImport )
986 #ifndef DISABLE_DYNLOADING
987 mpfnImport = (PFilterCall) maLibrary.getFunctionSymbol(OUString(IMPORT_FUNCTION_NAME));
988 #else
989 if( maFiltername.EqualsAscii( "icd" ) )
990 mpfnImport = icdGraphicImport;
991 else if( maFiltername.EqualsAscii( "idx" ) )
992 mpfnImport = idxGraphicImport;
993 else if( maFiltername.EqualsAscii( "ime" ) )
994 mpfnImport = imeGraphicImport;
995 else if( maFiltername.EqualsAscii( "ipb" ) )
996 mpfnImport = ipbGraphicImport;
997 else if( maFiltername.EqualsAscii( "ipd" ) )
998 mpfnImport = ipdGraphicImport;
999 else if( maFiltername.EqualsAscii( "ips" ) )
1000 mpfnImport = ipsGraphicImport;
1001 else if( maFiltername.EqualsAscii( "ipt" ) )
1002 mpfnImport = iptGraphicImport;
1003 else if( maFiltername.EqualsAscii( "ipx" ) )
1004 mpfnImport = ipxGraphicImport;
1005 else if( maFiltername.EqualsAscii( "ira" ) )
1006 mpfnImport = iraGraphicImport;
1007 else if( maFiltername.EqualsAscii( "itg" ) )
1008 mpfnImport = itgGraphicImport;
1009 else if( maFiltername.EqualsAscii( "iti" ) )
1010 mpfnImport = itiGraphicImport;
1011 #endif
1014 return mpfnImport;
1017 class ImpFilterLibCache
1019 ImpFilterLibCacheEntry* mpFirst;
1020 ImpFilterLibCacheEntry* mpLast;
1022 public:
1023 ImpFilterLibCache();
1024 ~ImpFilterLibCache();
1026 ImpFilterLibCacheEntry* GetFilter( const String& rFilterPath, const String& rFiltername );
1029 ImpFilterLibCache::ImpFilterLibCache() :
1030 mpFirst ( NULL ),
1031 mpLast ( NULL )
1035 ImpFilterLibCache::~ImpFilterLibCache()
1037 ImpFilterLibCacheEntry* pEntry = mpFirst;
1038 while( pEntry )
1040 ImpFilterLibCacheEntry* pNext = pEntry->mpNext;
1041 delete pEntry;
1042 pEntry = pNext;
1046 ImpFilterLibCacheEntry* ImpFilterLibCache::GetFilter( const String& rFilterPath, const String& rFilterName )
1048 ImpFilterLibCacheEntry* pEntry = mpFirst;
1050 while( pEntry )
1052 if( *pEntry == rFilterName )
1053 break;
1054 else
1055 pEntry = pEntry->mpNext;
1057 if( !pEntry )
1059 String aPhysicalName( ImpCreateFullFilterPath( rFilterPath, rFilterName ) );
1060 pEntry = new ImpFilterLibCacheEntry( aPhysicalName, rFilterName );
1061 #ifndef DISABLE_DYNLOADING
1062 if ( pEntry->maLibrary.is() )
1063 #endif
1065 if( !mpFirst )
1066 mpFirst = mpLast = pEntry;
1067 else
1068 mpLast = mpLast->mpNext = pEntry;
1070 #ifndef DISABLE_DYNLOADING
1071 else
1073 delete pEntry;
1074 pEntry = NULL;
1076 #endif
1078 return pEntry;
1081 namespace { struct Cache : public rtl::Static<ImpFilterLibCache, Cache> {}; }
1083 GraphicFilter::GraphicFilter( sal_Bool bConfig ) :
1084 bUseConfig ( bConfig ),
1085 nExpGraphHint ( 0 )
1087 ImplInit();
1090 GraphicFilter::~GraphicFilter()
1093 ::osl::MutexGuard aGuard( getListMutex() );
1094 for(
1095 FilterList_impl::iterator it = pFilterHdlList->begin();
1096 it != pFilterHdlList->end();
1097 ++it
1099 if( *it == this )
1101 pFilterHdlList->erase( it );
1102 break;
1105 if( pFilterHdlList->empty() )
1107 delete pFilterHdlList, pFilterHdlList = NULL;
1108 delete pConfig;
1112 delete pErrorEx;
1115 void GraphicFilter::ImplInit()
1118 ::osl::MutexGuard aGuard( getListMutex() );
1120 if ( !pFilterHdlList )
1122 pFilterHdlList = new FilterList_impl;
1123 pConfig = new FilterConfigCache( bUseConfig );
1125 else
1126 pConfig = pFilterHdlList->front()->pConfig;
1128 pFilterHdlList->push_back( this );
1131 if( bUseConfig )
1133 OUString url("$BRAND_BASE_DIR/program");
1134 rtl::Bootstrap::expandMacros(url); //TODO: detect failure
1135 utl::LocalFileHelper::ConvertURLToPhysicalName(url, aFilterPath);
1138 pErrorEx = new FilterErrorEx;
1139 bAbort = sal_False;
1142 sal_uLong GraphicFilter::ImplSetError( sal_uLong nError, const SvStream* pStm )
1144 pErrorEx->nFilterError = nError;
1145 pErrorEx->nStreamError = pStm ? pStm->GetError() : ERRCODE_NONE;
1146 return nError;
1149 sal_uInt16 GraphicFilter::GetImportFormatCount()
1151 return pConfig->GetImportFormatCount();
1154 sal_uInt16 GraphicFilter::GetImportFormatNumber( const String& rFormatName )
1156 return pConfig->GetImportFormatNumber( rFormatName );
1159 sal_uInt16 GraphicFilter::GetImportFormatNumberForMediaType( const String& rMediaType )
1161 return pConfig->GetImportFormatNumberForMediaType( rMediaType );
1164 sal_uInt16 GraphicFilter::GetImportFormatNumberForShortName( const String& rShortName )
1166 return pConfig->GetImportFormatNumberForShortName( rShortName );
1169 sal_uInt16 GraphicFilter::GetImportFormatNumberForTypeName( const String& rType )
1171 return pConfig->GetImportFormatNumberForTypeName( rType );
1174 String GraphicFilter::GetImportFormatName( sal_uInt16 nFormat )
1176 return pConfig->GetImportFormatName( nFormat );
1179 String GraphicFilter::GetImportFormatTypeName( sal_uInt16 nFormat )
1181 return pConfig->GetImportFilterTypeName( nFormat );
1184 String GraphicFilter::GetImportFormatMediaType( sal_uInt16 nFormat )
1186 return pConfig->GetImportFormatMediaType( nFormat );
1189 String GraphicFilter::GetImportFormatShortName( sal_uInt16 nFormat )
1191 return pConfig->GetImportFormatShortName( nFormat );
1194 String GraphicFilter::GetImportOSFileType( sal_uInt16 )
1196 String aOSFileType;
1197 return aOSFileType;
1200 String GraphicFilter::GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
1202 return pConfig->GetImportWildcard( nFormat, nEntry );
1205 sal_Bool GraphicFilter::IsImportPixelFormat( sal_uInt16 nFormat )
1207 return pConfig->IsImportPixelFormat( nFormat );
1210 sal_uInt16 GraphicFilter::GetExportFormatCount()
1212 return pConfig->GetExportFormatCount();
1215 sal_uInt16 GraphicFilter::GetExportFormatNumber( const String& rFormatName )
1217 return pConfig->GetExportFormatNumber( rFormatName );
1220 sal_uInt16 GraphicFilter::GetExportFormatNumberForMediaType( const String& rMediaType )
1222 return pConfig->GetExportFormatNumberForMediaType( rMediaType );
1225 sal_uInt16 GraphicFilter::GetExportFormatNumberForShortName( const String& rShortName )
1227 return pConfig->GetExportFormatNumberForShortName( rShortName );
1230 String GraphicFilter::GetExportInternalFilterName( sal_uInt16 nFormat )
1232 return pConfig->GetExportInternalFilterName( nFormat );
1235 sal_uInt16 GraphicFilter::GetExportFormatNumberForTypeName( const String& rType )
1237 return pConfig->GetExportFormatNumberForTypeName( rType );
1240 String GraphicFilter::GetExportFormatName( sal_uInt16 nFormat )
1242 return pConfig->GetExportFormatName( nFormat );
1245 String GraphicFilter::GetExportFormatTypeName( sal_uInt16 nFormat )
1247 return pConfig->GetExportFilterTypeName( nFormat );
1250 String GraphicFilter::GetExportFormatMediaType( sal_uInt16 nFormat )
1252 return pConfig->GetExportFormatMediaType( nFormat );
1255 String GraphicFilter::GetExportFormatShortName( sal_uInt16 nFormat )
1257 return pConfig->GetExportFormatShortName( nFormat );
1260 String GraphicFilter::GetExportOSFileType( sal_uInt16 )
1262 String aOSFileType;
1263 return aOSFileType;
1266 String GraphicFilter::GetExportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
1268 return pConfig->GetExportWildcard( nFormat, nEntry );
1271 sal_Bool GraphicFilter::IsExportPixelFormat( sal_uInt16 nFormat )
1273 return pConfig->IsExportPixelFormat( nFormat );
1276 sal_uInt16 GraphicFilter::CanImportGraphic( const INetURLObject& rPath,
1277 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
1279 sal_uInt16 nRetValue = GRFILTER_FORMATERROR;
1280 DBG_ASSERT( rPath.GetProtocol() != INET_PROT_NOT_VALID, "GraphicFilter::CanImportGraphic() : ProtType == INET_PROT_NOT_VALID" );
1282 String aMainUrl( rPath.GetMainURL( INetURLObject::NO_DECODE ) );
1283 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMainUrl, STREAM_READ | STREAM_SHARE_DENYNONE );
1284 if ( pStream )
1286 nRetValue = CanImportGraphic( aMainUrl, *pStream, nFormat, pDeterminedFormat );
1287 delete pStream;
1289 return nRetValue;
1292 sal_uInt16 GraphicFilter::CanImportGraphic( const String& rMainUrl, SvStream& rIStream,
1293 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
1295 sal_uLong nStreamPos = rIStream.Tell();
1296 sal_uInt16 nRes = ImpTestOrFindFormat( rMainUrl, rIStream, nFormat );
1298 rIStream.Seek(nStreamPos);
1300 if( nRes==GRFILTER_OK && pDeterminedFormat!=NULL )
1301 *pDeterminedFormat = nFormat;
1303 return (sal_uInt16) ImplSetError( nRes, &rIStream );
1306 //SJ: TODO, we need to create a GraphicImporter component
1307 sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const INetURLObject& rPath,
1308 sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat, sal_uInt32 nImportFlags )
1310 sal_uInt16 nRetValue = GRFILTER_FORMATERROR;
1311 DBG_ASSERT( rPath.GetProtocol() != INET_PROT_NOT_VALID, "GraphicFilter::ImportGraphic() : ProtType == INET_PROT_NOT_VALID" );
1313 String aMainUrl( rPath.GetMainURL( INetURLObject::NO_DECODE ) );
1314 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMainUrl, STREAM_READ | STREAM_SHARE_DENYNONE );
1315 if ( pStream )
1317 nRetValue = ImportGraphic( rGraphic, aMainUrl, *pStream, nFormat, pDeterminedFormat, nImportFlags );
1318 delete pStream;
1320 return nRetValue;
1323 sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rIStream,
1324 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags, WMF_EXTERNALHEADER *pExtHeader )
1326 return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, NULL, pExtHeader );
1329 //-------------------------------------------------------------------------
1331 sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rIStream,
1332 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags,
1333 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData,
1334 WMF_EXTERNALHEADER *pExtHeader )
1336 String aFilterName;
1337 sal_uLong nStmBegin;
1338 sal_uInt16 nStatus;
1339 GraphicReader* pContext = rGraphic.GetContext();
1340 GfxLinkType eLinkType = GFX_LINK_TYPE_NONE;
1341 sal_Bool bDummyContext = ( pContext == (GraphicReader*) 1 );
1342 const sal_Bool bLinkSet = rGraphic.IsLink();
1343 FilterConfigItem* pFilterConfigItem = NULL;
1345 Size aPreviewSizeHint( 0, 0 );
1346 sal_Bool bAllowPartialStreamRead = sal_False;
1347 sal_Bool bCreateNativeLink = sal_True;
1349 ResetLastError();
1351 if ( pFilterData )
1353 sal_Int32 i;
1354 for ( i = 0; i < pFilterData->getLength(); i++ )
1356 if ( (*pFilterData)[ i ].Name == "PreviewSizeHint" )
1358 awt::Size aSize;
1359 if ( (*pFilterData)[ i ].Value >>= aSize )
1361 aPreviewSizeHint = Size( aSize.Width, aSize.Height );
1362 if ( aSize.Width || aSize.Height )
1363 nImportFlags |= GRFILTER_I_FLAGS_FOR_PREVIEW;
1364 else
1365 nImportFlags &=~GRFILTER_I_FLAGS_FOR_PREVIEW;
1368 else if ( (*pFilterData)[ i ].Name == "AllowPartialStreamRead" )
1370 (*pFilterData)[ i ].Value >>= bAllowPartialStreamRead;
1371 if ( bAllowPartialStreamRead )
1372 nImportFlags |= GRFILTER_I_FLAGS_ALLOW_PARTIAL_STREAMREAD;
1373 else
1374 nImportFlags &=~GRFILTER_I_FLAGS_ALLOW_PARTIAL_STREAMREAD;
1376 else if ( (*pFilterData)[ i ].Name == "CreateNativeLink" )
1378 (*pFilterData)[ i ].Value >>= bCreateNativeLink;
1383 if( !pContext || bDummyContext )
1385 if( bDummyContext )
1387 rGraphic.SetContext( NULL );
1388 nStmBegin = 0;
1390 else
1391 nStmBegin = rIStream.Tell();
1393 bAbort = sal_False;
1394 nStatus = ImpTestOrFindFormat( rPath, rIStream, nFormat );
1395 // if pending, return GRFILTER_OK in order to request more bytes
1396 if( rIStream.GetError() == ERRCODE_IO_PENDING )
1398 rGraphic.SetContext( (GraphicReader*) 1 );
1399 rIStream.ResetError();
1400 rIStream.Seek( nStmBegin );
1401 return (sal_uInt16) ImplSetError( GRFILTER_OK );
1404 rIStream.Seek( nStmBegin );
1406 if( ( nStatus != GRFILTER_OK ) || rIStream.GetError() )
1407 return (sal_uInt16) ImplSetError( ( nStatus != GRFILTER_OK ) ? nStatus : GRFILTER_OPENERROR, &rIStream );
1409 if( pDeterminedFormat )
1410 *pDeterminedFormat = nFormat;
1412 aFilterName = pConfig->GetImportFilterName( nFormat );
1414 else
1416 if( pContext && !bDummyContext )
1417 aFilterName = pContext->GetUpperFilterName();
1419 nStmBegin = 0;
1420 nStatus = GRFILTER_OK;
1423 // read graphic
1424 if ( pConfig->IsImportInternalFilter( nFormat ) )
1426 if( aFilterName.EqualsIgnoreCaseAscii( IMP_GIF ) )
1428 if( rGraphic.GetContext() == (GraphicReader*) 1 )
1429 rGraphic.SetContext( NULL );
1431 if( !ImportGIF( rIStream, rGraphic ) )
1432 nStatus = GRFILTER_FILTERERROR;
1433 else
1434 eLinkType = GFX_LINK_TYPE_NATIVE_GIF;
1436 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_PNG ) )
1438 if ( rGraphic.GetContext() == (GraphicReader*) 1 )
1439 rGraphic.SetContext( NULL );
1441 vcl::PNGReader aPNGReader( rIStream );
1443 // ignore animation for previews and set preview size
1444 if( aPreviewSizeHint.Width() || aPreviewSizeHint.Height() )
1446 // position the stream at the end of the image if requested
1447 if( !bAllowPartialStreamRead )
1448 aPNGReader.GetChunks();
1450 else
1452 // check if this PNG contains a GIF chunk!
1453 const std::vector< vcl::PNGReader::ChunkData >& rChunkData = aPNGReader.GetChunks();
1454 std::vector< vcl::PNGReader::ChunkData >::const_iterator aIter( rChunkData.begin() );
1455 std::vector< vcl::PNGReader::ChunkData >::const_iterator aEnd ( rChunkData.end() );
1456 while( aIter != aEnd )
1458 // Microsoft Office is storing Animated GIFs in following chunk
1459 if ( aIter->nType == PMGCHUNG_msOG )
1461 sal_uInt32 nChunkSize = aIter->aData.size();
1462 if ( nChunkSize > 11 )
1464 const std::vector< sal_uInt8 >& rData = aIter->aData;
1465 SvMemoryStream aIStrm( (void*)&rData[ 11 ], nChunkSize - 11, STREAM_READ );
1466 ImportGIF( aIStrm, rGraphic );
1467 eLinkType = GFX_LINK_TYPE_NATIVE_PNG;
1468 break;
1471 ++aIter;
1475 if ( eLinkType == GFX_LINK_TYPE_NONE )
1477 BitmapEx aBmpEx( aPNGReader.Read( aPreviewSizeHint ) );
1478 if ( aBmpEx.IsEmpty() )
1479 nStatus = GRFILTER_FILTERERROR;
1480 else
1482 rGraphic = aBmpEx;
1483 eLinkType = GFX_LINK_TYPE_NATIVE_PNG;
1487 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_JPEG ) )
1489 if( rGraphic.GetContext() == (GraphicReader*) 1 )
1490 rGraphic.SetContext( NULL );
1492 // set LOGSIZE flag always, if not explicitly disabled
1493 // (see #90508 and #106763)
1494 if( 0 == ( nImportFlags & GRFILTER_I_FLAGS_DONT_SET_LOGSIZE_FOR_JPEG ) )
1495 nImportFlags |= GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG;
1497 if( !ImportJPEG( rIStream, rGraphic, NULL, nImportFlags ) )
1498 nStatus = GRFILTER_FILTERERROR;
1499 else
1500 eLinkType = GFX_LINK_TYPE_NATIVE_JPG;
1502 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_SVG ) )
1504 if( rGraphic.GetContext() == (GraphicReader*) 1 )
1505 rGraphic.SetContext( NULL );
1507 const sal_uInt32 nStmPos(rIStream.Tell());
1508 const sal_uInt32 nStmLen(rIStream.Seek(STREAM_SEEK_TO_END) - nStmPos);
1509 bool bOkay(false);
1511 if(nStmLen)
1513 SvgDataArray aNewData(new sal_uInt8[nStmLen]);
1515 rIStream.Seek(nStmPos);
1516 rIStream.Read(aNewData.get(), nStmLen);
1518 if(!rIStream.GetError())
1520 SvgDataPtr aSvgDataPtr(
1521 new SvgData(
1522 aNewData,
1523 nStmLen,
1524 rPath));
1526 rGraphic = Graphic(aSvgDataPtr);
1527 bOkay = true;
1531 if(bOkay)
1533 eLinkType = GFX_LINK_TYPE_NATIVE_SVG;
1535 else
1537 nStatus = GRFILTER_FILTERERROR;
1540 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_XBM ) )
1542 if( rGraphic.GetContext() == (GraphicReader*) 1 )
1543 rGraphic.SetContext( NULL );
1545 if( !ImportXBM( rIStream, rGraphic ) )
1546 nStatus = GRFILTER_FILTERERROR;
1548 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_XPM ) )
1550 if( rGraphic.GetContext() == (GraphicReader*) 1 )
1551 rGraphic.SetContext( NULL );
1553 if( !ImportXPM( rIStream, rGraphic ) )
1554 nStatus = GRFILTER_FILTERERROR;
1556 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_BMP ) ||
1557 aFilterName.EqualsIgnoreCaseAscii( IMP_SVMETAFILE ) )
1559 // SV internal filters for import bitmaps and MetaFiles
1560 rIStream >> rGraphic;
1561 if( rIStream.GetError() )
1562 nStatus = GRFILTER_FORMATERROR;
1564 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_WMF ) ||
1565 aFilterName.EqualsIgnoreCaseAscii( IMP_EMF ) )
1567 GDIMetaFile aMtf;
1568 if( !ConvertWMFToGDIMetaFile( rIStream, aMtf, NULL, pExtHeader ) )
1569 nStatus = GRFILTER_FORMATERROR;
1570 else
1572 rGraphic = aMtf;
1573 eLinkType = GFX_LINK_TYPE_NATIVE_WMF;
1576 else if( aFilterName.EqualsIgnoreCaseAscii( IMP_SVSGF )
1577 || aFilterName.EqualsIgnoreCaseAscii( IMP_SVSGV ) )
1579 sal_uInt16 nVersion;
1580 unsigned char nTyp = CheckSgfTyp( rIStream, nVersion );
1582 switch( nTyp )
1584 case SGF_BITIMAGE:
1586 SvMemoryStream aTempStream;
1587 if( aTempStream.GetError() )
1588 return GRFILTER_OPENERROR;
1590 if( !SgfBMapFilter( rIStream, aTempStream ) )
1591 nStatus = GRFILTER_FILTERERROR;
1592 else
1594 aTempStream.Seek( 0L );
1595 aTempStream >> rGraphic;
1597 if( aTempStream.GetError() )
1598 nStatus = GRFILTER_FILTERERROR;
1601 break;
1603 case SGF_SIMPVECT:
1605 GDIMetaFile aMtf;
1606 if( !SgfVectFilter( rIStream, aMtf ) )
1607 nStatus = GRFILTER_FILTERERROR;
1608 else
1609 rGraphic = Graphic( aMtf );
1611 break;
1613 case SGF_STARDRAW:
1615 if( nVersion != SGV_VERSION )
1616 nStatus = GRFILTER_VERSIONERROR;
1617 else
1619 GDIMetaFile aMtf;
1620 if( !SgfSDrwFilter( rIStream, aMtf,
1621 INetURLObject(aFilterPath) ) )
1623 nStatus = GRFILTER_FILTERERROR;
1625 else
1626 rGraphic = Graphic( aMtf );
1629 break;
1631 default:
1633 nStatus = GRFILTER_FORMATERROR;
1635 break;
1638 else
1639 nStatus = GRFILTER_FILTERERROR;
1641 else
1643 ImpFilterLibCacheEntry* pFilter = NULL;
1645 // find first filter in filter paths
1646 sal_Int32 i, nTokenCount = getTokenCount(aFilterPath, ';');
1647 ImpFilterLibCache &rCache = Cache::get();
1648 for( i = 0; ( i < nTokenCount ) && ( pFilter == NULL ); i++ )
1649 pFilter = rCache.GetFilter( getToken(aFilterPath, i, ';'), aFilterName );
1650 if( !pFilter )
1651 nStatus = GRFILTER_FILTERERROR;
1652 else
1654 PFilterCall pFunc = pFilter->GetImportFunction();
1656 if( !pFunc )
1657 nStatus = GRFILTER_FILTERERROR;
1658 else
1660 String aShortName;
1661 if( nFormat != GRFILTER_FORMAT_DONTKNOW )
1663 aShortName = GetImportFormatShortName( nFormat ).ToUpperAscii();
1664 if ( ( pFilterConfigItem == NULL ) && aShortName.EqualsAscii( "PCD" ) )
1666 String aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
1667 pFilterConfigItem = new FilterConfigItem( aFilterConfigPath );
1670 if( !(*pFunc)( rIStream, rGraphic, pFilterConfigItem, sal_False ) )
1671 nStatus = GRFILTER_FORMATERROR;
1672 else
1674 // try to set link type if format matches
1675 if( nFormat != GRFILTER_FORMAT_DONTKNOW )
1677 if( aShortName.CompareToAscii( TIF_SHORTNAME ) == COMPARE_EQUAL )
1678 eLinkType = GFX_LINK_TYPE_NATIVE_TIF;
1679 else if( aShortName.CompareToAscii( MET_SHORTNAME ) == COMPARE_EQUAL )
1680 eLinkType = GFX_LINK_TYPE_NATIVE_MET;
1681 else if( aShortName.CompareToAscii( PCT_SHORTNAME ) == COMPARE_EQUAL )
1682 eLinkType = GFX_LINK_TYPE_NATIVE_PCT;
1689 if( nStatus == GRFILTER_OK && bCreateNativeLink && ( eLinkType != GFX_LINK_TYPE_NONE ) && !rGraphic.GetContext() && !bLinkSet )
1691 const sal_uLong nStmEnd = rIStream.Tell();
1692 const sal_uLong nBufSize = nStmEnd - nStmBegin;
1694 if( nBufSize )
1696 sal_uInt8* pBuf=0;
1699 pBuf = new sal_uInt8[ nBufSize ];
1701 catch (const std::bad_alloc&)
1703 nStatus = GRFILTER_TOOBIG;
1706 if( nStatus == GRFILTER_OK )
1708 rIStream.Seek( nStmBegin );
1709 rIStream.Read( pBuf, nBufSize );
1710 rGraphic.SetLink( GfxLink( pBuf, nBufSize, eLinkType, sal_True ) );
1715 // Set error code or try to set native buffer
1716 if( nStatus != GRFILTER_OK )
1718 if( bAbort )
1719 nStatus = GRFILTER_ABORT;
1721 ImplSetError( nStatus, &rIStream );
1722 rIStream.Seek( nStmBegin );
1723 rGraphic.Clear();
1726 delete pFilterConfigItem;
1727 return nStatus;
1730 sal_uInt16 GraphicFilter::ExportGraphic( const Graphic& rGraphic, const INetURLObject& rPath,
1731 sal_uInt16 nFormat, const uno::Sequence< beans::PropertyValue >* pFilterData )
1733 #ifdef DISABLE_EXPORT
1734 (void) rGraphic;
1735 (void) rPath;
1736 (void) nFormat;
1737 (void) pFilterData;
1739 return GRFILTER_FORMATERROR;
1740 #else
1741 RTL_LOGFILE_CONTEXT( aLog, "GraphicFilter::ExportGraphic() (thb)" );
1742 sal_uInt16 nRetValue = GRFILTER_FORMATERROR;
1743 DBG_ASSERT( rPath.GetProtocol() != INET_PROT_NOT_VALID, "GraphicFilter::ExportGraphic() : ProtType == INET_PROT_NOT_VALID" );
1744 sal_Bool bAlreadyExists = DirEntryExists( rPath );
1746 String aMainUrl( rPath.GetMainURL( INetURLObject::NO_DECODE ) );
1747 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMainUrl, STREAM_WRITE | STREAM_TRUNC );
1748 if ( pStream )
1750 nRetValue = ExportGraphic( rGraphic, aMainUrl, *pStream, nFormat, pFilterData );
1751 delete pStream;
1753 if( ( GRFILTER_OK != nRetValue ) && !bAlreadyExists )
1754 KillDirEntry( aMainUrl );
1756 return nRetValue;
1757 #endif
1760 #ifdef DISABLE_DYNLOADING
1762 #ifndef DISABLE_EXPORT
1764 extern "C" sal_Bool egiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1765 extern "C" sal_Bool emeGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1766 extern "C" sal_Bool epbGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1767 extern "C" sal_Bool epgGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1768 extern "C" sal_Bool eppGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1769 extern "C" sal_Bool epsGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1770 extern "C" sal_Bool eptGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1771 extern "C" sal_Bool eraGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1772 extern "C" sal_Bool etiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1773 extern "C" sal_Bool expGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
1775 #endif
1777 #endif
1779 sal_uInt16 GraphicFilter::ExportGraphic( const Graphic& rGraphic, const String& rPath,
1780 SvStream& rOStm, sal_uInt16 nFormat, const uno::Sequence< beans::PropertyValue >* pFilterData )
1782 #ifdef DISABLE_EXPORT
1783 (void) rGraphic;
1784 (void) rPath;
1785 (void) rOStm;
1786 (void) nFormat;
1787 (void) pFilterData;
1789 return GRFILTER_FORMATERROR;
1790 #else
1791 RTL_LOGFILE_CONTEXT( aLog, "GraphicFilter::ExportGraphic() (thb)" );
1792 sal_uInt16 nFormatCount = GetExportFormatCount();
1794 ResetLastError();
1795 nExpGraphHint = 0;
1797 if( nFormat == GRFILTER_FORMAT_DONTKNOW )
1799 INetURLObject aURL( rPath );
1800 String aExt( aURL.GetFileExtension().toAsciiUpperCase() );
1803 for( sal_uInt16 i = 0; i < nFormatCount; i++ )
1805 if ( pConfig->GetExportFormatExtension( i ).EqualsIgnoreCaseAscii( aExt ) )
1807 nFormat=i;
1808 break;
1812 if( nFormat >= nFormatCount )
1813 return (sal_uInt16) ImplSetError( GRFILTER_FORMATERROR );
1815 FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData );
1816 String aFilterName( pConfig->GetExportFilterName( nFormat ) );
1818 bAbort = sal_False;
1819 sal_uInt16 nStatus = GRFILTER_OK;
1820 GraphicType eType;
1821 Graphic aGraphic( rGraphic );
1823 aGraphic = ImpGetScaledGraphic( rGraphic, aConfigItem );
1824 eType = aGraphic.GetType();
1826 if( pConfig->IsExportPixelFormat( nFormat ) )
1828 if( eType != GRAPHIC_BITMAP )
1830 Size aSizePixel;
1831 sal_uLong nColorCount,nBitsPerPixel,nNeededMem,nMaxMem;
1832 VirtualDevice aVirDev;
1834 nMaxMem = 1024;
1835 nMaxMem *= 1024; // In Bytes
1837 // Calculate how big the image would normally be:
1838 aSizePixel=aVirDev.LogicToPixel(aGraphic.GetPrefSize(),aGraphic.GetPrefMapMode());
1840 // Calculate how much memory the image will take up
1841 nColorCount=aVirDev.GetColorCount();
1842 if (nColorCount<=2) nBitsPerPixel=1;
1843 else if (nColorCount<=4) nBitsPerPixel=2;
1844 else if (nColorCount<=16) nBitsPerPixel=4;
1845 else if (nColorCount<=256) nBitsPerPixel=8;
1846 else if (nColorCount<=65536) nBitsPerPixel=16;
1847 else nBitsPerPixel=24;
1848 nNeededMem=((sal_uLong)aSizePixel.Width()*(sal_uLong)aSizePixel.Height()*nBitsPerPixel+7)/8;
1850 // is the image larger than available memory?
1851 if (nMaxMem<nNeededMem)
1853 double fFak=sqrt(((double)nMaxMem)/((double)nNeededMem));
1854 aSizePixel.Width()=(sal_uLong)(((double)aSizePixel.Width())*fFak);
1855 aSizePixel.Height()=(sal_uLong)(((double)aSizePixel.Height())*fFak);
1858 aVirDev.SetMapMode(MapMode(MAP_PIXEL));
1859 aVirDev.SetOutputSizePixel(aSizePixel);
1860 Graphic aGraphic2=aGraphic;
1861 aGraphic2.Draw(&aVirDev,Point(0,0),aSizePixel); // this changes the MapMode
1862 aVirDev.SetMapMode(MapMode(MAP_PIXEL));
1863 aGraphic=Graphic(aVirDev.GetBitmap(Point(0,0),aSizePixel));
1866 if( rOStm.GetError() )
1867 nStatus = GRFILTER_IOERROR;
1868 if( GRFILTER_OK == nStatus )
1870 if ( pConfig->IsExportInternalFilter( nFormat ) )
1872 if( aFilterName.EqualsIgnoreCaseAscii( EXP_BMP ) )
1874 Bitmap aBmp( aGraphic.GetBitmap() );
1875 sal_Int32 nColorRes = aConfigItem.ReadInt32( "Colors", 0 );
1876 if ( nColorRes && ( nColorRes <= (sal_uInt16)BMP_CONVERSION_24BIT) )
1878 if( !aBmp.Convert( (BmpConversion) nColorRes ) )
1879 aBmp = aGraphic.GetBitmap();
1881 sal_Bool bRleCoding = aConfigItem.ReadBool( "RLE_Coding", sal_True );
1882 // save RLE encoded?
1883 aBmp.Write( rOStm, bRleCoding );
1885 if( rOStm.GetError() )
1886 nStatus = GRFILTER_IOERROR;
1888 else if( aFilterName.EqualsIgnoreCaseAscii( EXP_SVMETAFILE ) )
1890 sal_Int32 nVersion = aConfigItem.ReadInt32( "Version", 0 ) ;
1891 if ( nVersion )
1892 rOStm.SetVersion( nVersion );
1894 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
1895 GDIMetaFile aMTF(aGraphic.GetGDIMetaFile());
1897 aMTF.Write( rOStm );
1899 if( rOStm.GetError() )
1900 nStatus = GRFILTER_IOERROR;
1902 else if ( aFilterName.EqualsIgnoreCaseAscii( EXP_WMF ) )
1904 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
1905 if ( !ConvertGDIMetaFileToWMF( aGraphic.GetGDIMetaFile(), rOStm, &aConfigItem ) )
1906 nStatus = GRFILTER_FORMATERROR;
1908 if( rOStm.GetError() )
1909 nStatus = GRFILTER_IOERROR;
1911 else if ( aFilterName.EqualsIgnoreCaseAscii( EXP_EMF ) )
1913 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
1914 if ( !ConvertGDIMetaFileToEMF( aGraphic.GetGDIMetaFile(), rOStm, &aConfigItem ) )
1915 nStatus = GRFILTER_FORMATERROR;
1917 if( rOStm.GetError() )
1918 nStatus = GRFILTER_IOERROR;
1920 else if( aFilterName.EqualsIgnoreCaseAscii( EXP_JPEG ) )
1922 bool bExportedGrayJPEG = false;
1923 if( !ExportJPEG( rOStm, aGraphic, pFilterData, &bExportedGrayJPEG ) )
1924 nStatus = GRFILTER_FORMATERROR;
1925 nExpGraphHint = bExportedGrayJPEG ? GRFILTER_OUTHINT_GREY : 0;
1927 if( rOStm.GetError() )
1928 nStatus = GRFILTER_IOERROR;
1930 else if ( aFilterName.EqualsIgnoreCaseAscii( EXP_PNG ) )
1932 vcl::PNGWriter aPNGWriter( aGraphic.GetBitmapEx(), pFilterData );
1933 if ( pFilterData )
1935 sal_Int32 k, j, i = 0;
1936 for ( i = 0; i < pFilterData->getLength(); i++ )
1938 if ( (*pFilterData)[ i ].Name == "AdditionalChunks" )
1940 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence;
1941 if ( (*pFilterData)[ i ].Value >>= aAdditionalChunkSequence )
1943 for ( j = 0; j < aAdditionalChunkSequence.getLength(); j++ )
1945 if ( aAdditionalChunkSequence[ j ].Name.getLength() == 4 )
1947 sal_uInt32 nChunkType = 0;
1948 for ( k = 0; k < 4; k++ )
1950 nChunkType <<= 8;
1951 nChunkType |= (sal_uInt8)aAdditionalChunkSequence[ j ].Name[ k ];
1953 com::sun::star::uno::Sequence< sal_Int8 > aByteSeq;
1954 if ( aAdditionalChunkSequence[ j ].Value >>= aByteSeq )
1956 std::vector< vcl::PNGWriter::ChunkData >& rChunkData = aPNGWriter.GetChunks();
1957 if ( !rChunkData.empty() )
1959 sal_uInt32 nChunkLen = aByteSeq.getLength();
1961 vcl::PNGWriter::ChunkData aChunkData;
1962 aChunkData.nType = nChunkType;
1963 if ( nChunkLen )
1965 aChunkData.aData.resize( nChunkLen );
1966 memcpy( &aChunkData.aData[ 0 ], aByteSeq.getConstArray(), nChunkLen );
1968 std::vector< vcl::PNGWriter::ChunkData >::iterator aIter = rChunkData.end() - 1;
1969 rChunkData.insert( aIter, aChunkData );
1978 aPNGWriter.Write( rOStm );
1980 if( rOStm.GetError() )
1981 nStatus = GRFILTER_IOERROR;
1983 else if( aFilterName.EqualsIgnoreCaseAscii( EXP_SVG ) )
1985 bool bDone(false);
1987 // do we have a native SVG RenderGraphic, whose data can be written directly?
1988 const SvgDataPtr aSvgDataPtr(rGraphic.getSvgData());
1990 if(aSvgDataPtr.get() && aSvgDataPtr->getSvgDataArrayLength())
1992 rOStm.Write(aSvgDataPtr->getSvgDataArray().get(), aSvgDataPtr->getSvgDataArrayLength());
1994 if( rOStm.GetError() )
1996 nStatus = GRFILTER_IOERROR;
1998 else
2000 bDone = true;
2004 if( !bDone )
2006 // do the normal GDIMetaFile export instead
2009 css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2011 css::uno::Reference< css::xml::sax::XDocumentHandler > xSaxWriter(
2012 xml::sax::Writer::create( xContext ), uno::UNO_QUERY_THROW);
2014 css::uno::Reference< css::svg::XSVGWriter > xSVGWriter(
2015 xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.svg.SVGWriter", xContext ),
2016 css::uno::UNO_QUERY );
2018 if( xSaxWriter.is() && xSVGWriter.is() )
2020 css::uno::Reference< css::io::XActiveDataSource > xActiveDataSource(
2021 xSaxWriter, css::uno::UNO_QUERY );
2023 if( xActiveDataSource.is() )
2025 const css::uno::Reference< css::uno::XInterface > xStmIf(
2026 static_cast< ::cppu::OWeakObject* >( new ImpFilterOutputStream( rOStm ) ) );
2028 SvMemoryStream aMemStm( 65535, 65535 );
2030 // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
2031 ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( aMemStm );
2033 xActiveDataSource->setOutputStream( css::uno::Reference< css::io::XOutputStream >(
2034 xStmIf, css::uno::UNO_QUERY ) );
2035 css::uno::Sequence< sal_Int8 > aMtfSeq( (sal_Int8*) aMemStm.GetData(), aMemStm.Tell() );
2036 xSVGWriter->write( xSaxWriter, aMtfSeq );
2040 catch(const css::uno::Exception&)
2042 nStatus = GRFILTER_IOERROR;
2046 else
2047 nStatus = GRFILTER_FILTERERROR;
2049 else
2051 sal_Int32 i, nTokenCount = getTokenCount(aFilterPath, ';');
2052 for ( i = 0; i < nTokenCount; i++ )
2054 #ifndef DISABLE_DYNLOADING
2055 String aPhysicalName( ImpCreateFullFilterPath( getToken(aFilterPath, i, ';'), aFilterName ) );
2056 osl::Module aLibrary( aPhysicalName );
2058 PFilterCall pFunc = (PFilterCall) aLibrary.getFunctionSymbol(OUString(EXPORT_FUNCTION_NAME));
2059 // Execute dialog in DLL
2060 #else
2061 PFilterCall pFunc = NULL;
2062 if( aFilterName.EqualsAscii( "egi" ) )
2063 pFunc = egiGraphicExport;
2064 else if( aFilterName.EqualsAscii( "eme" ) )
2065 pFunc = emeGraphicExport;
2066 else if( aFilterName.EqualsAscii( "epb" ) )
2067 pFunc = epbGraphicExport;
2068 else if( aFilterName.EqualsAscii( "epg" ) )
2069 pFunc = epgGraphicExport;
2070 else if( aFilterName.EqualsAscii( "epp" ) )
2071 pFunc = eppGraphicExport;
2072 else if( aFilterName.EqualsAscii( "eps" ) )
2073 pFunc = epsGraphicExport;
2074 else if( aFilterName.EqualsAscii( "ept" ) )
2075 pFunc = eptGraphicExport;
2076 else if( aFilterName.EqualsAscii( "era" ) )
2077 pFunc = eraGraphicExport;
2078 else if( aFilterName.EqualsAscii( "eti" ) )
2079 pFunc = etiGraphicExport;
2080 else if( aFilterName.EqualsAscii( "exp" ) )
2081 pFunc = expGraphicExport;
2082 #endif
2083 if( pFunc )
2085 if ( !(*pFunc)( rOStm, aGraphic, &aConfigItem, sal_False ) )
2086 nStatus = GRFILTER_FORMATERROR;
2087 break;
2089 else
2090 nStatus = GRFILTER_FILTERERROR;
2094 if( nStatus != GRFILTER_OK )
2096 if( bAbort )
2097 nStatus = GRFILTER_ABORT;
2099 ImplSetError( nStatus, &rOStm );
2101 return nStatus;
2102 #endif
2105 const FilterErrorEx& GraphicFilter::GetLastError() const
2107 return *pErrorEx;
2110 void GraphicFilter::ResetLastError()
2112 pErrorEx->nFilterError = pErrorEx->nStreamError = 0UL;
2115 const Link GraphicFilter::GetFilterCallback() const
2117 const Link aLink( LINK( this, GraphicFilter, FilterCallback ) );
2118 return aLink;
2121 IMPL_LINK( GraphicFilter, FilterCallback, ConvertData*, pData )
2123 long nRet = 0L;
2125 if( pData )
2127 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
2128 OString aShortName;
2129 switch( pData->mnFormat )
2131 case( CVT_BMP ): aShortName = BMP_SHORTNAME; break;
2132 case( CVT_GIF ): aShortName = GIF_SHORTNAME; break;
2133 case( CVT_JPG ): aShortName = JPG_SHORTNAME; break;
2134 case( CVT_MET ): aShortName = MET_SHORTNAME; break;
2135 case( CVT_PCT ): aShortName = PCT_SHORTNAME; break;
2136 case( CVT_PNG ): aShortName = PNG_SHORTNAME; break;
2137 case( CVT_SVM ): aShortName = SVM_SHORTNAME; break;
2138 case( CVT_TIF ): aShortName = TIF_SHORTNAME; break;
2139 case( CVT_WMF ): aShortName = WMF_SHORTNAME; break;
2140 case( CVT_EMF ): aShortName = EMF_SHORTNAME; break;
2141 case( CVT_SVG ): aShortName = SVG_SHORTNAME; break;
2143 default:
2144 break;
2146 if( GRAPHIC_NONE == pData->maGraphic.GetType() || pData->maGraphic.GetContext() ) // Import
2148 // Import
2149 nFormat = GetImportFormatNumberForShortName( OStringToOUString( aShortName, RTL_TEXTENCODING_UTF8) );
2150 nRet = ImportGraphic( pData->maGraphic, String(), pData->mrStm, nFormat ) == 0;
2152 #ifndef DISABLE_EXPORT
2153 else if( !aShortName.isEmpty() )
2155 // Export
2156 nFormat = GetExportFormatNumberForShortName( OStringToOUString(aShortName, RTL_TEXTENCODING_UTF8) );
2157 nRet = ExportGraphic( pData->maGraphic, String(), pData->mrStm, nFormat ) == 0;
2159 #endif
2161 return nRet;
2164 namespace
2166 class StandardGraphicFilter
2168 public:
2169 StandardGraphicFilter()
2171 m_aFilter.GetImportFormatCount();
2173 GraphicFilter m_aFilter;
2176 class theGraphicFilter : public rtl::Static<StandardGraphicFilter, theGraphicFilter> {};
2179 GraphicFilter& GraphicFilter::GetGraphicFilter()
2181 return theGraphicFilter::get().m_aFilter;
2184 int GraphicFilter::LoadGraphic( const String &rPath, const String &rFilterName,
2185 Graphic& rGraphic, GraphicFilter* pFilter,
2186 sal_uInt16* pDeterminedFormat )
2188 if ( !pFilter )
2189 pFilter = &GetGraphicFilter();
2191 const sal_uInt16 nFilter = rFilterName.Len() && pFilter->GetImportFormatCount()
2192 ? pFilter->GetImportFormatNumber( rFilterName )
2193 : GRFILTER_FORMAT_DONTKNOW;
2195 SvStream* pStream = NULL;
2196 INetURLObject aURL( rPath );
2198 if ( aURL.HasError() || INET_PROT_NOT_VALID == aURL.GetProtocol() )
2200 aURL.SetSmartProtocol( INET_PROT_FILE );
2201 aURL.SetSmartURL( rPath );
2203 else if ( INET_PROT_FILE != aURL.GetProtocol() )
2205 pStream = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ );
2208 int nRes = GRFILTER_OK;
2209 if ( !pStream )
2210 nRes = pFilter->ImportGraphic( rGraphic, aURL, nFilter, pDeterminedFormat );
2211 else
2212 nRes = pFilter->ImportGraphic( rGraphic, rPath, *pStream, nFilter, pDeterminedFormat );
2214 #ifdef DBG_UTIL
2215 if( nRes )
2216 DBG_WARNING2( "GrafikFehler [%d] - [%s]", nRes, rPath.GetBuffer() );
2217 #endif
2219 return nRes;
2222 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */