vcl/source/filter/ixbm/xbmread.cxx | 170 +++++++++++++++---------------------- vcl/source/filter/ixpm/xpmread.cxx | 161 +++++++++++++++-------------------- 2 files changed, 143 insertions(+), 188 deletions(-)
New commits: commit c9edd5e543c5c791171a4c40a226bf0f13a24d80 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Sat Mar 23 20:53:30 2024 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sat Mar 30 15:23:04 2024 +0100 vcl: cleanup XPMReader class - rename members with clearer names Change-Id: I185a72a972d35c29d774a53476a345664497be6a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165209 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/vcl/source/filter/ixpm/xpmread.cxx b/vcl/source/filter/ixpm/xpmread.cxx index 918a75d5a7fb..eca9b50287bd 100644 --- a/vcl/source/filter/ixpm/xpmread.cxx +++ b/vcl/source/filter/ixpm/xpmread.cxx @@ -61,99 +61,82 @@ enum ReadState class BitmapWriteAccess; class Graphic; -namespace { +namespace +{ class XPMReader : public GraphicReader { private: - - SvStream& mrIStm; - Bitmap maBmp; - BitmapScopedWriteAccess mpAcc; - Bitmap maMaskBmp; - BitmapScopedWriteAccess mpMaskAcc; - tools::Long mnLastPos; - - sal_uLong mnWidth; - sal_uLong mnHeight; - sal_uLong mnColors; - sal_uInt32 mnCpp; // characters per pix - bool mbTransparent; - bool mbStatus; - sal_uLong mnStatus; - sal_uLong mnIdentifier; - sal_uInt8 mcThisByte; - sal_uInt8 mcLastByte; - sal_uLong mnTempAvail; - sal_uInt8* mpTempBuf; - sal_uInt8* mpTempPtr; + SvStream& mrStream; + Bitmap maBitmap; + BitmapScopedWriteAccess mpWriterAccess; + Bitmap maMaskBitmap; + BitmapScopedWriteAccess mpMaskWriterAccess; + sal_uInt64 mnLastPos; + + tools::Long mnWidth = 0; + tools::Long mnHeight = 0; + sal_uLong mnColors = 0; + sal_uInt32 mnCpp = 0; // characters per pix + bool mbTransparent = false; + bool mbStatus = true; + sal_uLong mnStatus = 0; + sal_uLong mnIdentifier = XPMIDENTIFIER; + sal_uInt8 mcThisByte = 0; + sal_uInt8 mcLastByte = 0; + sal_uLong mnTempAvail = 0; + sal_uInt8* mpTempBuf = nullptr; + sal_uInt8* mpTempPtr = nullptr; // each key is ( mnCpp )Byte(s)-> ASCII entry assigned to the colour // each colordata is // 1 Byte -> 0xFF if colour is transparent // 3 Bytes -> RGB value of the colour - typedef std::array<sal_uInt8,4> colordata; - typedef std::map<OString, colordata> colormap; - colormap maColMap; - sal_uLong mnStringSize; - sal_uInt8* mpStringBuf; - sal_uLong mnParaSize; - sal_uInt8* mpPara; + typedef std::array<sal_uInt8, 4> ColorData; + typedef std::map<OString, ColorData> ColorMap; + ColorMap maColMap; + sal_uLong mnStringSize = 0; + sal_uInt8* mpStringBuf = nullptr; + sal_uLong mnParaSize = 0; + sal_uInt8* mpPara = nullptr; bool ImplGetString(); bool ImplGetColor(); bool ImplGetScanLine( sal_uLong ); - bool ImplGetColSub(colordata &rDest); + bool ImplGetColSub(ColorData &rDest); bool ImplGetColKey( sal_uInt8 ); - void ImplGetRGBHex(colordata &rDest, sal_uLong); + void ImplGetRGBHex(ColorData &rDest, sal_uLong); bool ImplGetPara( sal_uLong numb ); static bool ImplCompare(sal_uInt8 const *, sal_uInt8 const *, sal_uLong); sal_uLong ImplGetULONG( sal_uLong nPara ); public: - explicit XPMReader( SvStream& rStm ); + explicit XPMReader(SvStream& rStream); - ReadState ReadXPM( Graphic& rGraphic ); + ReadState ReadXPM(Graphic& rGraphic); }; } -XPMReader::XPMReader(SvStream& rStm) - : mrIStm(rStm) - , mnLastPos(rStm.Tell()) - , mnWidth(0) - , mnHeight(0) - , mnColors(0) - , mnCpp(0) - , mbTransparent(false) - , mbStatus(true) - , mnStatus( 0 ) - , mnIdentifier(XPMIDENTIFIER) - , mcThisByte(0) - , mcLastByte(0) - , mnTempAvail(0) - , mpTempBuf(nullptr) - , mpTempPtr(nullptr) - , mnStringSize(0) - , mpStringBuf(nullptr) - , mnParaSize(0) - , mpPara(nullptr) +XPMReader::XPMReader(SvStream& rStream) + : mrStream(rStream) + , mnLastPos(rStream.Tell()) { } -ReadState XPMReader::ReadXPM( Graphic& rGraphic ) +ReadState XPMReader::ReadXPM(Graphic& rGraphic) { ReadState eReadState; sal_uInt8 cDummy; // check if we can real ALL - mrIStm.Seek( STREAM_SEEK_TO_END ); - mrIStm.ReadUChar( cDummy ); + mrStream.Seek( STREAM_SEEK_TO_END ); + mrStream.ReadUChar( cDummy ); // if we could not read all // return and wait for new data - if ( mrIStm.GetError() != ERRCODE_IO_PENDING ) + if (mrStream.GetError() != ERRCODE_IO_PENDING) { - mrIStm.Seek( mnLastPos ); + mrStream.Seek( mnLastPos ); mbStatus = true; if ( mbStatus ) @@ -176,7 +159,7 @@ ReadState XPMReader::ReadXPM( Graphic& rGraphic ) 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 (mrIStm.remainingSize() + mnTempAvail < static_cast<sal_uInt64>(mnWidth) * mnHeight) + if (mrStream.remainingSize() + mnTempAvail < static_cast<sal_uInt64>(mnWidth) * mnHeight) mbStatus = false; if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp ) { @@ -200,25 +183,25 @@ ReadState XPMReader::ReadXPM( Graphic& rGraphic ) else ePixelFormat = vcl::PixelFormat::N8_BPP; - maBmp = Bitmap(Size(mnWidth, mnHeight), ePixelFormat); - mpAcc = maBmp; + maBitmap = Bitmap(Size(mnWidth, mnHeight), ePixelFormat); + mpWriterAccess = maBitmap; // mbTransparent is TRUE if at least one colour is transparent if ( mbTransparent ) { - maMaskBmp = Bitmap(Size(mnWidth, mnHeight), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); - mpMaskAcc = maMaskBmp; - if ( !mpMaskAcc ) + maMaskBitmap = Bitmap(Size(mnWidth, mnHeight), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); + mpMaskWriterAccess = maMaskBitmap; + if (!mpMaskWriterAccess) mbStatus = false; } - if( mpAcc && mbStatus ) + if (mpWriterAccess && mbStatus) { if (mnColors <= 256) // palette is only needed by using less than 257 { // colors sal_uInt8 i = 0; for (auto& elem : maColMap) { - mpAcc->SetPaletteColor(i, Color(elem.second[1], elem.second[2], elem.second[3])); + 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++; @@ -227,7 +210,7 @@ ReadState XPMReader::ReadXPM( Graphic& rGraphic ) // now we get the bitmap data mnIdentifier = XPMPIXELS; - for (sal_uLong i = 0; i < mnHeight; ++i) + for (tools::Long i = 0; i < mnHeight; ++i) { if ( !ImplGetScanLine( i ) ) { @@ -246,29 +229,29 @@ ReadState XPMReader::ReadXPM( Graphic& rGraphic ) } if( mbStatus ) { - mpAcc.reset(); - if ( mpMaskAcc ) + mpWriterAccess.reset(); + if (mpMaskWriterAccess) { - mpMaskAcc.reset(); - rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) ); + mpMaskWriterAccess.reset(); + rGraphic = Graphic(BitmapEx(maBitmap, maMaskBitmap)); } else { - rGraphic = BitmapEx(maBmp); + rGraphic = BitmapEx(maBitmap); } eReadState = XPMREAD_OK; } else { - mpMaskAcc.reset(); - mpAcc.reset(); + mpMaskWriterAccess.reset(); + mpWriterAccess.reset(); eReadState = XPMREAD_ERROR; } } else { - mrIStm.ResetError(); + mrStream.ResetError(); eReadState = XPMREAD_NEED_MORE; } return eReadState; @@ -286,7 +269,7 @@ bool XPMReader::ImplGetColor() return false; OString aKey(reinterpret_cast<char*>(pString), mnCpp); - colordata aValue{0}; + ColorData aValue{0}; bool bStatus = ImplGetColSub(aValue); if (bStatus) { @@ -306,29 +289,29 @@ bool XPMReader::ImplGetScanLine( sal_uLong nY ) if ( bStatus ) { - if ( mpMaskAcc ) + if (mpMaskWriterAccess) { - aWhite = mpMaskAcc->GetBestMatchingColor( COL_WHITE ); - aBlack = mpMaskAcc->GetBestMatchingColor( COL_BLACK ); + aWhite = mpMaskWriterAccess->GetBestMatchingColor( COL_WHITE ); + aBlack = mpMaskWriterAccess->GetBestMatchingColor( COL_BLACK ); } - if ( mnStringSize != ( mnWidth * mnCpp )) + if (mnStringSize != (sal_uLong(mnWidth) * mnCpp)) bStatus = false; else { - Scanline pScanline = mpAcc->GetScanline(nY); - Scanline pMaskScanline = mpMaskAcc ? mpMaskAcc->GetScanline(nY) : nullptr; - for (sal_uLong i = 0; i < mnWidth; ++i) + Scanline pScanline = mpWriterAccess->GetScanline(nY); + Scanline pMaskScanline = mpMaskWriterAccess ? mpMaskWriterAccess->GetScanline(nY) : nullptr; + for (tools::Long i = 0; i < mnWidth; ++i) { OString aKey(reinterpret_cast<char*>(pString), mnCpp); auto it = maColMap.find(aKey); if (it != maColMap.end()) { if (mnColors > 256) - mpAcc->SetPixelOnData(pScanline, i, Color(it->second[1], it->second[2], it->second[3])); + mpWriterAccess->SetPixelOnData(pScanline, i, Color(it->second[1], it->second[2], it->second[3])); else - mpAcc->SetPixelOnData(pScanline, i, BitmapColor(it->second[1])); + mpWriterAccess->SetPixelOnData(pScanline, i, BitmapColor(it->second[1])); if (pMaskScanline) - mpMaskAcc->SetPixelOnData(pMaskScanline, i, it->second[0] ? aWhite : aBlack); + mpMaskWriterAccess->SetPixelOnData(pMaskScanline, i, it->second[0] ? aWhite : aBlack); } pString += mnCpp; } @@ -341,7 +324,7 @@ bool XPMReader::ImplGetScanLine( sal_uLong nY ) // if a colour was found the RGB value is written a pDest[1]..pDest[2] // pDest[0] contains 0xFF if the colour is transparent otherwise 0 -bool XPMReader::ImplGetColSub(colordata &rDest) +bool XPMReader::ImplGetColSub(ColorData& rDest) { unsigned char cTransparent[] = "None"; @@ -459,7 +442,7 @@ bool XPMReader::ImplGetColKey( sal_uInt8 nKey ) // 2 : '#1234abcd1234' " " " " // 6 : '#12345678abcdefab12345678' " " " " -void XPMReader::ImplGetRGBHex(colordata &rDest, sal_uLong nAdd) +void XPMReader::ImplGetRGBHex(ColorData& rDest, sal_uLong nAdd) { sal_uInt8* pPtr = mpPara+1; @@ -584,7 +567,7 @@ bool XPMReader::ImplGetString() { if ( mnTempAvail == 0 ) { - mnTempAvail = mrIStm.ReadBytes( mpTempBuf, XPMTEMPBUFSIZE ); + mnTempAvail = mrStream.ReadBytes( mpTempBuf, XPMTEMPBUFSIZE ); if ( mnTempAvail == 0 ) break; commit d2cb896711a92ff5513a85efdc1fc656cf6976ed Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Sat Mar 23 20:25:33 2024 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sat Mar 30 15:22:54 2024 +0100 vcl: remove partial XBM image loading This removes the code that handles the IO_PENDING and the graphic "context" handling from XBM 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: Idb11f4ffa821467374b19f22b5841cfe940b9457 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165208 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/vcl/source/filter/ixbm/xbmread.cxx b/vcl/source/filter/ixbm/xbmread.cxx index 7b475ddab7de..5b6ae9dd7d07 100644 --- a/vcl/source/filter/ixbm/xbmread.cxx +++ b/vcl/source/filter/ixbm/xbmread.cxx @@ -28,7 +28,8 @@ #include "xbmread.hxx" -namespace { +namespace +{ enum XBMFormat { @@ -39,8 +40,7 @@ enum XBMFormat enum ReadState { XBMREAD_OK, - XBMREAD_ERROR, - XBMREAD_NEED_MORE + XBMREAD_ERROR }; class XBMReader : public GraphicReader @@ -51,7 +51,7 @@ class XBMReader : public GraphicReader std::array<short, 256> mpHexTable = { 0 }; BitmapColor maWhite; BitmapColor maBlack; - tools::Long mnLastPos = 0; + sal_uInt64 mnLastPosition = 0; tools::Long nWidth = 0; tools::Long nHeight = 0; bool bStatus = true; @@ -65,14 +65,14 @@ public: explicit XBMReader(SvStream& rStream); - ReadState ReadXBM(Graphic& rGraphic); + ReadState ReadXBM(BitmapEx& rBitmapEx); }; } XBMReader::XBMReader(SvStream& rStream) : mrStream(rStream) - , mnLastPos(rStream.Tell()) + , mnLastPosition(rStream.Tell()) { maUpperName = "SVIXBM"; InitTable(); @@ -262,128 +262,100 @@ void XBMReader::ParseData( SvStream* pInStm, const OString& aLastLine, XBMFormat } } -ReadState XBMReader::ReadXBM( Graphic& rGraphic ) +ReadState XBMReader::ReadXBM(BitmapEx& rBitmapEx) { - ReadState eReadState; - sal_uInt8 cDummy; + if (!mrStream.good()) + return XBMREAD_ERROR; - // check if we can read ALL - mrStream.Seek( STREAM_SEEK_TO_END ); - mrStream.ReadUChar( cDummy ); + ReadState eReadState = XBMREAD_ERROR; - // if we cannot read all - // we return and wait for new data - if (mrStream.GetError() != ERRCODE_IO_PENDING ) - { - mrStream.Seek(mnLastPos); - bStatus = false; - OString aLine = FindTokenLine(&mrStream, "#define", "_width"); + mrStream.Seek(mnLastPosition); + bStatus = false; + OString aLine = FindTokenLine(&mrStream, "#define", "_width"); - if ( bStatus ) + if ( bStatus ) + { + int nValue; + if ( ( nValue = ParseDefine( aLine.getStr() ) ) > 0 ) { - int nValue; - if ( ( nValue = ParseDefine( aLine.getStr() ) ) > 0 ) + nWidth = nValue; + aLine = FindTokenLine(&mrStream, "#define", "_height"); + + // if height was not received, we search again + // from start of the file + if ( !bStatus ) { - nWidth = nValue; + mrStream.Seek(mnLastPosition); aLine = FindTokenLine(&mrStream, "#define", "_height"); - - // if height was not received, we search again - // from start of the file - if ( !bStatus ) - { - mrStream.Seek(mnLastPos); - aLine = FindTokenLine(&mrStream, "#define", "_height"); - } } - else - bStatus = false; + } + else + bStatus = false; - if ( bStatus ) + if ( bStatus ) + { + if ( ( nValue = ParseDefine( aLine.getStr() ) ) > 0 ) { - if ( ( nValue = ParseDefine( aLine.getStr() ) ) > 0 ) + nHeight = nValue; + aLine = FindTokenLine(&mrStream, "static", "_bits"); + + if ( bStatus ) { - nHeight = nValue; - aLine = FindTokenLine(&mrStream, "static", "_bits"); + XBMFormat eFormat = XBM10; - if ( bStatus ) - { - XBMFormat eFormat = XBM10; + if (aLine.indexOf("short") != -1) + eFormat = XBM10; + else if (aLine.indexOf("char") != -1) + eFormat = XBM11; + else + bStatus = false; - if (aLine.indexOf("short") != -1) - eFormat = XBM10; - else if (aLine.indexOf("char") != -1) - eFormat = XBM11; - else - bStatus = false; + //xbms are a minimum of one character per 8 pixels, so if the file isn't + //even that long, it's not all there + if (mrStream.remainingSize() < (static_cast<sal_uInt64>(nWidth) * nHeight) / 8) + bStatus = false; - //xbms are a minimum of one character per 8 pixels, so if the file isn't - //even that long, it's not all there - if (mrStream.remainingSize() < (static_cast<sal_uInt64>(nWidth) * nHeight) / 8) - bStatus = false; + if ( bStatus && nWidth && nHeight ) + { + maBitmap = Bitmap(Size(nWidth, nHeight), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); + mpWriteAccess = maBitmap; - if ( bStatus && nWidth && nHeight ) + if (mpWriteAccess) { - maBitmap = Bitmap(Size(nWidth, nHeight), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); - mpWriteAccess = maBitmap; - - if (mpWriteAccess) - { - maWhite = mpWriteAccess->GetBestMatchingColor(COL_WHITE); - maBlack = mpWriteAccess->GetBestMatchingColor(COL_BLACK); - ParseData(&mrStream, aLine, eFormat); - } - else - bStatus = false; + maWhite = mpWriteAccess->GetBestMatchingColor(COL_WHITE); + maBlack = mpWriteAccess->GetBestMatchingColor(COL_BLACK); + ParseData(&mrStream, aLine, eFormat); } + else + bStatus = false; } } } } - - if (bStatus && mpWriteAccess) - { - Bitmap aBlackBmp(Size(mpWriteAccess->Width(), mpWriteAccess->Height()), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); - - mpWriteAccess.reset(); - aBlackBmp.Erase( COL_BLACK ); - rGraphic = BitmapEx(aBlackBmp, maBitmap); - eReadState = XBMREAD_OK; - } - else - eReadState = XBMREAD_ERROR; } - else + + if (bStatus && mpWriteAccess) { - mrStream.ResetError(); - eReadState = XBMREAD_NEED_MORE; + Bitmap aBlackBmp(Size(mpWriteAccess->Width(), mpWriteAccess->Height()), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); + + mpWriteAccess.reset(); + aBlackBmp.Erase( COL_BLACK ); + rBitmapEx = BitmapEx(aBlackBmp, maBitmap); + eReadState = XBMREAD_OK; } return eReadState; } -VCL_DLLPUBLIC bool ImportXBM( SvStream& rStm, Graphic& rGraphic ) +VCL_DLLPUBLIC bool ImportXBM(SvStream& rStmeam, Graphic& rGraphic) { - std::shared_ptr<GraphicReader> pContext = rGraphic.GetReaderContext(); - rGraphic.SetReaderContext(nullptr); - XBMReader* pXBMReader = dynamic_cast<XBMReader*>( pContext.get() ); - if (!pXBMReader) - { - pContext = std::make_shared<XBMReader>( rStm ); - pXBMReader = static_cast<XBMReader*>( pContext.get() ); - } - - bool bRet = true; - - ReadState eReadState = pXBMReader->ReadXBM( rGraphic ); - - if( eReadState == XBMREAD_ERROR ) - { - bRet = false; - } - else if( eReadState == XBMREAD_NEED_MORE ) - rGraphic.SetReaderContext( pContext ); - - return bRet; + XBMReader aXBMReader(rStmeam); + BitmapEx aBitmapEx; + ReadState eReadState = aXBMReader.ReadXBM(aBitmapEx); + if (eReadState == XBMREAD_ERROR) + return false; + rGraphic = Graphic(aBitmapEx); + return true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */