vcl/source/filter/ixpm/xpmread.cxx |  213 ++++++++++++++++---------------------
 1 file changed, 93 insertions(+), 120 deletions(-)

New commits:
commit d8ece6a5f56f012ecf1766cc3f68c85706e3b6cb
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sat Mar 23 20:59:24 2024 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Apr 1 08:08:39 2024 +0200

    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 <qui...@gmail.com>

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: */

Reply via email to