vcl/inc/impgraph.hxx        |    2 
 vcl/source/gdi/impgraph.cxx |  268 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 265 insertions(+), 5 deletions(-)

New commits:
commit fcd617586ea577a234739cb21248f411e7eda402
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sat Nov 28 11:13:09 2020 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Sun Dec 6 23:33:34 2020 +0100

    vcl: duplicate {Read,Write}ImpGraphic for swapping
    
    For swapping we can change the algroithm of saving and rading
    graphics to/from the swap file as the file format doesn't need to
    be stable. This duplicates the algorithm, but doesn't change it
    yet.
    
    Change-Id: I0b0854b19f4e3f9a34d278f44bd61cd94e133def
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107284
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx
index 9ad34e6f57b1..de5df4a1ac57 100644
--- a/vcl/inc/impgraph.hxx
+++ b/vcl/inc/impgraph.hxx
@@ -170,9 +170,11 @@ private:
 private:
     // swapping methods
     bool swapInFromStream(SvStream& rStream);
+    void swapInGraphic(SvStream& rStream);
 
     bool swapInContent(SvStream& rStream);
     bool swapOutContent(SvStream& rStream);
+    bool swapOutGraphic(SvStream& rStream);
     // end swapping
 
     std::shared_ptr<GraphicReader>& ImplGetContext() { return mpContext;}
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 42de58769aca..d06911a0bde5 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -1113,11 +1113,11 @@ bool ImpGraphic::swapInContent(SvStream& rStream)
     Size aSize;
     sal_uInt32 nId;
     sal_Int32 nType;
-    sal_Int32  nPageIndex = -1;
+    sal_Int32 nPageIndex = -1;
     const SvStreamEndian nOldFormat = rStream.GetEndian();
 
-    rStream.SetEndian( SvStreamEndian::LITTLE );
-    rStream.ReadUInt32( nId );
+    rStream.SetEndian(SvStreamEndian::LITTLE);
+    rStream.ReadUInt32(nId);
 
     // check version
     if (GRAPHIC_FORMAT_50 != nId)
@@ -1166,7 +1166,7 @@ bool ImpGraphic::swapInContent(SvStream& rStream)
 
         if( meType == GraphicType::Bitmap || meType == 
GraphicType::GdiMetafile )
         {
-            ReadImpGraphic(rStream, *this);
+            swapInGraphic(rStream);
             bRet = rStream.GetError() == ERRCODE_NONE;
         }
         else if( sal::static_int_cast<sal_uLong>(meType) >= SYS_WINMETAFILE
@@ -1212,6 +1212,103 @@ bool ImpGraphic::swapInContent(SvStream& rStream)
     return bRet;
 }
 
+bool ImpGraphic::swapOutGraphic(SvStream& rStream)
+{
+    if (rStream.GetError())
+        return false;
+
+    ensureAvailable();
+
+    if (isSwappedOut())
+    {
+        rStream.SetError(SVSTREAM_GENERALERROR);
+        return false;
+    }
+
+    if (rStream.GetVersion() >= SOFFICE_FILEFORMAT_50 &&
+        rStream.GetCompressMode() & SvStreamCompressFlags::NATIVE &&
+        mpGfxLink && mpGfxLink->IsNative())
+    {
+        // native format
+        rStream.WriteUInt32(NATIVE_FORMAT_50);
+
+        // write compat info, destructor writes stuff into the header
+        {
+            VersionCompat aCompat(rStream, StreamMode::WRITE, 1);
+        }
+        mpGfxLink->SetPrefMapMode(ImplGetPrefMapMode());
+        mpGfxLink->SetPrefSize(ImplGetPrefSize());
+        TypeSerializer aSerializer(rStream);
+        aSerializer.writeGfxLink(*mpGfxLink);
+    }
+    else
+    {
+        switch (ImplGetType())
+        {
+            case GraphicType::NONE:
+            case GraphicType::Default:
+            break;
+
+            case GraphicType::Bitmap:
+            {
+                if (getVectorGraphicData())
+                {
+                    // stream out Vector Graphic defining data (length, byte 
array and evtl. path)
+                    // this is used e.g. in swapping out graphic data and in 
transporting it over UNO API
+                    // as sequence of bytes, but AFAIK not written anywhere to 
any kind of file, so it should be
+                    // no problem to extend it; only used at runtime
+                    switch (getVectorGraphicData()->getVectorGraphicDataType())
+                    {
+                        case VectorGraphicDataType::Wmf:
+                        {
+                            rStream.WriteUInt32(constWmfMagic);
+                            break;
+                        }
+                        case VectorGraphicDataType::Emf:
+                        {
+                            rStream.WriteUInt32(constEmfMagic);
+                            break;
+                        }
+                        case VectorGraphicDataType::Svg:
+                        {
+                            rStream.WriteUInt32(constSvgMagic);
+                            break;
+                        }
+                        case VectorGraphicDataType::Pdf:
+                        {
+                            rStream.WriteUInt32(constPdfMagic);
+                            break;
+                        }
+                    }
+
+                    
rStream.WriteUInt32(getVectorGraphicData()->getVectorGraphicDataArrayLength());
+                    rStream.WriteBytes(
+                        
getVectorGraphicData()->getVectorGraphicDataArray().getConstArray(),
+                        
getVectorGraphicData()->getVectorGraphicDataArrayLength());
+                    
rStream.WriteUniOrByteString(getVectorGraphicData()->getPath(), 
rStream.GetStreamCharSet());
+                }
+                else if (ImplIsAnimated())
+                {
+                    WriteAnimation(rStream, *mpAnimation);
+                }
+                else
+                {
+                    WriteDIBBitmapEx(maBitmapEx, rStream);
+                }
+            }
+            break;
+
+            default:
+            {
+                if (ImplIsSupportedGraphic())
+                    WriteGDIMetaFile(rStream, maMetaFile);
+            }
+            break;
+        }
+    }
+    return true;
+}
+
 bool ImpGraphic::swapOutContent(SvStream& rOStm)
 {
     ensureAvailable();
@@ -1257,7 +1354,7 @@ bool ImpGraphic::swapOutContent(SvStream& rOStm)
         const sal_uLong nDataStart = rOStm.Tell();
 
         if (ImplIsSupportedGraphic())
-            WriteImpGraphic( rOStm, *this );
+            swapOutGraphic(rOStm);
 
         if( !rOStm.GetError() )
         {
@@ -1446,6 +1543,167 @@ bool ImpGraphic::swapInFromStream(SvStream& rStream)
     return bRet;
 }
 
+void ImpGraphic::swapInGraphic(SvStream& rStream)
+{
+    if (rStream.GetError())
+        return;
+
+    const sal_uLong nStmPos1 = rStream.Tell();
+    sal_uInt32 nID;
+
+    ImplClear();
+
+    // read Id
+    rStream.ReadUInt32(nID);
+
+    // if there is no more data, avoid further expensive
+    // reading which will create VDevs and other stuff, just to
+    // read nothing. CAUTION: Eof is only true AFTER reading another
+    // byte, a speciality of SvMemoryStream (!)
+    if (!rStream.good())
+        return;
+
+    if (NATIVE_FORMAT_50 == nID)
+    {
+        Graphic aGraphic;
+        GfxLink aLink;
+
+        // read compat info, destructor writes stuff into the header
+        {
+            VersionCompat aCompat(rStream, StreamMode::READ);
+        }
+
+        TypeSerializer aSerializer(rStream);
+        aSerializer.readGfxLink(aLink);
+
+        // set dummy link to avoid creation of additional link after filtering;
+        // we set a default link to avoid unnecessary swapping of native data
+        aGraphic.SetGfxLink(std::make_shared<GfxLink>());
+
+        if (!rStream.GetError() && aLink.LoadNative(aGraphic))
+        {
+            // set link only, if no other link was set
+            const bool bSetLink = !mpGfxLink;
+
+            // assign graphic
+            *this = *aGraphic.ImplGetImpGraphic();
+
+            if (aLink.IsPrefMapModeValid())
+                ImplSetPrefMapMode(aLink.GetPrefMapMode());
+
+            if (aLink.IsPrefSizeValid())
+                ImplSetPrefSize(aLink.GetPrefSize());
+
+            if (bSetLink)
+                ImplSetLink(std::make_shared<GfxLink>(aLink));
+        }
+        else
+        {
+            rStream.Seek(nStmPos1);
+            rStream.SetError(ERRCODE_IO_WRONGFORMAT);
+        }
+        return;
+    }
+
+    BitmapEx aBmpEx;
+    const SvStreamEndian nOldFormat = rStream.GetEndian();
+
+    rStream.SeekRel(-4);
+    rStream.SetEndian(SvStreamEndian::LITTLE);
+    ReadDIBBitmapEx(aBmpEx, rStream);
+
+    if (!rStream.GetError())
+    {
+        sal_uInt32 nMagic1(0);
+        sal_uInt32 nMagic2(0);
+        sal_uLong nActPos = rStream.Tell();
+
+        rStream.ReadUInt32(nMagic1);
+        rStream.ReadUInt32(nMagic2);
+        rStream.Seek(nActPos);
+
+        *this = ImpGraphic(aBmpEx);
+
+        if (!rStream.GetError() && (0x5344414e == nMagic1) && (0x494d4931 == 
nMagic2))
+        {
+            mpAnimation = std::make_unique<Animation>();
+            ReadAnimation(rStream, *mpAnimation);
+
+            // #108077# manually set loaded BmpEx to Animation
+            // (which skips loading its BmpEx if already done)
+            mpAnimation->SetBitmapEx(aBmpEx);
+        }
+        else
+            rStream.ResetError();
+    }
+    else
+    {
+        GDIMetaFile aMetaFile;
+
+        rStream.Seek(nStmPos1);
+        rStream.ResetError();
+        ReadGDIMetaFile(rStream, aMetaFile);
+
+        if (!rStream.GetError())
+        {
+            *this = aMetaFile;
+        }
+        else
+        {
+            ErrCode nOrigError = rStream.GetErrorCode();
+            // try to stream in Svg defining data (length, byte array and 
evtl. path)
+            // See below (operator<<) for more information
+            sal_uInt32 nMagic;
+            rStream.Seek(nStmPos1);
+            rStream.ResetError();
+            rStream.ReadUInt32( nMagic );
+
+            if (constSvgMagic == nMagic || constWmfMagic == nMagic || 
constEmfMagic == nMagic || constPdfMagic == nMagic)
+            {
+                sal_uInt32 nVectorGraphicDataArrayLength(0);
+                rStream.ReadUInt32(nVectorGraphicDataArrayLength);
+
+                if (nVectorGraphicDataArrayLength)
+                {
+                    VectorGraphicDataArray 
aNewData(nVectorGraphicDataArrayLength);
+
+                    rStream.ReadBytes(aNewData.getArray(), 
nVectorGraphicDataArrayLength);
+                    OUString aPath = 
rStream.ReadUniOrByteString(rStream.GetStreamCharSet());
+
+                    if (!rStream.GetError())
+                    {
+                        VectorGraphicDataType 
aDataType(VectorGraphicDataType::Svg);
+
+                        if (constWmfMagic == nMagic)
+                        {
+                            aDataType = VectorGraphicDataType::Wmf;
+                        }
+                        else if (constEmfMagic == nMagic)
+                        {
+                            aDataType = VectorGraphicDataType::Emf;
+                        }
+                        else if (constPdfMagic == nMagic)
+                        {
+                            aDataType = VectorGraphicDataType::Pdf;
+                        }
+
+                        auto aVectorGraphicDataPtr = 
std::make_shared<VectorGraphicData>(aNewData, aPath, aDataType);
+                        *this = ImpGraphic(aVectorGraphicDataPtr);
+                    }
+                }
+            }
+            else
+            {
+                rStream.SetError(nOrigError);
+            }
+
+            rStream.Seek(nStmPos1);
+        }
+    }
+
+    rStream.SetEndian(nOldFormat);
+}
+
 void ImpGraphic::ImplSetLink(const std::shared_ptr<GfxLink>& rGfxLink)
 {
     ensureAvailable();
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to