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 ) ) {