summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamjan Jovanovic <damjan@apache.org>2024-02-14 22:02:35 +0100
committerThorsten Behrens <thorsten.behrens@allotropia.de>2024-02-15 22:09:34 +0100
commit6c04b8356c0764ba8ac51448eee5ff577b08d9e2 (patch)
tree7d9e31d2f2266712a9b121d80014b23e1f990a9e
parent70b287d599a2bbddd8c67f51809a0513c2bdb2e6 (diff)
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.behrens@allotropia.de> Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
-rw-r--r--include/sot/formats.hxx3
-rw-r--r--sfx2/source/doc/sfxbasemodel.cxx47
-rw-r--r--sot/source/base/exchange.cxx1
-rw-r--r--vcl/source/treelist/transfer.cxx36
4 files changed, 77 insertions, 10 deletions
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 ) )
{