1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <config_folders.h>
22 #include <osl/mutex.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/string.hxx>
25 #include <ucbhelper/content.hxx>
26 #include <cppuhelper/implbase1.hxx>
27 #include <tools/urlobj.hxx>
28 #include <tools/zcodec.hxx>
29 #include <tools/fract.hxx>
30 #include <vcl/dibtools.hxx>
31 #include <vcl/salctype.hxx>
32 #include <vcl/pngread.hxx>
33 #include <vcl/pngwrite.hxx>
34 #include <vcl/svgdata.hxx>
35 #include <vcl/virdev.hxx>
36 #include <vcl/svapp.hxx>
37 #include <osl/file.hxx>
38 #include <vcl/graphicfilter.hxx>
39 #include <vcl/FilterConfigItem.hxx>
40 #include <vcl/wmf.hxx>
41 #include <vcl/settings.hxx>
42 #include "igif/gifread.hxx"
43 #include "jpeg/jpeg.hxx"
44 #include "ixbm/xbmread.hxx"
45 #include "ixpm/xpmread.hxx"
46 #include "sgffilt.hxx"
47 #include "osl/module.hxx"
48 #include <com/sun/star/uno/Reference.h>
49 #include <com/sun/star/awt/Size.hpp>
50 #include <com/sun/star/uno/XInterface.hpp>
51 #include <com/sun/star/uno/XWeak.hpp>
52 #include <com/sun/star/uno/XAggregation.hpp>
53 #include <com/sun/star/lang/XTypeProvider.hpp>
54 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
55 #include <com/sun/star/io/XActiveDataSource.hpp>
56 #include <com/sun/star/io/XOutputStream.hpp>
57 #include <com/sun/star/svg/XSVGWriter.hpp>
58 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
59 #include <com/sun/star/xml/sax/Writer.hpp>
60 #include <com/sun/star/ucb/CommandAbortedException.hpp>
61 #include <unotools/ucbstreamhelper.hxx>
62 #include <unotools/localfilehelper.hxx>
63 #include <rtl/bootstrap.hxx>
64 #include <rtl/instance.hxx>
65 #include <vcl/metaact.hxx>
67 #include <boost/scoped_array.hpp>
70 #include "FilterConfigCache.hxx"
71 #include "graphicfilter_internal.hxx"
73 #define PMGCHUNG_msOG 0x6d734f47 // Microsoft Office Animated GIF
75 #ifndef DISABLE_DYNLOADING
76 #define IMPORT_FUNCTION_NAME "GraphicImport"
77 #define EXPORT_FUNCTION_NAME "GraphicExport"
80 using namespace ::com::sun::star
;
82 using comphelper::string::getTokenCount
;
84 typedef ::std::vector
< GraphicFilter
* > FilterList_impl
;
85 static FilterList_impl
* pFilterHdlList
= NULL
;
87 static ::osl::Mutex
& getListMutex()
89 static ::osl::Mutex s_aListProtection
;
90 return s_aListProtection
;
93 class ImpFilterOutputStream
: public ::cppu::WeakImplHelper1
< css::io::XOutputStream
>
99 virtual void SAL_CALL
writeBytes( const css::uno::Sequence
< sal_Int8
>& rData
)
100 throw (css::io::NotConnectedException
, css::io::BufferSizeExceededException
, css::io::IOException
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
101 { mrStm
.Write( rData
.getConstArray(), rData
.getLength() ); }
102 virtual void SAL_CALL
flush()
103 throw (css::io::NotConnectedException
, css::io::BufferSizeExceededException
, css::io::IOException
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
105 virtual void SAL_CALL
closeOutput() throw(std::exception
) SAL_OVERRIDE
{}
109 ImpFilterOutputStream( SvStream
& rStm
) : mrStm( rStm
) {}
110 virtual ~ImpFilterOutputStream() {}
113 #ifndef DISABLE_EXPORT
115 static bool DirEntryExists( const INetURLObject
& rObj
)
117 bool bExists
= false;
121 ::ucbhelper::Content
aCnt( rObj
.GetMainURL( INetURLObject::NO_DECODE
),
122 css::uno::Reference
< css::ucb::XCommandEnvironment
>(),
123 comphelper::getProcessComponentContext() );
125 bExists
= aCnt
.isDocument();
127 catch(const css::ucb::CommandAbortedException
&)
129 SAL_WARN( "vcl.filter", "CommandAbortedException" );
131 catch(const css::ucb::ContentCreationException
&)
133 SAL_WARN( "vcl.filter", "ContentCreationException" );
137 SAL_WARN( "vcl.filter", "Any other exception" );
142 static void KillDirEntry( const OUString
& rMainUrl
)
146 ::ucbhelper::Content
aCnt( rMainUrl
,
147 css::uno::Reference
< css::ucb::XCommandEnvironment
>(),
148 comphelper::getProcessComponentContext() );
150 aCnt
.executeCommand( "delete",
151 css::uno::makeAny( true ) );
153 catch(const css::ucb::CommandAbortedException
&)
155 SAL_WARN( "vcl.filter", "CommandAbortedException" );
159 SAL_WARN( "vcl.filter", "Any other exception" );
163 #endif // !DISABLE_EXPORT
167 sal_uInt8
* ImplSearchEntry( sal_uInt8
* pSource
, sal_uInt8
const * pDest
, sal_uLong nComp
, sal_uLong nSize
)
169 while ( nComp
-- >= nSize
)
172 for ( i
= 0; i
< nSize
; i
++ )
174 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
184 inline OUString
ImpGetExtension( const OUString
&rPath
)
187 INetURLObject
aURL( rPath
);
188 aExt
= aURL
.GetFileExtension().toAsciiUpperCase();
192 bool isPCT(SvStream
& rStream
, sal_uLong nStreamPos
, sal_uLong nStreamLen
)
195 // store number format
196 SvStreamEndian oldNumberFormat
= rStream
.GetEndian();
197 sal_uInt32 nOffset
; // in MS documents the pict format is used without the first 512 bytes
198 for ( nOffset
= 0; ( nOffset
<= 512 ) && ( ( nStreamPos
+ nOffset
+ 14 ) <= nStreamLen
); nOffset
+= 512 )
203 rStream
.Seek( nStreamPos
+ nOffset
);
204 // size of the pict in version 1 pict ( 2bytes) : ignored
206 // bounding box (bytes 2 -> 9)
207 rStream
.SetEndian(SvStreamEndian::BIG
);
208 rStream
.ReadInt16( y1
).ReadInt16( x1
).ReadInt16( y2
).ReadInt16( x2
);
209 rStream
.SetEndian(oldNumberFormat
); // reset format
211 if (x1
> x2
|| y1
> y2
|| // bad bdbox
212 (x1
== x2
&& y1
== y2
) || // 1 pixel picture
213 x2
-x1
> 2048 || y2
-y1
> 2048 ) // picture anormaly big
217 rStream
.Read( sBuf
,3 );
218 // see http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Imaging_With_QuickDraw/Appendix_A.pdf
219 // normal version 2 - page A23 and A24
220 if ( sBuf
[ 0 ] == 0x00 && sBuf
[ 1 ] == 0x11 && sBuf
[ 2 ] == 0x02)
222 // normal version 1 - page A25
223 else if (sBuf
[ 0 ] == 0x11 && sBuf
[ 1 ] == 0x01 && bdBoxOk
)
229 /*************************************************************************
231 * ImpPeekGraphicFormat()
234 * This function is two-fold:
235 * 1.) Start reading file, determine the file format:
238 * rFormatExtension - content matter
241 * Return value - true if success
242 * rFormatExtension - on success: normal file extension in capitals
243 * 2.) Start reading file, verify file format
246 * rFormatExtension - normal file extension in capitals
249 * Return value - false, if cannot verify the file type
250 * passed to the function
251 * true, when the format is PROBABLY verified or
252 * WHEN THE FORMAT IS NOT KNOWN!
254 *************************************************************************/
256 static bool ImpPeekGraphicFormat( SvStream
& rStream
, OUString
& rFormatExtension
, bool bTest
)
258 sal_uInt8 sFirstBytes
[ 256 ];
259 sal_uLong
nFirstLong(0), nSecondLong(0);
260 sal_uLong nStreamPos
= rStream
.Tell();
262 rStream
.Seek( STREAM_SEEK_TO_END
);
263 sal_uLong nStreamLen
= rStream
.Tell() - nStreamPos
;
264 rStream
.Seek( nStreamPos
);
268 SvLockBytes
* pLockBytes
= rStream
.GetLockBytes();
270 pLockBytes
->SetSynchronMode( true );
272 rStream
.Seek( STREAM_SEEK_TO_END
);
273 nStreamLen
= rStream
.Tell() - nStreamPos
;
274 rStream
.Seek( nStreamPos
);
279 return false; // this prevents at least a STL assertion
281 else if (nStreamLen
>= 256)
283 // load first 256 bytes into a buffer
284 sal_uLong nRead
= rStream
.Read(sFirstBytes
, 256);
290 nStreamLen
= rStream
.Read(sFirstBytes
, nStreamLen
);
294 if (rStream
.GetError())
297 for (sal_uLong i
= nStreamLen
; i
< 256; ++i
)
300 // Accommodate the first 8 bytes in nFirstLong, nSecondLong
302 for (int i
= 0; i
< 4; ++i
)
304 nFirstLong
=(nFirstLong
<<8)|(sal_uLong
)sFirstBytes
[i
];
305 nSecondLong
=(nSecondLong
<<8)|(sal_uLong
)sFirstBytes
[i
+4];
308 // The following variable is used when bTest == true. It remains false
309 // if the format (rFormatExtension) has not yet been set.
310 bool bSomethingTested
= false;
312 // Now the different formats are checked. The order *does* matter. e.g. a MET file
313 // could also go through the BMP test, however, a BMP file can hardly go through the MET test.
314 // So MET should be tested prior to BMP. However, theoretically a BMP file could conceivably
315 // go through the MET test. These problems are of course not only in MET and BMP.
316 // Therefore, in the case of a format check (bTest == true) we only test *exactly* this
317 // format. Everything else could have fatal consequences, for example if the user says it is
318 // a BMP file (and it is a BMP) file, and the file would go through the MET test ...
319 //--------------------------- MET ------------------------------------
320 if( !bTest
|| rFormatExtension
.startsWith( "MET" ) )
322 bSomethingTested
=true;
323 if( sFirstBytes
[2] == 0xd3 )
325 rStream
.SetEndian( SvStreamEndian::BIG
);
326 rStream
.Seek( nStreamPos
);
327 sal_uInt16 nFieldSize
;
330 rStream
.ReadUInt16( nFieldSize
).ReadUChar( nMagic
);
331 for (int i
=0; i
<3; i
++) {
332 if (nFieldSize
<6) { bOK
=false; break; }
333 if (nStreamLen
< rStream
.Tell() + nFieldSize
) { bOK
=false; break; }
334 rStream
.SeekRel(nFieldSize
-3);
335 rStream
.ReadUInt16( nFieldSize
).ReadUChar( nMagic
);
336 if (nMagic
!=0xd3) { bOK
=false; break; }
338 rStream
.SetEndian( SvStreamEndian::LITTLE
);
339 if (bOK
&& !rStream
.GetError()) {
340 rFormatExtension
= "MET";
346 //--------------------------- BMP ------------------------------------
347 if( !bTest
|| rFormatExtension
.startsWith( "BMP" ) )
351 bSomethingTested
=true;
353 // We're possibly also able to read an OS/2 bitmap array
354 // ('BA'), therefore we must adjust the offset to discover the
355 // first bitmap in the array
356 if ( sFirstBytes
[0] == 0x42 && sFirstBytes
[1] == 0x41 )
361 // Now we initially test on 'BM'
362 if ( sFirstBytes
[0+nOffs
]==0x42 && sFirstBytes
[1+nOffs
]==0x4d )
365 // OS/2 can set the Reserved flags to a value other than 0
366 // (which they really should not do...);
367 // In this case we test the size of the BmpInfoHeaders
368 if ( ( sFirstBytes
[6+nOffs
]==0x00 &&
369 sFirstBytes
[7+nOffs
]==0x00 &&
370 sFirstBytes
[8+nOffs
]==0x00 &&
371 sFirstBytes
[9+nOffs
]==0x00 ) ||
372 sFirstBytes
[14+nOffs
] == 0x28 ||
373 sFirstBytes
[14+nOffs
] == 0x0c )
375 rFormatExtension
= "BMP";
381 //--------------------------- WMF/EMF ------------------------------------
384 rFormatExtension
.startsWith( "WMF" ) ||
385 rFormatExtension
.startsWith( "EMF" ) )
387 bSomethingTested
= true;
389 if ( nFirstLong
==0xd7cdc69a || nFirstLong
==0x01000900 )
391 rFormatExtension
= "WMF";
394 else if( nFirstLong
== 0x01000000 && sFirstBytes
[ 40 ] == 0x20 && sFirstBytes
[ 41 ] == 0x45 &&
395 sFirstBytes
[ 42 ] == 0x4d && sFirstBytes
[ 43 ] == 0x46 )
397 rFormatExtension
= "EMF";
402 //--------------------------- PCX ------------------------------------
403 if( !bTest
|| rFormatExtension
.startsWith( "PCX" ) )
405 bSomethingTested
=true;
406 if (sFirstBytes
[0]==0x0a)
408 sal_uInt8 nVersion
=sFirstBytes
[1];
409 sal_uInt8 nEncoding
=sFirstBytes
[2];
410 if( ( nVersion
==0 || nVersion
==2 || nVersion
==3 || nVersion
==5 ) && nEncoding
<=1 )
412 rFormatExtension
= "PCX";
418 //--------------------------- TIF ------------------------------------
419 if( !bTest
|| rFormatExtension
.startsWith( "TIF" ) )
421 bSomethingTested
=true;
422 if ( nFirstLong
==0x49492a00 || nFirstLong
==0x4d4d002a )
424 rFormatExtension
= "TIF";
429 //--------------------------- GIF ------------------------------------
430 if( !bTest
|| rFormatExtension
.startsWith( "GIF" ) )
432 bSomethingTested
=true;
433 if ( nFirstLong
==0x47494638 && (sFirstBytes
[4]==0x37 || sFirstBytes
[4]==0x39) && sFirstBytes
[5]==0x61 )
435 rFormatExtension
= "GIF";
440 //--------------------------- PNG ------------------------------------
441 if( !bTest
|| rFormatExtension
.startsWith( "PNG" ) )
443 bSomethingTested
=true;
444 if (nFirstLong
==0x89504e47 && nSecondLong
==0x0d0a1a0a)
446 rFormatExtension
= "PNG";
451 //--------------------------- JPG ------------------------------------
452 if( !bTest
|| rFormatExtension
.startsWith( "JPG" ) )
454 bSomethingTested
=true;
455 if ( ( nFirstLong
==0xffd8ffe0 && sFirstBytes
[6]==0x4a && sFirstBytes
[7]==0x46 && sFirstBytes
[8]==0x49 && sFirstBytes
[9]==0x46 ) ||
456 ( nFirstLong
==0xffd8fffe ) || ( 0xffd8ff00 == ( nFirstLong
& 0xffffff00 ) ) )
458 rFormatExtension
= "JPG";
463 //--------------------------- SVM ------------------------------------
464 if( !bTest
|| rFormatExtension
.startsWith( "SVM" ) )
466 bSomethingTested
=true;
467 if( nFirstLong
==0x53564744 && sFirstBytes
[4]==0x49 )
469 rFormatExtension
= "SVM";
472 else if( sFirstBytes
[0]==0x56 && sFirstBytes
[1]==0x43 && sFirstBytes
[2]==0x4C &&
473 sFirstBytes
[3]==0x4D && sFirstBytes
[4]==0x54 && sFirstBytes
[5]==0x46 )
475 rFormatExtension
= "SVM";
480 //--------------------------- PCD ------------------------------------
481 if( !bTest
|| rFormatExtension
.startsWith( "PCD" ) )
483 bSomethingTested
= true;
484 if( nStreamLen
>= 2055 )
487 rStream
.Seek( nStreamPos
+ 2048 );
488 rStream
.Read( sBuf
, 7 );
490 if( strncmp( sBuf
, "PCD_IPI", 7 ) == 0 )
492 rFormatExtension
= "PCD";
498 //--------------------------- PSD ------------------------------------
499 if( !bTest
|| rFormatExtension
.startsWith( "PSD" ) )
501 bSomethingTested
= true;
502 if ( ( nFirstLong
== 0x38425053 ) && ( (nSecondLong
>> 16 ) == 1 ) )
504 rFormatExtension
= "PSD";
509 //--------------------------- EPS ------------------------------------
510 if( !bTest
|| rFormatExtension
.startsWith( "EPS" ) )
512 bSomethingTested
= true;
513 if ( ( nFirstLong
== 0xC5D0D3C6 ) || ( ImplSearchEntry( sFirstBytes
, reinterpret_cast<sal_uInt8
const *>("%!PS-Adobe"), 10, 10 ) &&
514 ImplSearchEntry( &sFirstBytes
[15], reinterpret_cast<sal_uInt8
const *>("EPS"), 3, 3 ) ) )
516 rFormatExtension
= "EPS";
521 //--------------------------- DXF ------------------------------------
522 if( !bTest
|| rFormatExtension
.startsWith( "DXF" ) )
524 // Binary DXF File Format
525 if( strncmp( reinterpret_cast<char*>(sFirstBytes
), "AutoCAD Binary DXF", 18 ) == 0 )
527 rFormatExtension
= "DXF";
531 // ASCII DXF File Format
533 while (i
<256 && sFirstBytes
[i
]<=32)
536 if (i
<256 && sFirstBytes
[i
]=='0')
540 // only now do we have sufficient data to make a judgement
541 // based on a '0' + 'SECTION' == DXF argument
542 bSomethingTested
=true;
544 while( i
<256 && sFirstBytes
[i
]<=32 )
547 if (i
+7<256 && (strncmp(reinterpret_cast<char*>(sFirstBytes
+i
),"SECTION",7)==0))
549 rFormatExtension
= "DXF";
556 //--------------------------- PCT ------------------------------------
557 if( !bTest
|| rFormatExtension
.startsWith( "PCT" ) )
559 bSomethingTested
= true;
560 if (isPCT(rStream
, nStreamPos
, nStreamLen
))
562 rFormatExtension
= "PCT";
567 //------------------------- PBM + PGM + PPM ---------------------------
569 rFormatExtension
.startsWith( "PBM" ) ||
570 rFormatExtension
.startsWith( "PGM" ) ||
571 rFormatExtension
.startsWith( "PPM" ) )
573 bSomethingTested
=true;
574 if ( sFirstBytes
[ 0 ] == 'P' )
576 switch( sFirstBytes
[ 1 ] )
580 rFormatExtension
= "PBM";
585 rFormatExtension
= "PGM";
590 rFormatExtension
= "PPM";
596 //--------------------------- RAS( SUN RasterFile )------------------
597 if( !bTest
|| rFormatExtension
.startsWith( "RAS" ) )
599 bSomethingTested
=true;
600 if( nFirstLong
== 0x59a66a95 )
602 rFormatExtension
= "RAS";
607 //--------------------------- XPM ------------------------------------
610 bSomethingTested
= true;
611 if( ImplSearchEntry( sFirstBytes
, reinterpret_cast<sal_uInt8
const *>("/* XPM */"), 256, 9 ) )
613 rFormatExtension
= "XPM";
617 else if( rFormatExtension
.startsWith( "XPM" ) )
619 bSomethingTested
= true;
623 //--------------------------- XBM ------------------------------------
626 sal_uLong nSize
= ( nStreamLen
> 2048 ) ? 2048 : nStreamLen
;
627 boost::scoped_array
<sal_uInt8
> pBuf(new sal_uInt8
[ nSize
]);
629 rStream
.Seek( nStreamPos
);
630 rStream
.Read( pBuf
.get(), nSize
);
631 sal_uInt8
* pPtr
= ImplSearchEntry( pBuf
.get(), reinterpret_cast<sal_uInt8
const *>("#define"), nSize
, 7 );
635 if( ImplSearchEntry( pPtr
, reinterpret_cast<sal_uInt8
const *>("_width"), pBuf
.get() + nSize
- pPtr
, 6 ) )
637 rFormatExtension
= "XBM";
642 else if( rFormatExtension
.startsWith( "XBM" ) )
644 bSomethingTested
= true;
648 //--------------------------- SVG ------------------------------------
651 sal_uInt8
* pCheckArray
= sFirstBytes
;
652 sal_uLong nCheckSize
= nStreamLen
< 256 ? nStreamLen
: 256;
654 sal_uInt8 sExtendedOrDecompressedFirstBytes
[2048];
655 sal_uLong nDecompressedSize
= nCheckSize
;
659 // check if it is gzipped -> svgz
660 if(sFirstBytes
[0] == 0x1F && sFirstBytes
[1] == 0x8B)
663 rStream
.Seek(nStreamPos
);
664 aCodec
.BeginCompression(ZCODEC_DEFAULT_COMPRESSION
, false, true);
665 nDecompressedSize
= aCodec
.Read(rStream
, sExtendedOrDecompressedFirstBytes
, 2048);
666 nCheckSize
= nDecompressedSize
< 256 ? nDecompressedSize
: 256;
667 aCodec
.EndCompression();
668 pCheckArray
= sExtendedOrDecompressedFirstBytes
;
676 // #119176# SVG files which have no xml header at all have shown up this is optional
677 if( ImplSearchEntry(pCheckArray
, reinterpret_cast<sal_uInt8
const *>("<?xml"), nCheckSize
, 5 ) // is it xml
678 && ImplSearchEntry(pCheckArray
, reinterpret_cast<sal_uInt8
const *>("version"), nCheckSize
, 7 )) // does it have a version (required for xml)
681 // check for DOCTYPE svg combination
682 if( ImplSearchEntry(pCheckArray
, reinterpret_cast<sal_uInt8
const *>("DOCTYPE"), nCheckSize
, 7 ) // 'DOCTYPE' is there
683 && ImplSearchEntry(pCheckArray
, reinterpret_cast<sal_uInt8
const *>("svg"), nCheckSize
, 3 )) // 'svg' is there
689 // check for svg element in 1st 256 bytes
690 if(!bIsSvg
&& ImplSearchEntry(pCheckArray
, reinterpret_cast<sal_uInt8
const *>("<svg"), nCheckSize
, 4 )) // '<svg'
695 // extended search for svg element
698 // it's a xml, look for '<svg' in full file. Should not happen too
699 // often since the tests above will handle most cases, but can happen
700 // with Svg files containing big comment headers or Svg as the host
703 pCheckArray
= sExtendedOrDecompressedFirstBytes
;
707 nCheckSize
= nDecompressedSize
< 2048 ? nDecompressedSize
: 2048;
711 nCheckSize
= nStreamLen
< 2048 ? nStreamLen
: 2048;
712 rStream
.Seek(nStreamPos
);
713 nCheckSize
= rStream
.Read(sExtendedOrDecompressedFirstBytes
, nCheckSize
);
716 if(ImplSearchEntry(pCheckArray
, reinterpret_cast<sal_uInt8
const *>("<svg"), nCheckSize
, 4)) // '<svg'
724 rFormatExtension
= "SVG";
728 else if( rFormatExtension
.startsWith( "SVG" ) )
730 bSomethingTested
= true;
734 //--------------------------- TGA ------------------------------------
735 if( !bTest
|| rFormatExtension
.startsWith( "TGA" ) )
737 bSomethingTested
= true;
739 // just a simple test for the extension
740 if( rFormatExtension
.startsWith( "TGA" ) )
744 //--------------------------- SGV ------------------------------------
745 if( !bTest
|| rFormatExtension
.startsWith( "SGV" ) )
747 bSomethingTested
= true;
749 // just a simple test for the extension
750 if( rFormatExtension
.startsWith( "SGV" ) )
754 //--------------------------- SGF ------------------------------------
755 if( !bTest
|| rFormatExtension
.startsWith( "SGF" ) )
757 bSomethingTested
=true;
758 if( sFirstBytes
[ 0 ] == 'J' && sFirstBytes
[ 1 ] == 'J' )
760 rFormatExtension
= "SGF";
765 if(!bTest
|| rFormatExtension
.startsWith( "MOV" ))
767 if ((sFirstBytes
[ 4 ] == 'f' && sFirstBytes
[ 5 ] == 't' && sFirstBytes
[ 6 ] == 'y' &&
768 sFirstBytes
[ 7 ] == 'p' && sFirstBytes
[ 8 ] == 'q' && sFirstBytes
[ 9 ] == 't') ||
769 (sFirstBytes
[ 4 ] == 'm' && sFirstBytes
[ 5 ] == 'o' && sFirstBytes
[ 6 ] == 'o' &&
770 sFirstBytes
[ 7 ] == 'v' && sFirstBytes
[ 11 ] == 'l' && sFirstBytes
[ 12 ] == 'm'))
772 bSomethingTested
=true;
773 rFormatExtension
= "MOV";
778 return bTest
&& !bSomethingTested
;
781 sal_uInt16
GraphicFilter::ImpTestOrFindFormat( const OUString
& rPath
, SvStream
& rStream
, sal_uInt16
& rFormat
)
783 // determine or check the filter/format by reading into it
784 if( rFormat
== GRFILTER_FORMAT_DONTKNOW
)
787 if( ImpPeekGraphicFormat( rStream
, aFormatExt
, false ) )
789 rFormat
= pConfig
->GetImportFormatNumberForExtension( aFormatExt
);
790 if( rFormat
!= GRFILTER_FORMAT_DONTKNOW
)
793 // determine filter by file extension
794 if( !rPath
.isEmpty() )
796 OUString
aExt( ImpGetExtension( rPath
) );
797 rFormat
= pConfig
->GetImportFormatNumberForExtension( aExt
);
798 if( rFormat
!= GRFILTER_FORMAT_DONTKNOW
)
801 return GRFILTER_FORMATERROR
;
805 OUString
aTmpStr( pConfig
->GetImportFormatExtension( rFormat
) );
806 aTmpStr
= aTmpStr
.toAsciiUpperCase();
807 if( !ImpPeekGraphicFormat( rStream
, aTmpStr
, true ) )
808 return GRFILTER_FORMATERROR
;
809 if ( pConfig
->GetImportFormatExtension( rFormat
).equalsIgnoreAsciiCase( "pcd" ) )
811 sal_Int32 nBase
= 2; // default Base0
812 if ( pConfig
->GetImportFilterType( rFormat
).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base4" ) )
814 else if ( pConfig
->GetImportFilterType( rFormat
).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base16" ) )
816 OUString
aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
817 FilterConfigItem
aFilterConfigItem( aFilterConfigPath
);
818 aFilterConfigItem
.WriteInt32( "Resolution", nBase
);
825 #ifndef DISABLE_EXPORT
827 static Graphic
ImpGetScaledGraphic( const Graphic
& rGraphic
, FilterConfigItem
& rConfigItem
)
831 std::unique_ptr
<ResMgr
> xResMgr(ResMgr::CreateResMgr( "svt", Application::GetSettings().GetUILanguageTag() ));
833 sal_Int32 nLogicalWidth
= rConfigItem
.ReadInt32( "LogicalWidth", 0 );
834 sal_Int32 nLogicalHeight
= rConfigItem
.ReadInt32( "LogicalHeight", 0 );
836 if ( rGraphic
.GetType() != GRAPHIC_NONE
)
838 sal_Int32 nMode
= rConfigItem
.ReadInt32( "ExportMode", -1 );
840 if ( nMode
== -1 ) // the property is not there, this is possible, if the graphic filter
841 { // is called via UnoGraphicExporter and not from a graphic export Dialog
842 nMode
= 0; // then we are defaulting this mode to 0
843 if ( nLogicalWidth
|| nLogicalHeight
)
848 Size
aPrefSize( rGraphic
.GetPrefSize() );
849 MapMode
aPrefMapMode( rGraphic
.GetPrefMapMode() );
850 if ( aPrefMapMode
== MAP_PIXEL
)
851 aOriginalSize
= Application::GetDefaultDevice()->PixelToLogic( aPrefSize
, MAP_100TH_MM
);
853 aOriginalSize
= OutputDevice::LogicToLogic( aPrefSize
, aPrefMapMode
, MAP_100TH_MM
);
854 if ( !nLogicalWidth
)
855 nLogicalWidth
= aOriginalSize
.Width();
856 if ( !nLogicalHeight
)
857 nLogicalHeight
= aOriginalSize
.Height();
858 if( rGraphic
.GetType() == GRAPHIC_BITMAP
)
864 Bitmap
aBitmap( rGraphic
.GetBitmap() );
865 MapMode
aMap( MAP_100TH_INCH
);
867 sal_Int32 nDPI
= rConfigItem
.ReadInt32( "Resolution", 75 );
868 Fraction
aFrac( 1, std::min( std::max( nDPI
, sal_Int32( 75 ) ), sal_Int32( 600 ) ) );
870 aMap
.SetScaleX( aFrac
);
871 aMap
.SetScaleY( aFrac
);
873 Size aOldSize
= aBitmap
.GetSizePixel();
875 aGraphic
.SetPrefMapMode( aMap
);
876 aGraphic
.SetPrefSize( Size( aOldSize
.Width() * 100,
877 aOldSize
.Height() * 100 ) );
880 else if( nMode
== 2 )
883 aGraphic
.SetPrefMapMode( MapMode( MAP_100TH_MM
) );
884 aGraphic
.SetPrefSize( Size( nLogicalWidth
, nLogicalHeight
) );
889 sal_Int32 nColors
= rConfigItem
.ReadInt32( "Color", 0 ); // #92767#
890 if ( nColors
) // graphic conversion necessary ?
892 BitmapEx
aBmpEx( aGraphic
.GetBitmapEx() );
893 aBmpEx
.Convert( (BmpConversion
)nColors
); // the entries in the xml section have the same meaning as
894 aGraphic
= aBmpEx
; // they have in the BmpConversion enum, so it should be
895 } // allowed to cast them
899 if( ( nMode
== 1 ) || ( nMode
== 2 ) )
901 GDIMetaFile
aMtf( rGraphic
.GetGDIMetaFile() );
902 css::awt::Size
aDefaultSize( 10000, 10000 );
903 Size
aNewSize( OutputDevice::LogicToLogic( Size( nLogicalWidth
, nLogicalHeight
), MAP_100TH_MM
, aMtf
.GetPrefMapMode() ) );
905 if( aNewSize
.Width() && aNewSize
.Height() )
907 const Size
aPreferredSize( aMtf
.GetPrefSize() );
908 aMtf
.Scale( Fraction( aNewSize
.Width(), aPreferredSize
.Width() ),
909 Fraction( aNewSize
.Height(), aPreferredSize
.Height() ) );
911 aGraphic
= Graphic( aMtf
);
926 static OUString
ImpCreateFullFilterPath( const OUString
& rPath
, const OUString
& rFilterName
)
930 ::osl::FileBase::getFileURLFromSystemPath( rPath
, aPathURL
);
933 OUString aSystemPath
;
934 ::osl::FileBase::getSystemPathFromFileURL( aPathURL
, aSystemPath
);
935 aSystemPath
+= rFilterName
;
937 return OUString( aSystemPath
);
940 class ImpFilterLibCache
;
942 struct ImpFilterLibCacheEntry
944 ImpFilterLibCacheEntry
* mpNext
;
945 #ifndef DISABLE_DYNLOADING
946 osl::Module maLibrary
;
948 OUString maFiltername
;
949 PFilterCall mpfnImport
;
951 ImpFilterLibCacheEntry( const OUString
& rPathname
, const OUString
& rFiltername
);
952 bool operator==( const OUString
& rFiltername
) const { return maFiltername
== rFiltername
; }
954 PFilterCall
GetImportFunction();
957 ImpFilterLibCacheEntry::ImpFilterLibCacheEntry( const OUString
& rPathname
, const OUString
& rFiltername
) :
959 #ifndef DISABLE_DYNLOADING
960 maLibrary ( rPathname
),
962 maFiltername ( rFiltername
),
965 #ifdef DISABLE_DYNLOADING
970 #ifdef DISABLE_DYNLOADING
972 extern "C" bool icdGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
973 extern "C" bool idxGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
974 extern "C" bool imeGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
975 extern "C" bool ipbGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
976 extern "C" bool ipdGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
977 extern "C" bool ipsGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
978 extern "C" bool iptGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
979 extern "C" bool ipxGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
980 extern "C" bool iraGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
981 extern "C" bool itgGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
982 extern "C" bool itiGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
986 PFilterCall
ImpFilterLibCacheEntry::GetImportFunction()
990 #ifndef DISABLE_DYNLOADING
991 mpfnImport
= reinterpret_cast<PFilterCall
>(maLibrary
.getFunctionSymbol(OUString(IMPORT_FUNCTION_NAME
)));
993 if( maFiltername
.equalsAscii( "icd" ) )
994 mpfnImport
= icdGraphicImport
;
995 else if( maFiltername
.equalsAscii( "idx" ) )
996 mpfnImport
= idxGraphicImport
;
997 else if( maFiltername
.equalsAscii( "ime" ) )
998 mpfnImport
= imeGraphicImport
;
999 else if( maFiltername
.equalsAscii( "ipb" ) )
1000 mpfnImport
= ipbGraphicImport
;
1001 else if( maFiltername
.equalsAscii( "ipd" ) )
1002 mpfnImport
= ipdGraphicImport
;
1003 else if( maFiltername
.equalsAscii( "ips" ) )
1004 mpfnImport
= ipsGraphicImport
;
1005 else if( maFiltername
.equalsAscii( "ipt" ) )
1006 mpfnImport
= iptGraphicImport
;
1007 else if( maFiltername
.equalsAscii( "ipx" ) )
1008 mpfnImport
= ipxGraphicImport
;
1009 else if( maFiltername
.equalsAscii( "ira" ) )
1010 mpfnImport
= iraGraphicImport
;
1011 else if( maFiltername
.equalsAscii( "itg" ) )
1012 mpfnImport
= itgGraphicImport
;
1013 else if( maFiltername
.equalsAscii( "iti" ) )
1014 mpfnImport
= itiGraphicImport
;
1021 class ImpFilterLibCache
1023 ImpFilterLibCacheEntry
* mpFirst
;
1024 ImpFilterLibCacheEntry
* mpLast
;
1027 ImpFilterLibCache();
1028 ~ImpFilterLibCache();
1030 ImpFilterLibCacheEntry
* GetFilter( const OUString
& rFilterPath
, const OUString
& rFiltername
);
1033 ImpFilterLibCache::ImpFilterLibCache() :
1039 ImpFilterLibCache::~ImpFilterLibCache()
1041 ImpFilterLibCacheEntry
* pEntry
= mpFirst
;
1044 ImpFilterLibCacheEntry
* pNext
= pEntry
->mpNext
;
1050 ImpFilterLibCacheEntry
* ImpFilterLibCache::GetFilter( const OUString
& rFilterPath
, const OUString
& rFilterName
)
1052 ImpFilterLibCacheEntry
* pEntry
= mpFirst
;
1056 if( *pEntry
== rFilterName
)
1059 pEntry
= pEntry
->mpNext
;
1063 OUString
aPhysicalName( ImpCreateFullFilterPath( rFilterPath
, rFilterName
) );
1064 pEntry
= new ImpFilterLibCacheEntry( aPhysicalName
, rFilterName
);
1065 #ifndef DISABLE_DYNLOADING
1066 if ( pEntry
->maLibrary
.is() )
1070 mpFirst
= mpLast
= pEntry
;
1072 mpLast
= mpLast
->mpNext
= pEntry
;
1074 #ifndef DISABLE_DYNLOADING
1085 namespace { struct Cache
: public rtl::Static
<ImpFilterLibCache
, Cache
> {}; }
1087 GraphicFilter::GraphicFilter( bool bConfig
)
1089 , bUseConfig(bConfig
)
1095 GraphicFilter::~GraphicFilter()
1098 ::osl::MutexGuard
aGuard( getListMutex() );
1100 FilterList_impl::iterator it
= pFilterHdlList
->begin();
1101 it
!= pFilterHdlList
->end();
1106 pFilterHdlList
->erase( it
);
1110 if( pFilterHdlList
->empty() )
1112 delete pFilterHdlList
, pFilterHdlList
= NULL
;
1120 void GraphicFilter::ImplInit()
1123 ::osl::MutexGuard
aGuard( getListMutex() );
1125 if ( !pFilterHdlList
)
1127 pFilterHdlList
= new FilterList_impl
;
1128 pConfig
= new FilterConfigCache( bUseConfig
);
1131 pConfig
= pFilterHdlList
->front()->pConfig
;
1133 pFilterHdlList
->push_back( this );
1138 OUString
url("$BRAND_BASE_DIR/" LIBO_LIB_FOLDER
);
1139 rtl::Bootstrap::expandMacros(url
); //TODO: detect failure
1140 utl::LocalFileHelper::ConvertURLToPhysicalName(url
, aFilterPath
);
1143 pErrorEx
= new FilterErrorEx
;
1147 sal_uLong
GraphicFilter::ImplSetError( sal_uLong nError
, const SvStream
* pStm
)
1149 pErrorEx
->nFilterError
= nError
;
1150 pErrorEx
->nStreamError
= pStm
? pStm
->GetError() : ERRCODE_NONE
;
1154 sal_uInt16
GraphicFilter::GetImportFormatCount()
1156 return pConfig
->GetImportFormatCount();
1159 sal_uInt16
GraphicFilter::GetImportFormatNumber( const OUString
& rFormatName
)
1161 return pConfig
->GetImportFormatNumber( rFormatName
);
1164 sal_uInt16
GraphicFilter::GetImportFormatNumberForMediaType( const OUString
& rMediaType
)
1166 return pConfig
->GetImportFormatNumberForMediaType( rMediaType
);
1169 sal_uInt16
GraphicFilter::GetImportFormatNumberForShortName( const OUString
& rShortName
)
1171 return pConfig
->GetImportFormatNumberForShortName( rShortName
);
1174 sal_uInt16
GraphicFilter::GetImportFormatNumberForTypeName( const OUString
& rType
)
1176 return pConfig
->GetImportFormatNumberForTypeName( rType
);
1179 OUString
GraphicFilter::GetImportFormatName( sal_uInt16 nFormat
)
1181 return pConfig
->GetImportFormatName( nFormat
);
1184 OUString
GraphicFilter::GetImportFormatTypeName( sal_uInt16 nFormat
)
1186 return pConfig
->GetImportFilterTypeName( nFormat
);
1189 OUString
GraphicFilter::GetImportFormatMediaType( sal_uInt16 nFormat
)
1191 return pConfig
->GetImportFormatMediaType( nFormat
);
1194 OUString
GraphicFilter::GetImportFormatShortName( sal_uInt16 nFormat
)
1196 return pConfig
->GetImportFormatShortName( nFormat
);
1199 OUString
GraphicFilter::GetImportOSFileType( sal_uInt16
)
1201 OUString aOSFileType
;
1205 OUString
GraphicFilter::GetImportWildcard( sal_uInt16 nFormat
, sal_Int32 nEntry
)
1207 return pConfig
->GetImportWildcard( nFormat
, nEntry
);
1210 bool GraphicFilter::IsImportPixelFormat( sal_uInt16 nFormat
)
1212 return pConfig
->IsImportPixelFormat( nFormat
);
1215 sal_uInt16
GraphicFilter::GetExportFormatCount()
1217 return pConfig
->GetExportFormatCount();
1220 sal_uInt16
GraphicFilter::GetExportFormatNumber( const OUString
& rFormatName
)
1222 return pConfig
->GetExportFormatNumber( rFormatName
);
1225 sal_uInt16
GraphicFilter::GetExportFormatNumberForMediaType( const OUString
& rMediaType
)
1227 return pConfig
->GetExportFormatNumberForMediaType( rMediaType
);
1230 sal_uInt16
GraphicFilter::GetExportFormatNumberForShortName( const OUString
& rShortName
)
1232 return pConfig
->GetExportFormatNumberForShortName( rShortName
);
1235 OUString
GraphicFilter::GetExportInternalFilterName( sal_uInt16 nFormat
)
1237 return pConfig
->GetExportInternalFilterName( nFormat
);
1240 sal_uInt16
GraphicFilter::GetExportFormatNumberForTypeName( const OUString
& rType
)
1242 return pConfig
->GetExportFormatNumberForTypeName( rType
);
1245 OUString
GraphicFilter::GetExportFormatName( sal_uInt16 nFormat
)
1247 return pConfig
->GetExportFormatName( nFormat
);
1250 OUString
GraphicFilter::GetExportFormatTypeName( sal_uInt16 nFormat
)
1252 return pConfig
->GetExportFilterTypeName( nFormat
);
1255 OUString
GraphicFilter::GetExportFormatMediaType( sal_uInt16 nFormat
)
1257 return pConfig
->GetExportFormatMediaType( nFormat
);
1260 OUString
GraphicFilter::GetExportFormatShortName( sal_uInt16 nFormat
)
1262 return pConfig
->GetExportFormatShortName( nFormat
);
1265 OUString
GraphicFilter::GetExportOSFileType( sal_uInt16
)
1267 OUString aOSFileType
;
1271 OUString
GraphicFilter::GetExportWildcard( sal_uInt16 nFormat
, sal_Int32 nEntry
)
1273 return pConfig
->GetExportWildcard( nFormat
, nEntry
);
1276 bool GraphicFilter::IsExportPixelFormat( sal_uInt16 nFormat
)
1278 return pConfig
->IsExportPixelFormat( nFormat
);
1281 sal_uInt16
GraphicFilter::CanImportGraphic( const INetURLObject
& rPath
,
1282 sal_uInt16 nFormat
, sal_uInt16
* pDeterminedFormat
)
1284 sal_uInt16 nRetValue
= GRFILTER_FORMATERROR
;
1285 DBG_ASSERT( rPath
.GetProtocol() != INetProtocol::NotValid
, "GraphicFilter::CanImportGraphic() : ProtType == INetProtocol::NotValid" );
1287 OUString
aMainUrl( rPath
.GetMainURL( INetURLObject::NO_DECODE
) );
1288 std::unique_ptr
<SvStream
> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl
, StreamMode::READ
| StreamMode::SHARE_DENYNONE
));
1291 nRetValue
= CanImportGraphic( aMainUrl
, *xStream
, nFormat
, pDeterminedFormat
);
1296 sal_uInt16
GraphicFilter::CanImportGraphic( const OUString
& rMainUrl
, SvStream
& rIStream
,
1297 sal_uInt16 nFormat
, sal_uInt16
* pDeterminedFormat
)
1299 sal_uLong nStreamPos
= rIStream
.Tell();
1300 sal_uInt16 nRes
= ImpTestOrFindFormat( rMainUrl
, rIStream
, nFormat
);
1302 rIStream
.Seek(nStreamPos
);
1304 if( nRes
==GRFILTER_OK
&& pDeterminedFormat
!=NULL
)
1305 *pDeterminedFormat
= nFormat
;
1307 return (sal_uInt16
) ImplSetError( nRes
, &rIStream
);
1310 //SJ: TODO, we need to create a GraphicImporter component
1311 sal_uInt16
GraphicFilter::ImportGraphic( Graphic
& rGraphic
, const INetURLObject
& rPath
,
1312 sal_uInt16 nFormat
, sal_uInt16
* pDeterminedFormat
, GraphicFilterImportFlags nImportFlags
)
1314 sal_uInt16 nRetValue
= GRFILTER_FORMATERROR
;
1315 DBG_ASSERT( rPath
.GetProtocol() != INetProtocol::NotValid
, "GraphicFilter::ImportGraphic() : ProtType == INetProtocol::NotValid" );
1317 OUString
aMainUrl( rPath
.GetMainURL( INetURLObject::NO_DECODE
) );
1318 std::unique_ptr
<SvStream
> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl
, StreamMode::READ
| StreamMode::SHARE_DENYNONE
));
1321 nRetValue
= ImportGraphic( rGraphic
, aMainUrl
, *xStream
, nFormat
, pDeterminedFormat
, nImportFlags
);
1326 sal_uInt16
GraphicFilter::ImportGraphic( Graphic
& rGraphic
, const OUString
& rPath
, SvStream
& rIStream
,
1327 sal_uInt16 nFormat
, sal_uInt16
* pDeterminedFormat
, GraphicFilterImportFlags nImportFlags
, WMF_EXTERNALHEADER
*pExtHeader
)
1329 return ImportGraphic( rGraphic
, rPath
, rIStream
, nFormat
, pDeterminedFormat
, nImportFlags
, NULL
, pExtHeader
);
1332 sal_uInt16
GraphicFilter::ImportGraphic( Graphic
& rGraphic
, const OUString
& rPath
, SvStream
& rIStream
,
1333 sal_uInt16 nFormat
, sal_uInt16
* pDeterminedFormat
, GraphicFilterImportFlags nImportFlags
,
1334 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
>* pFilterData
,
1335 WMF_EXTERNALHEADER
*pExtHeader
)
1337 OUString aFilterName
;
1338 sal_uLong nStreamBegin
;
1340 GraphicReader
* pContext
= rGraphic
.GetContext();
1341 GfxLinkType eLinkType
= GFX_LINK_TYPE_NONE
;
1342 bool bDummyContext
= ( pContext
== reinterpret_cast<GraphicReader
*>(1) );
1343 const bool bLinkSet
= rGraphic
.IsLink();
1344 FilterConfigItem
* pFilterConfigItem
= NULL
;
1346 Size
aPreviewSizeHint( 0, 0 );
1347 bool bAllowPartialStreamRead
= false;
1348 bool bCreateNativeLink
= true;
1350 sal_uInt8
* pGraphicContent
= NULL
;
1351 bool bGraphicContentOwned
= true;
1352 sal_Int32 nGraphicContentSize
= 0;
1359 for ( i
= 0; i
< pFilterData
->getLength(); i
++ )
1361 if ( (*pFilterData
)[ i
].Name
== "PreviewSizeHint" )
1364 if ( (*pFilterData
)[ i
].Value
>>= aSize
)
1366 aPreviewSizeHint
= Size( aSize
.Width
, aSize
.Height
);
1367 if ( aSize
.Width
|| aSize
.Height
)
1368 nImportFlags
|= GraphicFilterImportFlags::ForPreview
;
1370 nImportFlags
&=~GraphicFilterImportFlags::ForPreview
;
1373 else if ( (*pFilterData
)[ i
].Name
== "AllowPartialStreamRead" )
1375 (*pFilterData
)[ i
].Value
>>= bAllowPartialStreamRead
;
1376 if ( bAllowPartialStreamRead
)
1377 nImportFlags
|= GraphicFilterImportFlags::AllowPartialStreamRead
;
1379 nImportFlags
&=~GraphicFilterImportFlags::AllowPartialStreamRead
;
1381 else if ( (*pFilterData
)[ i
].Name
== "CreateNativeLink" )
1383 (*pFilterData
)[ i
].Value
>>= bCreateNativeLink
;
1388 if( !pContext
|| bDummyContext
)
1392 rGraphic
.SetContext( NULL
);
1396 nStreamBegin
= rIStream
.Tell();
1399 nStatus
= ImpTestOrFindFormat( rPath
, rIStream
, nFormat
);
1400 // if pending, return GRFILTER_OK in order to request more bytes
1401 if( rIStream
.GetError() == ERRCODE_IO_PENDING
)
1403 rGraphic
.SetContext( reinterpret_cast<GraphicReader
*>(1) );
1404 rIStream
.ResetError();
1405 rIStream
.Seek( nStreamBegin
);
1406 return (sal_uInt16
) ImplSetError( GRFILTER_OK
);
1409 rIStream
.Seek( nStreamBegin
);
1411 if( ( nStatus
!= GRFILTER_OK
) || rIStream
.GetError() )
1412 return (sal_uInt16
) ImplSetError( ( nStatus
!= GRFILTER_OK
) ? nStatus
: GRFILTER_OPENERROR
, &rIStream
);
1414 if( pDeterminedFormat
)
1415 *pDeterminedFormat
= nFormat
;
1417 aFilterName
= pConfig
->GetImportFilterName( nFormat
);
1421 if( pContext
&& !bDummyContext
)
1422 aFilterName
= pContext
->GetUpperFilterName();
1425 nStatus
= GRFILTER_OK
;
1429 if ( pConfig
->IsImportInternalFilter( nFormat
) )
1431 if( aFilterName
.equalsIgnoreAsciiCase( IMP_GIF
) )
1433 if( rGraphic
.GetContext() == reinterpret_cast<GraphicReader
*>(1) )
1434 rGraphic
.SetContext( NULL
);
1436 if( !ImportGIF( rIStream
, rGraphic
) )
1437 nStatus
= GRFILTER_FILTERERROR
;
1439 eLinkType
= GFX_LINK_TYPE_NATIVE_GIF
;
1441 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_PNG
) )
1443 if ( rGraphic
.GetContext() == reinterpret_cast<GraphicReader
*>(1) )
1444 rGraphic
.SetContext( NULL
);
1446 vcl::PNGReader
aPNGReader( rIStream
);
1448 // ignore animation for previews and set preview size
1449 if( aPreviewSizeHint
.Width() || aPreviewSizeHint
.Height() )
1451 // position the stream at the end of the image if requested
1452 if( !bAllowPartialStreamRead
)
1453 aPNGReader
.GetChunks();
1457 // check if this PNG contains a GIF chunk!
1458 const std::vector
< vcl::PNGReader::ChunkData
>& rChunkData
= aPNGReader
.GetChunks();
1459 std::vector
< vcl::PNGReader::ChunkData
>::const_iterator
aIter( rChunkData
.begin() );
1460 std::vector
< vcl::PNGReader::ChunkData
>::const_iterator
aEnd ( rChunkData
.end() );
1461 while( aIter
!= aEnd
)
1463 // Microsoft Office is storing Animated GIFs in following chunk
1464 if ( aIter
->nType
== PMGCHUNG_msOG
)
1466 sal_uInt32 nChunkSize
= aIter
->aData
.size();
1467 if ( nChunkSize
> 11 )
1469 const std::vector
< sal_uInt8
>& rData
= aIter
->aData
;
1470 SvMemoryStream
aIStrm( (void*)&rData
[ 11 ], nChunkSize
- 11, StreamMode::READ
);
1471 ImportGIF( aIStrm
, rGraphic
);
1472 eLinkType
= GFX_LINK_TYPE_NATIVE_PNG
;
1480 if ( eLinkType
== GFX_LINK_TYPE_NONE
)
1482 BitmapEx
aBmpEx( aPNGReader
.Read( aPreviewSizeHint
) );
1483 if ( aBmpEx
.IsEmpty() )
1484 nStatus
= GRFILTER_FILTERERROR
;
1488 eLinkType
= GFX_LINK_TYPE_NATIVE_PNG
;
1492 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_JPEG
) )
1494 if( rGraphic
.GetContext() == reinterpret_cast<GraphicReader
*>(1) )
1495 rGraphic
.SetContext( NULL
);
1497 // set LOGSIZE flag always, if not explicitly disabled
1498 // (see #90508 and #106763)
1499 if( !( nImportFlags
& GraphicFilterImportFlags::DontSetLogsizeForJpeg
) )
1500 nImportFlags
|= GraphicFilterImportFlags::SetLogsizeForJpeg
;
1502 if( !ImportJPEG( rIStream
, rGraphic
, NULL
, nImportFlags
) )
1503 nStatus
= GRFILTER_FILTERERROR
;
1505 eLinkType
= GFX_LINK_TYPE_NATIVE_JPG
;
1507 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_SVG
) )
1509 if( rGraphic
.GetContext() == reinterpret_cast<GraphicReader
*>(1) )
1510 rGraphic
.SetContext( NULL
);
1512 const sal_uInt32
nStreamPosition(rIStream
.Tell());
1513 const sal_uInt32
nStreamLength(rIStream
.Seek(STREAM_SEEK_TO_END
) - nStreamPosition
);
1517 if(nStreamLength
> 0)
1519 std::vector
<sal_uInt8
> aTwoBytes(2);
1520 rIStream
.Seek(nStreamPosition
);
1521 rIStream
.Read(&aTwoBytes
[0], 2);
1522 rIStream
.Seek(nStreamPosition
);
1523 if(aTwoBytes
[0] == 0x1F && aTwoBytes
[1] == 0x8B)
1525 SvMemoryStream aMemStream
;
1529 aCodec
.BeginCompression(ZCODEC_DEFAULT_COMPRESSION
, false, true);
1530 nMemoryLength
= aCodec
.Decompress(rIStream
, aMemStream
);
1531 aCodec
.EndCompression();
1533 if (!rIStream
.GetError() && nMemoryLength
>= 0)
1535 SvgDataArray
aNewData(new sal_uInt8
[nMemoryLength
]);
1536 aMemStream
.Seek(STREAM_SEEK_TO_BEGIN
);
1537 aMemStream
.Read(aNewData
.get(), nMemoryLength
);
1539 // Make a uncompressed copy for GfxLink
1540 nGraphicContentSize
= nMemoryLength
;
1541 pGraphicContent
= new sal_uInt8
[nGraphicContentSize
];
1542 std::copy(aNewData
.get(), aNewData
.get() + nMemoryLength
, pGraphicContent
);
1544 if(!aMemStream
.GetError() )
1546 SvgDataPtr
aSvgDataPtr(new SvgData(aNewData
, nMemoryLength
, rPath
));
1547 rGraphic
= Graphic(aSvgDataPtr
);
1554 SvgDataArray
aNewData(new sal_uInt8
[nStreamLength
]);
1555 rIStream
.Seek(nStreamPosition
);
1556 rIStream
.Read(aNewData
.get(), nStreamLength
);
1558 if(!rIStream
.GetError())
1560 SvgDataPtr
aSvgDataPtr(new SvgData(aNewData
, nStreamLength
, rPath
));
1561 rGraphic
= Graphic(aSvgDataPtr
);
1569 eLinkType
= GFX_LINK_TYPE_NATIVE_SVG
;
1573 nStatus
= GRFILTER_FILTERERROR
;
1576 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_XBM
) )
1578 if( rGraphic
.GetContext() == reinterpret_cast<GraphicReader
*>(1) )
1579 rGraphic
.SetContext( NULL
);
1581 if( !ImportXBM( rIStream
, rGraphic
) )
1582 nStatus
= GRFILTER_FILTERERROR
;
1584 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_XPM
) )
1586 if( rGraphic
.GetContext() == reinterpret_cast<GraphicReader
*>(1) )
1587 rGraphic
.SetContext( NULL
);
1589 if( !ImportXPM( rIStream
, rGraphic
) )
1590 nStatus
= GRFILTER_FILTERERROR
;
1592 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_BMP
) ||
1593 aFilterName
.equalsIgnoreAsciiCase( IMP_SVMETAFILE
) )
1595 // SV internal filters for import bitmaps and MetaFiles
1596 ReadGraphic( rIStream
, rGraphic
);
1597 if( rIStream
.GetError() )
1599 nStatus
= GRFILTER_FORMATERROR
;
1601 else if (aFilterName
.equalsIgnoreAsciiCase(IMP_BMP
))
1603 // #i15508# added BMP type (checked, works)
1604 eLinkType
= GFX_LINK_TYPE_NATIVE_BMP
;
1607 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_MOV
) )
1609 ReadGraphic( rIStream
, rGraphic
);
1610 if( rIStream
.GetError() )
1611 nStatus
= GRFILTER_FORMATERROR
;
1614 rGraphic
.SetDefaultType();
1615 rIStream
.Seek( STREAM_SEEK_TO_END
);
1616 eLinkType
= GFX_LINK_TYPE_NATIVE_MOV
;
1619 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_WMF
) ||
1620 aFilterName
.equalsIgnoreAsciiCase( IMP_EMF
) )
1623 if( !ConvertWMFToGDIMetaFile( rIStream
, aMtf
, NULL
, pExtHeader
) )
1624 nStatus
= GRFILTER_FORMATERROR
;
1628 eLinkType
= GFX_LINK_TYPE_NATIVE_WMF
;
1631 else if( aFilterName
.equalsIgnoreAsciiCase( IMP_SVSGF
)
1632 || aFilterName
.equalsIgnoreAsciiCase( IMP_SVSGV
) )
1634 sal_uInt16 nVersion
;
1635 unsigned char nTyp
= CheckSgfTyp( rIStream
, nVersion
);
1641 SvMemoryStream aTempStream
;
1642 if( aTempStream
.GetError() )
1643 return GRFILTER_OPENERROR
;
1645 if( !SgfBMapFilter( rIStream
, aTempStream
) )
1646 nStatus
= GRFILTER_FILTERERROR
;
1649 aTempStream
.Seek( 0L );
1650 ReadGraphic( aTempStream
, rGraphic
);
1652 if( aTempStream
.GetError() )
1653 nStatus
= GRFILTER_FILTERERROR
;
1661 if( !SgfVectFilter( rIStream
, aMtf
) )
1662 nStatus
= GRFILTER_FILTERERROR
;
1664 rGraphic
= Graphic( aMtf
);
1670 if( nVersion
!= SGV_VERSION
)
1671 nStatus
= GRFILTER_VERSIONERROR
;
1675 if( !SgfSDrwFilter( rIStream
, aMtf
,
1676 INetURLObject(aFilterPath
) ) )
1678 nStatus
= GRFILTER_FILTERERROR
;
1681 rGraphic
= Graphic( aMtf
);
1688 nStatus
= GRFILTER_FORMATERROR
;
1694 nStatus
= GRFILTER_FILTERERROR
;
1698 ImpFilterLibCacheEntry
* pFilter
= NULL
;
1700 // find first filter in filter paths
1701 sal_Int32 i
, nTokenCount
= getTokenCount(aFilterPath
, ';');
1702 ImpFilterLibCache
&rCache
= Cache::get();
1703 for( i
= 0; ( i
< nTokenCount
) && ( pFilter
== NULL
); i
++ )
1704 pFilter
= rCache
.GetFilter( aFilterPath
.getToken(i
, ';'), aFilterName
);
1706 nStatus
= GRFILTER_FILTERERROR
;
1709 PFilterCall pFunc
= pFilter
->GetImportFunction();
1712 nStatus
= GRFILTER_FILTERERROR
;
1715 OUString aShortName
;
1716 if( nFormat
!= GRFILTER_FORMAT_DONTKNOW
)
1718 aShortName
= GetImportFormatShortName( nFormat
).toAsciiUpperCase();
1719 if ( ( pFilterConfigItem
== NULL
) && aShortName
== "PCD" )
1721 OUString
aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
1722 pFilterConfigItem
= new FilterConfigItem( aFilterConfigPath
);
1725 if( !(*pFunc
)( rIStream
, rGraphic
, pFilterConfigItem
) )
1726 nStatus
= GRFILTER_FORMATERROR
;
1729 // try to set link type if format matches
1730 if( nFormat
!= GRFILTER_FORMAT_DONTKNOW
)
1732 if( aShortName
.startsWith( TIF_SHORTNAME
) )
1733 eLinkType
= GFX_LINK_TYPE_NATIVE_TIF
;
1734 else if( aShortName
.startsWith( MET_SHORTNAME
) )
1735 eLinkType
= GFX_LINK_TYPE_NATIVE_MET
;
1736 else if( aShortName
.startsWith( PCT_SHORTNAME
) )
1737 eLinkType
= GFX_LINK_TYPE_NATIVE_PCT
;
1744 if( nStatus
== GRFILTER_OK
&& bCreateNativeLink
&& ( eLinkType
!= GFX_LINK_TYPE_NONE
) && !rGraphic
.GetContext() && !bLinkSet
)
1746 if (pGraphicContent
== NULL
)
1748 const sal_uLong nStreamEnd
= rIStream
.Tell();
1749 nGraphicContentSize
= nStreamEnd
- nStreamBegin
;
1751 if (nGraphicContentSize
> 0)
1755 pGraphicContent
= new sal_uInt8
[nGraphicContentSize
];
1757 catch (const std::bad_alloc
&)
1759 nStatus
= GRFILTER_TOOBIG
;
1762 if( nStatus
== GRFILTER_OK
)
1764 rIStream
.Seek(nStreamBegin
);
1765 rIStream
.Read(pGraphicContent
, nGraphicContentSize
);
1769 if( nStatus
== GRFILTER_OK
)
1771 rGraphic
.SetLink( GfxLink( pGraphicContent
, nGraphicContentSize
, eLinkType
, true ) );
1772 bGraphicContentOwned
= false; //ownership passed to the GfxLink
1776 if (bGraphicContentOwned
)
1777 delete[] pGraphicContent
;
1779 // Set error code or try to set native buffer
1780 if( nStatus
!= GRFILTER_OK
)
1783 nStatus
= GRFILTER_ABORT
;
1785 ImplSetError( nStatus
, &rIStream
);
1786 rIStream
.Seek( nStreamBegin
);
1790 delete pFilterConfigItem
;
1794 sal_uInt16
GraphicFilter::ExportGraphic( const Graphic
& rGraphic
, const INetURLObject
& rPath
,
1795 sal_uInt16 nFormat
, const uno::Sequence
< beans::PropertyValue
>* pFilterData
)
1797 #ifdef DISABLE_EXPORT
1803 return GRFILTER_FORMATERROR
;
1805 SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1806 sal_uInt16 nRetValue
= GRFILTER_FORMATERROR
;
1807 DBG_ASSERT( rPath
.GetProtocol() != INetProtocol::NotValid
, "GraphicFilter::ExportGraphic() : ProtType == INetProtocol::NotValid" );
1808 bool bAlreadyExists
= DirEntryExists( rPath
);
1810 OUString
aMainUrl( rPath
.GetMainURL( INetURLObject::NO_DECODE
) );
1811 std::unique_ptr
<SvStream
> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl
, StreamMode::WRITE
| StreamMode::TRUNC
));
1814 nRetValue
= ExportGraphic( rGraphic
, aMainUrl
, *xStream
, nFormat
, pFilterData
);
1817 if( ( GRFILTER_OK
!= nRetValue
) && !bAlreadyExists
)
1818 KillDirEntry( aMainUrl
);
1824 #ifdef DISABLE_DYNLOADING
1826 #ifndef DISABLE_EXPORT
1828 extern "C" bool egiGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1829 extern "C" bool emeGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1830 extern "C" bool epbGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1831 extern "C" bool epgGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1832 extern "C" bool eppGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1833 extern "C" bool epsGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1834 extern "C" bool eptGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1835 extern "C" bool eraGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1836 extern "C" bool etiGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1837 extern "C" bool expGraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
1843 sal_uInt16
GraphicFilter::ExportGraphic( const Graphic
& rGraphic
, const OUString
& rPath
,
1844 SvStream
& rOStm
, sal_uInt16 nFormat
, const uno::Sequence
< beans::PropertyValue
>* pFilterData
)
1846 #ifdef DISABLE_EXPORT
1853 return GRFILTER_FORMATERROR
;
1855 SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1856 sal_uInt16 nFormatCount
= GetExportFormatCount();
1861 if( nFormat
== GRFILTER_FORMAT_DONTKNOW
)
1863 INetURLObject
aURL( rPath
);
1864 OUString
aExt( aURL
.GetFileExtension().toAsciiUpperCase() );
1866 for( sal_uInt16 i
= 0; i
< nFormatCount
; i
++ )
1868 if ( pConfig
->GetExportFormatExtension( i
).equalsIgnoreAsciiCase( aExt
) )
1875 if( nFormat
>= nFormatCount
)
1876 return (sal_uInt16
) ImplSetError( GRFILTER_FORMATERROR
);
1878 FilterConfigItem
aConfigItem( const_cast<uno::Sequence
< beans::PropertyValue
>*>(pFilterData
) );
1879 OUString
aFilterName( pConfig
->GetExportFilterName( nFormat
) );
1882 sal_uInt16 nStatus
= GRFILTER_OK
;
1884 Graphic
aGraphic( rGraphic
);
1886 aGraphic
= ImpGetScaledGraphic( rGraphic
, aConfigItem
);
1887 eType
= aGraphic
.GetType();
1889 if( pConfig
->IsExportPixelFormat( nFormat
) )
1891 if( eType
!= GRAPHIC_BITMAP
)
1894 sal_uLong nColorCount
,nBitsPerPixel
,nNeededMem
,nMaxMem
;
1895 ScopedVclPtrInstance
< VirtualDevice
> aVirDev
;
1898 nMaxMem
*= 1024; // In Bytes
1900 // Calculate how big the image would normally be:
1901 aSizePixel
=aVirDev
->LogicToPixel(aGraphic
.GetPrefSize(),aGraphic
.GetPrefMapMode());
1903 // Calculate how much memory the image will take up
1904 nColorCount
=aVirDev
->GetColorCount();
1905 if (nColorCount
<=2) nBitsPerPixel
=1;
1906 else if (nColorCount
<=4) nBitsPerPixel
=2;
1907 else if (nColorCount
<=16) nBitsPerPixel
=4;
1908 else if (nColorCount
<=256) nBitsPerPixel
=8;
1909 else if (nColorCount
<=65536) nBitsPerPixel
=16;
1910 else nBitsPerPixel
=24;
1911 nNeededMem
=((sal_uLong
)aSizePixel
.Width()*(sal_uLong
)aSizePixel
.Height()*nBitsPerPixel
+7)/8;
1913 // is the image larger than available memory?
1914 if (nMaxMem
<nNeededMem
)
1916 double fFak
=sqrt(((double)nMaxMem
)/((double)nNeededMem
));
1917 aSizePixel
.Width()=(sal_uLong
)(((double)aSizePixel
.Width())*fFak
);
1918 aSizePixel
.Height()=(sal_uLong
)(((double)aSizePixel
.Height())*fFak
);
1921 aVirDev
->SetMapMode(MapMode(MAP_PIXEL
));
1922 aVirDev
->SetOutputSizePixel(aSizePixel
);
1923 Graphic aGraphic2
=aGraphic
;
1924 aGraphic2
.Draw(aVirDev
.get(),Point(0,0),aSizePixel
); // this changes the MapMode
1925 aVirDev
->SetMapMode(MapMode(MAP_PIXEL
));
1926 aGraphic
=Graphic(aVirDev
->GetBitmap(Point(0,0),aSizePixel
));
1929 if( rOStm
.GetError() )
1930 nStatus
= GRFILTER_IOERROR
;
1931 if( GRFILTER_OK
== nStatus
)
1933 if ( pConfig
->IsExportInternalFilter( nFormat
) )
1935 if( aFilterName
.equalsIgnoreAsciiCase( EXP_BMP
) )
1937 Bitmap
aBmp( aGraphic
.GetBitmap() );
1938 sal_Int32 nColorRes
= aConfigItem
.ReadInt32( "Colors", 0 );
1939 if ( nColorRes
&& ( nColorRes
<= (sal_uInt16
)BMP_CONVERSION_24BIT
) )
1941 if( !aBmp
.Convert( (BmpConversion
) nColorRes
) )
1942 aBmp
= aGraphic
.GetBitmap();
1944 bool bRleCoding
= aConfigItem
.ReadBool( "RLE_Coding", true );
1945 // save RLE encoded?
1946 WriteDIB(aBmp
, rOStm
, bRleCoding
, true);
1948 if( rOStm
.GetError() )
1949 nStatus
= GRFILTER_IOERROR
;
1951 else if( aFilterName
.equalsIgnoreAsciiCase( EXP_SVMETAFILE
) )
1953 sal_Int32 nVersion
= aConfigItem
.ReadInt32( "Version", 0 ) ;
1955 rOStm
.SetVersion( nVersion
);
1957 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
1958 GDIMetaFile
aMTF(aGraphic
.GetGDIMetaFile());
1960 aMTF
.Write( rOStm
);
1962 if( rOStm
.GetError() )
1963 nStatus
= GRFILTER_IOERROR
;
1965 else if ( aFilterName
.equalsIgnoreAsciiCase( EXP_WMF
) )
1967 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
1968 if ( !ConvertGDIMetaFileToWMF( aGraphic
.GetGDIMetaFile(), rOStm
, &aConfigItem
) )
1969 nStatus
= GRFILTER_FORMATERROR
;
1971 if( rOStm
.GetError() )
1972 nStatus
= GRFILTER_IOERROR
;
1974 else if ( aFilterName
.equalsIgnoreAsciiCase( EXP_EMF
) )
1976 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
1977 if ( !ConvertGDIMetaFileToEMF(aGraphic
.GetGDIMetaFile(), rOStm
))
1978 nStatus
= GRFILTER_FORMATERROR
;
1980 if( rOStm
.GetError() )
1981 nStatus
= GRFILTER_IOERROR
;
1983 else if( aFilterName
.equalsIgnoreAsciiCase( EXP_JPEG
) )
1985 bool bExportedGrayJPEG
= false;
1986 if( !ExportJPEG( rOStm
, aGraphic
, pFilterData
, &bExportedGrayJPEG
) )
1987 nStatus
= GRFILTER_FORMATERROR
;
1988 nExpGraphHint
= bExportedGrayJPEG
? GRFILTER_OUTHINT_GREY
: 0;
1990 if( rOStm
.GetError() )
1991 nStatus
= GRFILTER_IOERROR
;
1993 else if ( aFilterName
.equalsIgnoreAsciiCase( EXP_PNG
) )
1995 vcl::PNGWriter
aPNGWriter( aGraphic
.GetBitmapEx(), pFilterData
);
1998 sal_Int32 k
, j
, i
= 0;
1999 for ( i
= 0; i
< pFilterData
->getLength(); i
++ )
2001 if ( (*pFilterData
)[ i
].Name
== "AdditionalChunks" )
2003 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aAdditionalChunkSequence
;
2004 if ( (*pFilterData
)[ i
].Value
>>= aAdditionalChunkSequence
)
2006 for ( j
= 0; j
< aAdditionalChunkSequence
.getLength(); j
++ )
2008 if ( aAdditionalChunkSequence
[ j
].Name
.getLength() == 4 )
2010 sal_uInt32 nChunkType
= 0;
2011 for ( k
= 0; k
< 4; k
++ )
2014 nChunkType
|= (sal_uInt8
)aAdditionalChunkSequence
[ j
].Name
[ k
];
2016 com::sun::star::uno::Sequence
< sal_Int8
> aByteSeq
;
2017 if ( aAdditionalChunkSequence
[ j
].Value
>>= aByteSeq
)
2019 std::vector
< vcl::PNGWriter::ChunkData
>& rChunkData
= aPNGWriter
.GetChunks();
2020 if ( !rChunkData
.empty() )
2022 sal_uInt32 nChunkLen
= aByteSeq
.getLength();
2024 vcl::PNGWriter::ChunkData aChunkData
;
2025 aChunkData
.nType
= nChunkType
;
2028 aChunkData
.aData
.resize( nChunkLen
);
2029 memcpy( &aChunkData
.aData
[ 0 ], aByteSeq
.getConstArray(), nChunkLen
);
2031 std::vector
< vcl::PNGWriter::ChunkData
>::iterator aIter
= rChunkData
.end() - 1;
2032 rChunkData
.insert( aIter
, aChunkData
);
2041 aPNGWriter
.Write( rOStm
);
2043 if( rOStm
.GetError() )
2044 nStatus
= GRFILTER_IOERROR
;
2046 else if( aFilterName
.equalsIgnoreAsciiCase( EXP_SVG
) )
2050 // do we have a native SVG RenderGraphic, whose data can be written directly?
2051 const SvgDataPtr
aSvgDataPtr(rGraphic
.getSvgData());
2053 if(aSvgDataPtr
.get() && aSvgDataPtr
->getSvgDataArrayLength())
2055 rOStm
.Write(aSvgDataPtr
->getSvgDataArray().get(), aSvgDataPtr
->getSvgDataArrayLength());
2057 if( rOStm
.GetError() )
2059 nStatus
= GRFILTER_IOERROR
;
2069 // do the normal GDIMetaFile export instead
2072 css::uno::Reference
< css::uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
2074 css::uno::Reference
< css::xml::sax::XDocumentHandler
> xSaxWriter(
2075 xml::sax::Writer::create( xContext
), uno::UNO_QUERY_THROW
);
2076 css::uno::Sequence
< css::uno::Any
> aArguments( 1 );
2077 aArguments
[ 0 ] <<= aConfigItem
.GetFilterData();
2078 css::uno::Reference
< css::svg::XSVGWriter
> xSVGWriter(
2079 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.svg.SVGWriter", aArguments
, xContext
),
2080 css::uno::UNO_QUERY
);
2081 if( xSaxWriter
.is() && xSVGWriter
.is() )
2083 css::uno::Reference
< css::io::XActiveDataSource
> xActiveDataSource(
2084 xSaxWriter
, css::uno::UNO_QUERY
);
2086 if( xActiveDataSource
.is() )
2088 const css::uno::Reference
< css::uno::XInterface
> xStmIf(
2089 static_cast< ::cppu::OWeakObject
* >( new ImpFilterOutputStream( rOStm
) ) );
2091 SvMemoryStream
aMemStm( 65535, 65535 );
2093 // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
2094 ( (GDIMetaFile
&) aGraphic
.GetGDIMetaFile() ).Write( aMemStm
);
2096 xActiveDataSource
->setOutputStream( css::uno::Reference
< css::io::XOutputStream
>(
2097 xStmIf
, css::uno::UNO_QUERY
) );
2098 css::uno::Sequence
< sal_Int8
> aMtfSeq( static_cast<sal_Int8
const *>(aMemStm
.GetData()), aMemStm
.Tell() );
2099 xSVGWriter
->write( xSaxWriter
, aMtfSeq
);
2103 catch(const css::uno::Exception
&)
2105 nStatus
= GRFILTER_IOERROR
;
2110 nStatus
= GRFILTER_FILTERERROR
;
2114 sal_Int32 i
, nTokenCount
= getTokenCount(aFilterPath
, ';');
2115 for ( i
= 0; i
< nTokenCount
; i
++ )
2117 #ifndef DISABLE_DYNLOADING
2118 OUString
aPhysicalName( ImpCreateFullFilterPath( aFilterPath
.getToken(i
, ';'), aFilterName
) );
2119 osl::Module
aLibrary( aPhysicalName
);
2121 PFilterCall pFunc
= reinterpret_cast<PFilterCall
>(aLibrary
.getFunctionSymbol(OUString(EXPORT_FUNCTION_NAME
)));
2122 // Execute dialog in DLL
2124 PFilterCall pFunc
= NULL
;
2125 if( aFilterName
.equalsAscii( "egi" ) )
2126 pFunc
= egiGraphicExport
;
2127 else if( aFilterName
.equalsAscii( "eme" ) )
2128 pFunc
= emeGraphicExport
;
2129 else if( aFilterName
.equalsAscii( "epb" ) )
2130 pFunc
= epbGraphicExport
;
2131 else if( aFilterName
.equalsAscii( "epg" ) )
2132 pFunc
= epgGraphicExport
;
2133 else if( aFilterName
.equalsAscii( "epp" ) )
2134 pFunc
= eppGraphicExport
;
2135 else if( aFilterName
.equalsAscii( "eps" ) )
2136 pFunc
= epsGraphicExport
;
2137 else if( aFilterName
.equalsAscii( "ept" ) )
2138 pFunc
= eptGraphicExport
;
2139 else if( aFilterName
.equalsAscii( "era" ) )
2140 pFunc
= eraGraphicExport
;
2141 else if( aFilterName
.equalsAscii( "eti" ) )
2142 pFunc
= etiGraphicExport
;
2143 else if( aFilterName
.equalsAscii( "exp" ) )
2144 pFunc
= expGraphicExport
;
2148 if ( !(*pFunc
)( rOStm
, aGraphic
, &aConfigItem
) )
2149 nStatus
= GRFILTER_FORMATERROR
;
2153 nStatus
= GRFILTER_FILTERERROR
;
2157 if( nStatus
!= GRFILTER_OK
)
2160 nStatus
= GRFILTER_ABORT
;
2162 ImplSetError( nStatus
, &rOStm
);
2169 void GraphicFilter::ResetLastError()
2171 pErrorEx
->nFilterError
= pErrorEx
->nStreamError
= 0UL;
2174 const Link
<> GraphicFilter::GetFilterCallback() const
2176 const Link
<> aLink( LINK( const_cast<GraphicFilter
*>(this), GraphicFilter
, FilterCallback
) );
2180 IMPL_LINK( GraphicFilter
, FilterCallback
, ConvertData
*, pData
)
2186 sal_uInt16 nFormat
= GRFILTER_FORMAT_DONTKNOW
;
2188 switch( pData
->mnFormat
)
2190 case( CVT_BMP
): aShortName
= BMP_SHORTNAME
; break;
2191 case( CVT_GIF
): aShortName
= GIF_SHORTNAME
; break;
2192 case( CVT_JPG
): aShortName
= JPG_SHORTNAME
; break;
2193 case( CVT_MET
): aShortName
= MET_SHORTNAME
; break;
2194 case( CVT_PCT
): aShortName
= PCT_SHORTNAME
; break;
2195 case( CVT_PNG
): aShortName
= PNG_SHORTNAME
; break;
2196 case( CVT_SVM
): aShortName
= SVM_SHORTNAME
; break;
2197 case( CVT_TIF
): aShortName
= TIF_SHORTNAME
; break;
2198 case( CVT_WMF
): aShortName
= WMF_SHORTNAME
; break;
2199 case( CVT_EMF
): aShortName
= EMF_SHORTNAME
; break;
2200 case( CVT_SVG
): aShortName
= SVG_SHORTNAME
; break;
2205 if( GRAPHIC_NONE
== pData
->maGraphic
.GetType() || pData
->maGraphic
.GetContext() ) // Import
2208 nFormat
= GetImportFormatNumberForShortName( OStringToOUString( aShortName
, RTL_TEXTENCODING_UTF8
) );
2209 nRet
= ImportGraphic( pData
->maGraphic
, OUString(), pData
->mrStm
, nFormat
) == 0;
2211 #ifndef DISABLE_EXPORT
2212 else if( !aShortName
.isEmpty() )
2215 nFormat
= GetExportFormatNumberForShortName( OStringToOUString(aShortName
, RTL_TEXTENCODING_UTF8
) );
2216 nRet
= ExportGraphic( pData
->maGraphic
, OUString(), pData
->mrStm
, nFormat
) == 0;
2225 class StandardGraphicFilter
2228 StandardGraphicFilter()
2230 m_aFilter
.GetImportFormatCount();
2232 GraphicFilter m_aFilter
;
2235 class theGraphicFilter
: public rtl::Static
<StandardGraphicFilter
, theGraphicFilter
> {};
2238 GraphicFilter
& GraphicFilter::GetGraphicFilter()
2240 return theGraphicFilter::get().m_aFilter
;
2243 int GraphicFilter::LoadGraphic( const OUString
&rPath
, const OUString
&rFilterName
,
2244 Graphic
& rGraphic
, GraphicFilter
* pFilter
,
2245 sal_uInt16
* pDeterminedFormat
)
2248 pFilter
= &GetGraphicFilter();
2250 const sal_uInt16 nFilter
= !rFilterName
.isEmpty() && pFilter
->GetImportFormatCount()
2251 ? pFilter
->GetImportFormatNumber( rFilterName
)
2252 : GRFILTER_FORMAT_DONTKNOW
;
2254 INetURLObject
aURL( rPath
);
2255 if ( aURL
.HasError() )
2257 aURL
.SetSmartProtocol( INetProtocol::File
);
2258 aURL
.SetSmartURL( rPath
);
2261 SvStream
* pStream
= NULL
;
2262 if ( INetProtocol::File
!= aURL
.GetProtocol() )
2264 pStream
= ::utl::UcbStreamHelper::CreateStream( rPath
, StreamMode::READ
);
2267 int nRes
= GRFILTER_OK
;
2269 nRes
= pFilter
->ImportGraphic( rGraphic
, aURL
, nFilter
, pDeterminedFormat
);
2271 nRes
= pFilter
->ImportGraphic( rGraphic
, rPath
, *pStream
, nFilter
, pDeterminedFormat
);
2274 OUString aReturnString
;
2278 case GRFILTER_OPENERROR
:
2279 aReturnString
="open error";
2281 case GRFILTER_IOERROR
:
2282 aReturnString
="IO error";
2284 case GRFILTER_FORMATERROR
:
2285 aReturnString
="format error";
2287 case GRFILTER_VERSIONERROR
:
2288 aReturnString
="version error";
2290 case GRFILTER_FILTERERROR
:
2291 aReturnString
="filter error";
2293 case GRFILTER_ABORT
:
2294 aReturnString
="import aborted";
2296 case GRFILTER_TOOBIG
:
2297 aReturnString
="graphic is too big";
2300 // nothing more to do
2304 SAL_INFO_IF( nRes
, "vcl.filter", "Problem importing graphic " << rPath
<< ". Reason: " << aReturnString
);
2310 sal_uInt16
GraphicFilter::compressAsPNG(const Graphic
& rGraphic
, SvStream
& rOutputStream
, sal_uInt32 nCompression
)
2312 nCompression
= MinMax(nCompression
, 0, 100);
2314 uno::Sequence
<beans::PropertyValue
> aFilterData(1);
2315 aFilterData
[0].Name
= "Compression";
2316 aFilterData
[0].Value
<<= nCompression
;
2318 sal_uInt16 nFilterFormat
= GetExportFormatNumberForShortName("PNG");
2319 return ExportGraphic(rGraphic
, OUString(), rOutputStream
, nFilterFormat
, &aFilterData
);
2322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */