diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2024-03-23 20:59:24 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2024-04-01 08:08:39 +0200 |
commit | d8ece6a5f56f012ecf1766cc3f68c85706e3b6cb (patch) | |
tree | c6a94f491474d189864302cbca8fd1a637a8639a /vcl | |
parent | 350c590620226c4d5b94aa01d3853e15af3cebb0 (diff) |
vcl: remove partial XPM image loading
This removes the code that handles the IO_PENDING and the graphic
"context" handling from XPM image format.
Partial loading of images complicates the image filter life cycle
a lot (many exceptions) and is not really needed so much today as
this was needed in the past. In most cases we load the whole image
in one pass anyway. Even loading from the network should be fast
enough to not cause issues for the user.
Most image filters don't even implement this like PNG and nobody
noticed for many years that this is not supported.
To handle IO_PENDING case it is probably better to load the
bitstream into memory and then load the whole image after that
in one pass. This can also be implemented all inside (Imp)Graphic
in a very straight forward way.
Change-Id: Icdc4f042b38936e3d9f11d7026fd8525a6f46943
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165210
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/filter/ixpm/xpmread.cxx | 213 |
1 files changed, 93 insertions, 120 deletions
diff --git a/vcl/source/filter/ixpm/xpmread.cxx b/vcl/source/filter/ixpm/xpmread.cxx index eca9b50287bd..1ad06483a712 100644 --- a/vcl/source/filter/ixpm/xpmread.cxx +++ b/vcl/source/filter/ixpm/xpmread.cxx @@ -52,8 +52,7 @@ namespace { enum ReadState { XPMREAD_OK, - XPMREAD_ERROR, - XPMREAD_NEED_MORE + XPMREAD_ERROR }; } @@ -112,7 +111,7 @@ private: public: explicit XPMReader(SvStream& rStream); - ReadState ReadXPM(Graphic& rGraphic); + ReadState ReadXPM(BitmapEx& rBitmapEx); }; } @@ -123,136 +122,122 @@ XPMReader::XPMReader(SvStream& rStream) { } -ReadState XPMReader::ReadXPM(Graphic& rGraphic) +ReadState XPMReader::ReadXPM(BitmapEx& rBitmapEx) { - ReadState eReadState; - sal_uInt8 cDummy; + if (!mrStream.good()) + return XPMREAD_ERROR; - // check if we can real ALL - mrStream.Seek( STREAM_SEEK_TO_END ); - mrStream.ReadUChar( cDummy ); + ReadState eReadState = XPMREAD_ERROR; - // if we could not read all - // return and wait for new data - if (mrStream.GetError() != ERRCODE_IO_PENDING) + mrStream.Seek( mnLastPos ); + mbStatus = true; + + if ( mbStatus ) { - mrStream.Seek( mnLastPos ); - mbStatus = true; + mpStringBuf = new sal_uInt8 [ XPMSTRINGBUF ]; + mpTempBuf = new sal_uInt8 [ XPMTEMPBUFSIZE ]; + mbStatus = ImplGetString(); if ( mbStatus ) { - mpStringBuf = new sal_uInt8 [ XPMSTRINGBUF ]; - mpTempBuf = new sal_uInt8 [ XPMTEMPBUFSIZE ]; + mnIdentifier = XPMVALUES; // fetch Bitmap information + mnWidth = ImplGetULONG( 0 ); + mnHeight = ImplGetULONG( 1 ); + mnColors = ImplGetULONG( 2 ); + mnCpp = ImplGetULONG( 3 ); + } + if ( mnColors > ( SAL_MAX_UINT32 / ( 4 + mnCpp ) ) ) + mbStatus = false; + if ( ( mnWidth * mnCpp ) >= XPMSTRINGBUF ) + mbStatus = false; + //xpms are a minimum of one character (one byte) per pixel, so if the file isn't + //even that long, it's not all there + if (mrStream.remainingSize() + mnTempAvail < static_cast<sal_uInt64>(mnWidth) * mnHeight) + mbStatus = false; + if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp ) + { + mnIdentifier = XPMCOLORS; - mbStatus = ImplGetString(); - if ( mbStatus ) + for (sal_uLong i = 0; i < mnColors; ++i) { - mnIdentifier = XPMVALUES; // fetch Bitmap information - mnWidth = ImplGetULONG( 0 ); - mnHeight = ImplGetULONG( 1 ); - mnColors = ImplGetULONG( 2 ); - mnCpp = ImplGetULONG( 3 ); + if (!ImplGetColor()) + { + mbStatus = false; + break; + } } - if ( mnColors > ( SAL_MAX_UINT32 / ( 4 + mnCpp ) ) ) - mbStatus = false; - if ( ( mnWidth * mnCpp ) >= XPMSTRINGBUF ) - mbStatus = false; - //xpms are a minimum of one character (one byte) per pixel, so if the file isn't - //even that long, it's not all there - if (mrStream.remainingSize() + mnTempAvail < static_cast<sal_uInt64>(mnWidth) * mnHeight) - mbStatus = false; - if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp ) + + if ( mbStatus ) { - mnIdentifier = XPMCOLORS; + // create a 24bit graphic when more as 256 colours present + auto ePixelFormat = vcl::PixelFormat::INVALID; + if ( mnColors > 256 ) + ePixelFormat = vcl::PixelFormat::N24_BPP; + else + ePixelFormat = vcl::PixelFormat::N8_BPP; - for (sal_uLong i = 0; i < mnColors; ++i) + maBitmap = Bitmap(Size(mnWidth, mnHeight), ePixelFormat); + mpWriterAccess = maBitmap; + + // mbTransparent is TRUE if at least one colour is transparent + if ( mbTransparent ) { - if (!ImplGetColor()) - { + maMaskBitmap = Bitmap(Size(mnWidth, mnHeight), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); + mpMaskWriterAccess = maMaskBitmap; + if (!mpMaskWriterAccess) mbStatus = false; - break; - } } - - if ( mbStatus ) + if (mpWriterAccess && mbStatus) { - // create a 24bit graphic when more as 256 colours present - auto ePixelFormat = vcl::PixelFormat::INVALID; - if ( mnColors > 256 ) - ePixelFormat = vcl::PixelFormat::N24_BPP; - else - ePixelFormat = vcl::PixelFormat::N8_BPP; - - maBitmap = Bitmap(Size(mnWidth, mnHeight), ePixelFormat); - mpWriterAccess = maBitmap; - - // mbTransparent is TRUE if at least one colour is transparent - if ( mbTransparent ) - { - maMaskBitmap = Bitmap(Size(mnWidth, mnHeight), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); - mpMaskWriterAccess = maMaskBitmap; - if (!mpMaskWriterAccess) - mbStatus = false; - } - if (mpWriterAccess && mbStatus) - { - if (mnColors <= 256) // palette is only needed by using less than 257 - { // colors - sal_uInt8 i = 0; - for (auto& elem : maColMap) - { - mpWriterAccess->SetPaletteColor(i, Color(elem.second[1], elem.second[2], elem.second[3])); - //reuse map entry, overwrite color with palette index - elem.second[1] = i; - i++; - } + if (mnColors <= 256) // palette is only needed by using less than 257 + { // colors + sal_uInt8 i = 0; + for (auto& elem : maColMap) + { + mpWriterAccess->SetPaletteColor(i, Color(elem.second[1], elem.second[2], elem.second[3])); + //reuse map entry, overwrite color with palette index + elem.second[1] = i; + i++; } + } - // now we get the bitmap data - mnIdentifier = XPMPIXELS; - for (tools::Long i = 0; i < mnHeight; ++i) + // now we get the bitmap data + mnIdentifier = XPMPIXELS; + for (tools::Long i = 0; i < mnHeight; ++i) + { + if ( !ImplGetScanLine( i ) ) { - if ( !ImplGetScanLine( i ) ) - { - mbStatus = false; - break; - } + mbStatus = false; + break; } - mnIdentifier = XPMEXTENSIONS; } + mnIdentifier = XPMEXTENSIONS; } } + } - delete[] mpStringBuf; - delete[] mpTempBuf; + delete[] mpStringBuf; + delete[] mpTempBuf; - } - if( mbStatus ) + } + if( mbStatus ) + { + mpWriterAccess.reset(); + if (mpMaskWriterAccess) { - mpWriterAccess.reset(); - if (mpMaskWriterAccess) - { - mpMaskWriterAccess.reset(); - rGraphic = Graphic(BitmapEx(maBitmap, maMaskBitmap)); - } - else - { - rGraphic = BitmapEx(maBitmap); - } - eReadState = XPMREAD_OK; + mpMaskWriterAccess.reset(); + rBitmapEx = BitmapEx(maBitmap, maMaskBitmap); } else { - mpMaskWriterAccess.reset(); - mpWriterAccess.reset(); - - eReadState = XPMREAD_ERROR; + rBitmapEx = BitmapEx(maBitmap); } + eReadState = XPMREAD_OK; } else { - mrStream.ResetError(); - eReadState = XPMREAD_NEED_MORE; + mpMaskWriterAccess.reset(); + mpWriterAccess.reset(); } return eReadState; } @@ -650,29 +635,17 @@ bool XPMReader::ImplGetString() } -VCL_DLLPUBLIC bool ImportXPM( SvStream& rStm, Graphic& rGraphic ) +VCL_DLLPUBLIC bool ImportXPM(SvStream& rStream, Graphic& rGraphic) { - std::shared_ptr<GraphicReader> pContext = rGraphic.GetReaderContext(); - rGraphic.SetReaderContext(nullptr); - XPMReader* pXPMReader = dynamic_cast<XPMReader*>( pContext.get() ); - if (!pXPMReader) - { - pContext = std::make_shared<XPMReader>( rStm ); - pXPMReader = static_cast<XPMReader*>( pContext.get() ); - } + XPMReader aXPMReader(rStream); - bool bRet = true; + BitmapEx aBitmapEx; + ReadState eReadState = aXPMReader.ReadXPM(aBitmapEx); - ReadState eReadState = pXPMReader->ReadXPM( rGraphic ); - - if( eReadState == XPMREAD_ERROR ) - { - bRet = false; - } - else if( eReadState == XPMREAD_NEED_MORE ) - rGraphic.SetReaderContext( pContext ); - - return bRet; + if (eReadState == XPMREAD_ERROR) + return false; + rGraphic = Graphic(aBitmapEx); + return true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |