include/sot/formats.hxx          |    3 +-
 sfx2/source/doc/sfxbasemodel.cxx |   47 ++++++++++++++++++++++++++++++++-------
 sot/source/base/exchange.cxx     |    1 
 vcl/source/treelist/transfer.cxx |   36 +++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+), 10 deletions(-)

New commits:
commit 6c04b8356c0764ba8ac51448eee5ff577b08d9e2
Author:     Damjan Jovanovic <dam...@apache.org>
AuthorDate: Wed Feb 14 22:02:35 2024 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Thu Feb 15 22:09:34 2024 +0100

    i#112829: offer svg as clipboard format as well
    
    When copying charts, shapes, etc. out of LibreOffice, export them to
    the clipboard in the (lossless) SVG graphics format as well.
    
    This can be pasted into GIMP, Inkscape, and other apps, unlike our
    current WMF/EMF clipboard formats which use private MIME types that
    nothing supports.
    
    (cherry picked from commit 61aee323790d0a1ed0745ee5a84b8885bcd0a559)
    
    Change-Id: Ia32be448a096154bb092d49f372148c6b2263f35
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163412
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/include/sot/formats.hxx b/include/sot/formats.hxx
index 12727ffb34c9..fbfa3754bd82 100644
--- a/include/sot/formats.hxx
+++ b/include/sot/formats.hxx
@@ -175,8 +175,9 @@ enum class SotClipboardFormatId : sal_uInt32
     RICHTEXT               = 145,
     STRING_TSVC            = 146,
     PDF                    = 147,
+    SVG                    = 148,
     // the point at which we start allocating "runtime" format IDs
-    USER_END  = PDF
+    USER_END  = SVG
 };
 
 /** Make it easier to iterate over format IDs */
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 5de773ac01e2..3d969f223fc1 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -2229,6 +2229,28 @@ Any SAL_CALL SfxBaseModel::getTransferData( const 
datatransfer::DataFlavor& aFla
             else
                 throw datatransfer::UnsupportedFlavorException();
         }
+        else if ( aFlavor.MimeType == "image/svg+xml" )
+        {
+            if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 
>>::get() )
+                throw datatransfer::UnsupportedFlavorException();
+
+            std::shared_ptr<GDIMetaFile> xMetaFile =
+                m_pData->m_pObjectShell->GetPreviewMetaFile( true );
+
+            if (xMetaFile)
+            {
+                std::unique_ptr<SvMemoryStream> xStream(
+                    GraphicHelper::getFormatStrFromGDI_Impl(
+                        xMetaFile.get(), ConvertDataFormat::SVG ) );
+
+                if (xStream)
+                {
+                    xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
+                    aAny <<= Sequence< sal_Int8 >( static_cast< const 
sal_Int8* >( xStream->GetData() ),
+                                                    xStream->TellEnd() );
+                }
+            }
+        }
         else if ( aFlavor.MimeType == 
"application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" )
         {
             if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 
>>::get() )
@@ -2288,7 +2310,7 @@ Sequence< datatransfer::DataFlavor > SAL_CALL 
SfxBaseModel::getTransferDataFlavo
 {
     SfxModelGuard aGuard( *this );
 
-    const sal_Int32 nSuppFlavors = 
GraphicHelper::supportsMetaFileHandle_Impl() ? 10 : 8;
+    const sal_Int32 nSuppFlavors = 
GraphicHelper::supportsMetaFileHandle_Impl() ? 11 : 9;
     Sequence< datatransfer::DataFlavor > aFlavorSeq( nSuppFlavors );
     auto pFlavorSeq = aFlavorSeq.getArray();
 
@@ -2331,17 +2353,21 @@ Sequence< datatransfer::DataFlavor > SAL_CALL 
SfxBaseModel::getTransferDataFlavo
     pFlavorSeq[7].HumanPresentableName = "PNG";
     pFlavorSeq[7].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
 
-    if ( nSuppFlavors == 10 )
+    pFlavorSeq[8].MimeType = "image/svg+xml";
+    pFlavorSeq[8].HumanPresentableName = "SVG";
+    pFlavorSeq[8].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
+
+    if ( nSuppFlavors == 11 )
     {
-        pFlavorSeq[8].MimeType =
+        pFlavorSeq[9].MimeType =
             "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
-        pFlavorSeq[8].HumanPresentableName = "Enhanced Windows MetaFile";
-        pFlavorSeq[8].DataType = cppu::UnoType<sal_uInt64>::get();
+        pFlavorSeq[9].HumanPresentableName = "Enhanced Windows MetaFile";
+        pFlavorSeq[9].DataType = cppu::UnoType<sal_uInt64>::get();
 
-        pFlavorSeq[9].MimeType =
+        pFlavorSeq[10].MimeType =
             "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
-        pFlavorSeq[9].HumanPresentableName = "Windows MetaFile";
-        pFlavorSeq[9].DataType = cppu::UnoType<sal_uInt64>::get();
+        pFlavorSeq[10].HumanPresentableName = "Windows MetaFile";
+        pFlavorSeq[10].DataType = cppu::UnoType<sal_uInt64>::get();
     }
 
     return aFlavorSeq;
@@ -2381,6 +2407,11 @@ sal_Bool SAL_CALL SfxBaseModel::isDataFlavorSupported( 
const datatransfer::DataF
           && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
             return true;
     }
+    else if ( aFlavor.MimeType == "image/svg+xml" )
+    {
+        if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
+            return true;
+    }
     else if ( aFlavor.MimeType == 
"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object 
Descriptor (XML)\"" )
     {
         if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
diff --git a/sot/source/base/exchange.cxx b/sot/source/base/exchange.cxx
index 9777c3117917..edff7f7c63d6 100644
--- a/sot/source/base/exchange.cxx
+++ b/sot/source/base/exchange.cxx
@@ -200,6 +200,7 @@ const DataFlavorRepresentation* FormatArray_Impl()
         /*145 SotClipboardFormatId::RICHTEXT*/ { "text/richtext", "Richtext 
Format", &cppu::UnoType<Sequence<sal_Int8>>::get() },
         /*146 SotClipboardFormatId::STRING_TSVC*/            { 
"application/x-libreoffice-tsvc", "Text TSV-Calc", 
&cppu::UnoType<OUString>::get() },
         /*147 SotClipboardFormatId::PDF*/            { "application/pdf", "PDF 
Document", &cppu::UnoType<Sequence<sal_Int8>>::get() },
+        /*148 SotClipboardFormatId::SVG*/            { 
"image/svg+xml;windows_formatname=\"image/svg+xml\"", "SVG", 
&cppu::UnoType<Sequence<sal_Int8>>::get() },
     };
     return &aInstance[0];
 };
diff --git a/vcl/source/treelist/transfer.cxx b/vcl/source/treelist/transfer.cxx
index 7e6009de77dc..0935f91500ce 100644
--- a/vcl/source/treelist/transfer.cxx
+++ b/vcl/source/treelist/transfer.cxx
@@ -413,6 +413,37 @@ Any SAL_CALL TransferableHelper::getTransferData2( const 
DataFlavor& rFlavor, co
                     }
                 }
             }
+            else if( SotExchange::GetFormatDataFlavor( 
SotClipboardFormatId::SVG, aSubstFlavor ) &&
+                     TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) 
&&
+                     SotExchange::GetFormatDataFlavor( 
SotClipboardFormatId::GDIMETAFILE, aSubstFlavor ) )
+            {
+                GetData(aSubstFlavor, rDestDoc);
+
+                if( maAny.hasValue() )
+                {
+                    Sequence< sal_Int8 > aSeq;
+
+                    if( maAny >>= aSeq )
+                    {
+                        GDIMetaFile     aMtf;
+                        {
+                            SvMemoryStream aSrcStm( aSeq.getArray(), 
aSeq.getLength(), StreamMode::WRITE | StreamMode::TRUNC );
+                            SvmReader aReader( aSrcStm );
+                            aReader.Read( aMtf );
+                        }
+
+                        SvMemoryStream  aDstStm( 65535, 65535 );
+                        Graphic         aGraphic( aMtf );
+
+                        if( GraphicConverter::Export( aDstStm, aGraphic, 
ConvertDataFormat::SVG ) == ERRCODE_NONE )
+                        {
+                            maAny <<= Sequence< sal_Int8 >( static_cast< const 
sal_Int8* >( aDstStm.GetData() ),
+                                                            aDstStm.TellEnd() 
);
+                            bDone = true;
+                        }
+                    }
+                }
+            }
 
             // reset Any if substitute doesn't work
             if( !bDone && maAny.hasValue() )
@@ -620,6 +651,7 @@ void TransferableHelper::AddFormat( const DataFlavor& 
rFlavor )
     {
         AddFormat( SotClipboardFormatId::EMF );
         AddFormat( SotClipboardFormatId::WMF );
+        AddFormat( SotClipboardFormatId::SVG );
     }
 }
 
@@ -1235,7 +1267,9 @@ void TransferableDataHelper::FillDataFlavorExVector( 
const Sequence< DataFlavor
                     rDataFlavorExVector.push_back( aFlavorEx );
                 }
             }
-            else if( SotClipboardFormatId::WMF == aFlavorEx.mnSotId || 
SotClipboardFormatId::EMF == aFlavorEx.mnSotId )
+            else if( SotClipboardFormatId::WMF == aFlavorEx.mnSotId
+                     || SotClipboardFormatId::EMF == aFlavorEx.mnSotId
+                     || SotClipboardFormatId::SVG == aFlavorEx.mnSotId )
             {
                 if( SotExchange::GetFormatDataFlavor( 
SotClipboardFormatId::GDIMETAFILE, aFlavorEx ) )
                 {

Reply via email to