[Libreoffice-commits] core.git: 3 commits - filter/source vcl/source
Tomaž Vajngerl
tomaz.vajngerl at collabora.com
Sun Mar 2 13:12:46 PST 2014
filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu | 2
filter/source/svg/svgfilter.cxx | 115 ++++--
filter/source/svg/svgfilter.hxx | 3
filter/source/svg/svgimport.cxx | 47 ++
vcl/source/filter/graphicfilter.cxx | 176 +++++-----
5 files changed, 211 insertions(+), 132 deletions(-)
New commits:
commit 4f7aa27c6297453a348137bb99d1a28e3dfc5619
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Sun Mar 2 22:06:13 2014 +0100
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
diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx
index ce6d93e..e94ba85 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 7dfbb77..536a956 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 21c7c80..d61603e 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());
commit 51e7a789a1345932eadb92dc1ef5ac5ecfe2d0c0
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Sun Mar 2 21:25:26 2014 +0100
fdo#75487 Register svgz as a recognisable extension.
Change-Id: If4b5d6a38b468e5412dd973547cbcd580a83e239
diff --git a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
index caa5754..f811f9b 100644
--- a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
+++ b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
@@ -18,7 +18,7 @@
<node oor:name="svg_Scalable_Vector_Graphics" oor:op="replace" >
<prop oor:name="DetectService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
<prop oor:name="URLPattern"/>
- <prop oor:name="Extensions"><value>svg</value></prop>
+ <prop oor:name="Extensions"><value>svg svgz</value></prop>
<prop oor:name="MediaType"><value>image/svg+xml</value></prop>
<prop oor:name="Preferred"><value>true</value></prop>
<prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics</value></prop>
commit c77c6c2a0e675995e30afbf9eca3c4c9e6aceeae
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Sun Mar 2 21:21:08 2014 +0100
Support svgz in graphicfilter (import image to document)
Detect if input stream is gzip, if it is decompress and check the
decompressed stream if the content is svg.
When reading, decompress the whole svg content first, and then
store it internally.
Change-Id: Ie8b7e2b2f59a92d6420c38fd4a25637a6ee94425
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 978d927..813600f 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -25,6 +25,7 @@
#include <ucbhelper/content.hxx>
#include <cppuhelper/implbase1.hxx>
#include <tools/urlobj.hxx>
+#include <tools/zcodec.hxx>
#include <vcl/dibtools.hxx>
#include <vcl/salctype.hxx>
#include <vcl/pngread.hxx>
@@ -255,7 +256,7 @@ bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
static bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, bool bTest )
{
sal_uInt16 i;
- sal_uInt8 sFirstBytes[ 256 ];
+ sal_uInt8 sFirstBytes[ 256 ];
sal_uLong nFirstLong,nSecondLong;
sal_uLong nStreamPos = rStream.Tell();
@@ -645,89 +646,80 @@ static bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension,
//--------------------------- SVG ------------------------------------
if( !bTest )
{
- // check for Xml
- if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<?xml", 256, 5 ) // is it xml
- && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"version", 256, 7 )) // does it have a version (required for xml)
- {
- bool bIsSvg(false);
-
- // check for DOCTYPE svg combination
- if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"DOCTYPE", 256, 7 ) // 'DOCTYPE' is there
- && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"svg", 256, 3 )) // 'svg' is there
- {
- bIsSvg = true;
- }
+ sal_uInt8* pCheckArray = sFirstBytes;
+ sal_uLong nCheckSize = nStreamLen < 256 ? nStreamLen : 256;
- // check for svg element in 1st 256 bytes
- if(!bIsSvg && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
- {
- bIsSvg = true;
- }
+ sal_uInt8 sExtendedOrDecompressedFirstBytes[2048];
+ sal_uLong nDecompressedSize = nCheckSize;
- if(!bIsSvg)
- {
- // it's a xml, look for '<svg' in full file. Should not happen too
- // often since the tests above will handle most cases, but can happen
- // with Svg files containing big comment headers or Svg as the host
- // language
- const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
- sal_uInt8* pBuf = new sal_uInt8[nSize];
+ bool bIsGZip(false);
- rStream.Seek(nStreamPos);
- rStream.Read(pBuf, nSize);
+ // check if it is gzipped -> svgz
+ if(sFirstBytes[0] == 0x1F && sFirstBytes[1] == 0x8B)
+ {
+ GZCodec aCodec;
+ rStream.Seek(nStreamPos);
+ aCodec.BeginCompression();
+ nDecompressedSize = aCodec.Read(rStream, sExtendedOrDecompressedFirstBytes, 2048);
+ nCheckSize = nDecompressedSize < 256 ? nDecompressedSize : 256;
+ aCodec.EndCompression();
+ pCheckArray = sExtendedOrDecompressedFirstBytes;
+ }
- if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
- {
- bIsSvg = true;
- }
+ bool bIsSvg(false);
- delete[] pBuf;
- }
+ // check for Xml
+ // #119176# SVG files which have no xml header at all have shown up this is optional
+ if( ImplSearchEntry(pCheckArray, (sal_uInt8*)"<?xml", nCheckSize, 5 ) // is it xml
+ && ImplSearchEntry(pCheckArray, (sal_uInt8*)"version", nCheckSize, 7 )) // does it have a version (required for xml)
+ {
- if(bIsSvg)
+ // check for DOCTYPE svg combination
+ if( ImplSearchEntry(pCheckArray, (sal_uInt8*)"DOCTYPE", nCheckSize, 7 ) // 'DOCTYPE' is there
+ && ImplSearchEntry(pCheckArray, (sal_uInt8*)"svg", nCheckSize, 3 )) // 'svg' is there
{
- rFormatExtension = "SVG";
- return true;
+ bIsSvg = true;
}
}
- else
+
+ // check for svg element in 1st 256 bytes
+ if(!bIsSvg && ImplSearchEntry(pCheckArray, (sal_uInt8*)"<svg", nCheckSize, 4 )) // '<svg'
+ {
+ bIsSvg = true;
+ }
+
+ // extended search for svg element
+ if(!bIsSvg)
{
- // #119176# SVG files which have no xml header at all have shown up,
- // detect those, too
- bool bIsSvg(false);
+ // it's a xml, look for '<svg' in full file. Should not happen too
+ // often since the tests above will handle most cases, but can happen
+ // with Svg files containing big comment headers or Svg as the host
+ // language
- // check for svg element in 1st 256 bytes
- if(ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
+ pCheckArray = sExtendedOrDecompressedFirstBytes;
+
+ if(!bIsGZip)
{
- bIsSvg = true;
+ nCheckSize = nDecompressedSize < 2048 ? nDecompressedSize : 2048;
}
-
- if(!bIsSvg)
+ else
{
- // look for '<svg' in full file. Should not happen too
- // often since the tests above will handle most cases, but can happen
- // with SVG files containing big comment headers or SVG as the host
- // language
- const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
- sal_uInt8* pBuf = new sal_uInt8[nSize];
-
+ nCheckSize = nStreamLen < 2048 ? nStreamLen : 2048;
rStream.Seek(nStreamPos);
- rStream.Read(pBuf, nSize);
-
- if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
- {
- bIsSvg = true;
- }
-
- delete[] pBuf;
+ rStream.Read(sExtendedOrDecompressedFirstBytes, nCheckSize);
}
- if(bIsSvg)
+ if(ImplSearchEntry(pCheckArray, (sal_uInt8*)"<svg", nCheckSize, 4)) // '<svg'
{
- rFormatExtension = "SVG";
- return true;
+ bIsSvg = true;
}
}
+
+ if(bIsSvg)
+ {
+ rFormatExtension = "SVG";
+ return true;
+ }
}
else if( rFormatExtension.startsWith( "SVG" ) )
{
@@ -1521,27 +1513,53 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPat
if( rGraphic.GetContext() == (GraphicReader*) 1 )
rGraphic.SetContext( NULL );
- const sal_uInt32 nStmPos(rIStream.Tell());
- const sal_uInt32 nStmLen(rIStream.Seek(STREAM_SEEK_TO_END) - nStmPos);
+ const sal_uInt32 nStreamPosition(rIStream.Tell());
+ const sal_uInt32 nStreamLength(rIStream.Seek(STREAM_SEEK_TO_END) - nStreamPosition);
+
bool bOkay(false);
- if(nStmLen)
+ if(nStreamLength > 0)
{
- SvgDataArray aNewData(new sal_uInt8[nStmLen]);
+ std::vector<sal_uInt8> aTwoBytes(2);
+ rIStream.Seek(nStreamPosition);
+ rIStream.Read(&aTwoBytes[0], 2);
+ rIStream.Seek(nStreamPosition);
+ if(aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
+ {
+ SvMemoryStream aMemStream;
+ GZCodec aCodec;
+ sal_uInt32 nMemoryLength;
- rIStream.Seek(nStmPos);
- rIStream.Read(aNewData.get(), nStmLen);
+ aCodec.BeginCompression();
+ nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
+ aCodec.EndCompression();
- if(!rIStream.GetError())
+ if(!rIStream.GetError() )
+ {
+ SvgDataArray aNewData(new sal_uInt8[nMemoryLength]);
+ aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
+ aMemStream.Read(aNewData.get(), nMemoryLength);
+
+ if(!aMemStream.GetError() )
+ {
+ SvgDataPtr aSvgDataPtr(new SvgData(aNewData, nMemoryLength, rPath));
+ rGraphic = Graphic(aSvgDataPtr);
+ bOkay = true;
+ }
+ }
+ }
+ else
{
- SvgDataPtr aSvgDataPtr(
- new SvgData(
- aNewData,
- nStmLen,
- rPath));
-
- rGraphic = Graphic(aSvgDataPtr);
- bOkay = true;
+ SvgDataArray aNewData(new sal_uInt8[nStreamLength]);
+ rIStream.Seek(nStreamPosition);
+ rIStream.Read(aNewData.get(), nStreamLength);
+
+ if(!rIStream.GetError())
+ {
+ SvgDataPtr aSvgDataPtr(new SvgData(aNewData, nStreamLength, rPath));
+ rGraphic = Graphic(aSvgDataPtr);
+ bOkay = true;
+ }
}
}
More information about the Libreoffice-commits
mailing list