Kaydet (Commit) c77c6c2a authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

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
üst 15f90918
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <ucbhelper/content.hxx> #include <ucbhelper/content.hxx>
#include <cppuhelper/implbase1.hxx> #include <cppuhelper/implbase1.hxx>
#include <tools/urlobj.hxx> #include <tools/urlobj.hxx>
#include <tools/zcodec.hxx>
#include <vcl/dibtools.hxx> #include <vcl/dibtools.hxx>
#include <vcl/salctype.hxx> #include <vcl/salctype.hxx>
#include <vcl/pngread.hxx> #include <vcl/pngread.hxx>
...@@ -255,7 +256,7 @@ bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen) ...@@ -255,7 +256,7 @@ bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
static bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, bool bTest ) static bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, bool bTest )
{ {
sal_uInt16 i; sal_uInt16 i;
sal_uInt8 sFirstBytes[ 256 ]; sal_uInt8 sFirstBytes[ 256 ];
sal_uLong nFirstLong,nSecondLong; sal_uLong nFirstLong,nSecondLong;
sal_uLong nStreamPos = rStream.Tell(); sal_uLong nStreamPos = rStream.Tell();
...@@ -645,89 +646,80 @@ static bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, ...@@ -645,89 +646,80 @@ static bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension,
//--------------------------- SVG ------------------------------------ //--------------------------- SVG ------------------------------------
if( !bTest ) if( !bTest )
{ {
// check for Xml sal_uInt8* pCheckArray = sFirstBytes;
if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<?xml", 256, 5 ) // is it xml sal_uLong nCheckSize = nStreamLen < 256 ? nStreamLen : 256;
&& 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;
}
// check for svg element in 1st 256 bytes sal_uInt8 sExtendedOrDecompressedFirstBytes[2048];
if(!bIsSvg && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg' sal_uLong nDecompressedSize = nCheckSize;
{
bIsSvg = true;
}
if(!bIsSvg) bool bIsGZip(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
const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
sal_uInt8* pBuf = new sal_uInt8[nSize];
rStream.Seek(nStreamPos); // check if it is gzipped -> svgz
rStream.Read(pBuf, nSize); 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' bool bIsSvg(false);
{
bIsSvg = true;
}
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"; bIsSvg = true;
return 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, // it's a xml, look for '<svg' in full file. Should not happen too
// detect those, too // often since the tests above will handle most cases, but can happen
bool bIsSvg(false); // with Svg files containing big comment headers or Svg as the host
// language
// check for svg element in 1st 256 bytes pCheckArray = sExtendedOrDecompressedFirstBytes;
if(ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
if(!bIsGZip)
{ {
bIsSvg = true; nCheckSize = nDecompressedSize < 2048 ? nDecompressedSize : 2048;
} }
else
if(!bIsSvg)
{ {
// look for '<svg' in full file. Should not happen too nCheckSize = nStreamLen < 2048 ? nStreamLen : 2048;
// 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];
rStream.Seek(nStreamPos); rStream.Seek(nStreamPos);
rStream.Read(pBuf, nSize); rStream.Read(sExtendedOrDecompressedFirstBytes, nCheckSize);
if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
{
bIsSvg = true;
}
delete[] pBuf;
} }
if(bIsSvg) if(ImplSearchEntry(pCheckArray, (sal_uInt8*)"<svg", nCheckSize, 4)) // '<svg'
{ {
rFormatExtension = "SVG"; bIsSvg = true;
return true;
} }
} }
if(bIsSvg)
{
rFormatExtension = "SVG";
return true;
}
} }
else if( rFormatExtension.startsWith( "SVG" ) ) else if( rFormatExtension.startsWith( "SVG" ) )
{ {
...@@ -1521,27 +1513,53 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPat ...@@ -1521,27 +1513,53 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPat
if( rGraphic.GetContext() == (GraphicReader*) 1 ) if( rGraphic.GetContext() == (GraphicReader*) 1 )
rGraphic.SetContext( NULL ); rGraphic.SetContext( NULL );
const sal_uInt32 nStmPos(rIStream.Tell()); const sal_uInt32 nStreamPosition(rIStream.Tell());
const sal_uInt32 nStmLen(rIStream.Seek(STREAM_SEEK_TO_END) - nStmPos); const sal_uInt32 nStreamLength(rIStream.Seek(STREAM_SEEK_TO_END) - nStreamPosition);
bool bOkay(false); 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); aCodec.BeginCompression();
rIStream.Read(aNewData.get(), nStmLen); 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( SvgDataArray aNewData(new sal_uInt8[nStreamLength]);
new SvgData( rIStream.Seek(nStreamPosition);
aNewData, rIStream.Read(aNewData.get(), nStreamLength);
nStmLen,
rPath)); if(!rIStream.GetError())
{
rGraphic = Graphic(aSvgDataPtr); SvgDataPtr aSvgDataPtr(new SvgData(aNewData, nStreamLength, rPath));
bOkay = true; rGraphic = Graphic(aSvgDataPtr);
bOkay = true;
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment