diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-03-02 22:06:13 +0100 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-03-02 22:12:07 +0100 |
commit | 4f7aa27c6297453a348137bb99d1a28e3dfc5619 (patch) | |
tree | 4dde491d48e6a0b95b23f39b037716787ddf316c /filter | |
parent | fdo#75487 Register svgz as a recognisable extension. (diff) | |
download | core-4f7aa27c6297453a348137bb99d1a28e3dfc5619.tar.gz core-4f7aa27c6297453a348137bb99d1a28e3dfc5619.zip |
fdo#75487 Add support for svgz to SvgFilter and co.
Draw can open a svg file directly as a "document" not only as a
picture (which is handled by "graphicfilter" in vcl). This commit
adds support to also open svgz files by decompressing the stream
first.
Change-Id: I241e695076b380735dc9b9fc27f5416fff68f6ab
Diffstat (limited to 'filter')
-rw-r--r-- | filter/source/svg/svgfilter.cxx | 115 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.hxx | 3 | ||||
-rw-r--r-- | filter/source/svg/svgimport.cxx | 47 |
3 files changed, 113 insertions, 52 deletions
diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx index ce6d93edf0a1..e94ba85ba106 100644 --- a/filter/source/svg/svgfilter.cxx +++ b/filter/source/svg/svgfilter.cxx @@ -40,6 +40,11 @@ #include <com/sun/star/drawing/framework/ResourceId.hpp> #include <comphelper/processfactory.hxx> +#include <unotools/mediadescriptor.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/streamwrap.hxx> +#include <tools/zcodec.hxx> + #include <osl/mutex.hxx> #include "svgfilter.hxx" @@ -47,9 +52,10 @@ using namespace ::com::sun::star; - -// - SVGFilter - - +namespace +{ + static const char constFilterName[] = "svg_Scalable_Vector_Graphics"; +} SVGFilter::SVGFilter( const Reference< XComponentContext >& rxCtx ) : mxContext( rxCtx ), @@ -62,12 +68,9 @@ SVGFilter::SVGFilter( const Reference< XComponentContext >& rxCtx ) : mbPresentation( sal_False ), mbExportAll( sal_False ), mpObjects( NULL ) - { } - - SVGFilter::~SVGFilter() { DBG_ASSERT( mpSVGDoc == NULL, "mpSVGDoc not destroyed" ); @@ -77,8 +80,6 @@ SVGFilter::~SVGFilter() DBG_ASSERT( mpObjects == NULL, "mpObjects not destroyed" ); } - - sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException, std::exception) { @@ -242,70 +243,102 @@ sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescripto return bRet; } - - void SAL_CALL SVGFilter::cancel( ) throw (RuntimeException, std::exception) { } - - void SAL_CALL SVGFilter::setSourceDocument( const Reference< XComponent >& xDoc ) throw (IllegalArgumentException, RuntimeException, std::exception) { mxSrcDoc = xDoc; } - - void SAL_CALL SVGFilter::setTargetDocument( const Reference< XComponent >& xDoc ) throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException, std::exception) { mxDstDoc = xDoc; } - - -OUString SAL_CALL SVGFilter::detect( Sequence< PropertyValue >& io_rDescriptor ) throw (RuntimeException, std::exception) +bool SAL_CALL SVGFilter::isStreamGZip(uno::Reference<io::XInputStream> xInput) { - uno::Reference< io::XInputStream > xInput; + uno::Reference<io::XSeekable> xSeek(xInput, uno::UNO_QUERY); + if(xSeek.is()) + xSeek->seek(0); - const beans::PropertyValue* pAttribs = io_rDescriptor.getConstArray(); - const sal_Int32 nAttribs = io_rDescriptor.getLength(); - for( sal_Int32 i = 0; i < nAttribs; i++ ) + uno::Sequence<sal_Int8> aBuffer(2); + const sal_uInt64 nBytes = xInput->readBytes(aBuffer, 2); + if (nBytes == 2) { - if ( pAttribs[i].Name == "InputStream" ) - pAttribs[i].Value >>= xInput; + const sal_Int8* pBuffer = aBuffer.getConstArray(); + if (pBuffer[0] == (sal_Int8)0x1F && pBuffer[1] == (sal_Int8)0x8B) + return true; } + return false; +} - if( !xInput.is() ) - return OUString(); - - uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY ); - if( xSeek.is() ) - xSeek->seek( 0 ); +bool SAL_CALL SVGFilter::isStreamSvg(uno::Reference<io::XInputStream> xInput) +{ + uno::Reference<io::XSeekable> xSeek(xInput, uno::UNO_QUERY); + if(xSeek.is()) + xSeek->seek(0); - // read the first 1024 bytes & check a few magic string - // constants (heuristically) const sal_Int32 nLookAhead = 1024; - uno::Sequence< sal_Int8 > aBuf( nLookAhead ); - const sal_uInt64 nBytes=xInput->readBytes(aBuf, nLookAhead); - const sal_Int8* const pBuf=aBuf.getConstArray(); + uno::Sequence<sal_Int8> aBuffer(nLookAhead); + const sal_uInt64 nBytes = xInput->readBytes(aBuffer, nLookAhead); + const sal_Int8* pBuffer = aBuffer.getConstArray(); sal_Int8 aMagic1[] = {'<', 's', 'v', 'g'}; - if( std::search(pBuf, pBuf+nBytes, - aMagic1, aMagic1+sizeof(aMagic1)/sizeof(*aMagic1)) != pBuf+nBytes ) - return OUString("svg_Scalable_Vector_Graphics"); + sal_Int32 aMagic1Size = sizeof(aMagic1) / sizeof(*aMagic1); + + if (std::search(pBuffer, pBuffer + nBytes, aMagic1, aMagic1 + aMagic1Size) != pBuffer + nBytes ) + return true; sal_Int8 aMagic2[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'}; - if( std::search(pBuf, pBuf+nBytes, - aMagic2, aMagic2+sizeof(aMagic2)/sizeof(*aMagic2)) != pBuf+nBytes ) - return OUString("svg_Scalable_Vector_Graphics"); + sal_Int32 aMagic2Size = sizeof(aMagic2) / sizeof(*aMagic2); - return OUString(); + if (std::search(pBuffer, pBuffer + nBytes, aMagic2, aMagic2 + aMagic2Size) != pBuffer + nBytes) + return true; + + return false; } +OUString SAL_CALL SVGFilter::detect(Sequence<PropertyValue>& rDescriptor) throw (RuntimeException, std::exception) +{ + utl::MediaDescriptor aMediaDescriptor(rDescriptor); + uno::Reference<io::XInputStream> xInput(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY); + if (!xInput.is()) + return OUString(); + + if (isStreamGZip(xInput)) + { + boost::scoped_ptr<SvStream> aStream(utl::UcbStreamHelper::CreateStream(xInput, true )); + if(!aStream.get()) + return OUString(); + + SvStream* pMemoryStream = new SvMemoryStream; + uno::Reference<io::XSeekable> xSeek(xInput, uno::UNO_QUERY); + if (!xSeek.is()) + return OUString(); + xSeek->seek(0); + + GZCodec aCodec; + aCodec.BeginCompression(); + aCodec.Decompress(*aStream.get(), *pMemoryStream); + aCodec.EndCompression(); + pMemoryStream->Seek(STREAM_SEEK_TO_BEGIN); + uno::Reference<io::XInputStream> xDecompressedInput(new utl::OSeekableInputStreamWrapper(pMemoryStream, true)); + + if (xDecompressedInput.is() && isStreamSvg(xDecompressedInput)) + return OUString(constFilterName); + } + else + { + if (isStreamSvg(xInput)) + return OUString(constFilterName); + } + return OUString(); +} #define SVG_FILTER_IMPL_NAME "com.sun.star.comp.Draw.SVGFilter" #define SVG_WRITER_IMPL_NAME "com.sun.star.comp.Draw.SVGWriter" diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx index 7dfbb7767e66..536a956ee2e8 100644 --- a/filter/source/svg/svgfilter.hxx +++ b/filter/source/svg/svgfilter.hxx @@ -309,6 +309,9 @@ private: const Reference< XPropertySetInfo > & rxPropSetInfo ); DECL_LINK( CalcFieldHdl, EditFieldInfo* ); + bool isStreamGZip(css::uno::Reference<css::io::XInputStream> xInput); + bool isStreamSvg(css::uno::Reference<css::io::XInputStream> xInput); + protected: // XFilter diff --git a/filter/source/svg/svgimport.cxx b/filter/source/svg/svgimport.cxx index 21c7c80e8043..d61603e4058c 100644 --- a/filter/source/svg/svgimport.cxx +++ b/filter/source/svg/svgimport.cxx @@ -39,24 +39,49 @@ #include <com/sun/star/io/XActiveDataSource.hpp> #include <com/sun/star/task/XStatusIndicator.hpp> +#include <unotools/mediadescriptor.hxx> +#include <tools/zcodec.hxx> + using namespace ::com::sun::star; using namespace ::svgi; sal_Bool SVGFilter::implImport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException) { - uno::Reference< io::XInputStream > xInputStream; - uno::Reference< task::XStatusIndicator > xStatus; - const sal_Int32 nLength = rDescriptor.getLength(); - const beans::PropertyValue* pAttribs = rDescriptor.getConstArray(); - for ( sal_Int32 i=0 ; i<nLength; ++i, ++pAttribs ) + utl::MediaDescriptor aMediaDescriptor(rDescriptor); + uno::Reference<io::XInputStream> xInputStream; + uno::Reference<task::XStatusIndicator> xStatus; + + xInputStream = uno::Reference<io::XInputStream>(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY); + xStatus = uno::Reference<task::XStatusIndicator>(aMediaDescriptor[utl::MediaDescriptor::PROP_STATUSINDICATOR()], UNO_QUERY); + + if (isStreamGZip(xInputStream)) + { + uno::Reference<io::XSeekable> xSeek(xInputStream, uno::UNO_QUERY); + if (!xSeek.is()) + return sal_False; + xSeek->seek(0); + + boost::scoped_ptr<SvStream> aStream(utl::UcbStreamHelper::CreateStream(xInputStream, true )); + if(!aStream.get()) + return sal_False; + + SvStream* pMemoryStream = new SvMemoryStream; + GZCodec aCodec; + aCodec.BeginCompression(); + aCodec.Decompress(*aStream.get(), *pMemoryStream); + aCodec.EndCompression(); + pMemoryStream->Seek(STREAM_SEEK_TO_BEGIN); + uno::Reference<io::XInputStream> xDecompressedInput(new utl::OSeekableInputStreamWrapper(pMemoryStream, true)); + if (!xDecompressedInput.is()) + return sal_False; + xInputStream = xDecompressedInput; + } + else { - if ( pAttribs->Name == "InputStream" ) - { - pAttribs->Value >>= xInputStream; - } - else if ( pAttribs->Name == "StatusIndicator" ) - pAttribs->Value >>= xStatus; + uno::Reference<io::XSeekable> xSeek(xInputStream, uno::UNO_QUERY); + if (xSeek.is()) + xSeek->seek(0); } OSL_ASSERT(xInputStream.is()); |