summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.com>2014-03-02 22:06:13 +0100
committerTomaž Vajngerl <tomaz.vajngerl@collabora.com>2014-03-02 22:12:07 +0100
commit4f7aa27c6297453a348137bb99d1a28e3dfc5619 (patch)
tree4dde491d48e6a0b95b23f39b037716787ddf316c
parent51e7a789a1345932eadb92dc1ef5ac5ecfe2d0c0 (diff)
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
-rw-r--r--filter/source/svg/svgfilter.cxx115
-rw-r--r--filter/source/svg/svgfilter.hxx3
-rw-r--r--filter/source/svg/svgimport.cxx47
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());