diff options
-rw-r--r-- | vcl/inc/TypeSerializer.hxx | 4 | ||||
-rw-r--r-- | vcl/qa/cppunit/TypeSerializerTest.cxx | 57 | ||||
-rw-r--r-- | vcl/source/gdi/TypeSerializer.cxx | 117 |
3 files changed, 178 insertions, 0 deletions
diff --git a/vcl/inc/TypeSerializer.hxx b/vcl/inc/TypeSerializer.hxx index befd4edd7660..4ac7e06471ea 100644 --- a/vcl/inc/TypeSerializer.hxx +++ b/vcl/inc/TypeSerializer.hxx @@ -24,6 +24,7 @@ #include <tools/GenericTypeSerializer.hxx> #include <vcl/gradient.hxx> #include <vcl/gfxlink.hxx> +#include <vcl/graph.hxx> class VCL_DLLPUBLIC TypeSerializer : public tools::GenericTypeSerializer { @@ -35,6 +36,9 @@ public: void readGfxLink(GfxLink& rGfxLink); void writeGfxLink(const GfxLink& rGfxLink); + + static void readGraphic(Graphic& rGraphic); + void writeGraphic(const Graphic& rGraphic); }; #endif diff --git a/vcl/qa/cppunit/TypeSerializerTest.cxx b/vcl/qa/cppunit/TypeSerializerTest.cxx index e5d3a259f803..0c737a4c4f03 100644 --- a/vcl/qa/cppunit/TypeSerializerTest.cxx +++ b/vcl/qa/cppunit/TypeSerializerTest.cxx @@ -130,6 +130,43 @@ void TypeSerializerTest::testGraphic() CPPUNIT_ASSERT_EQUAL(std::string("c2bed2099ce617f1cc035701de5186f0d43e3064"), toHexString(aHash)); } + + // Test TypeSerializer - Native Format 5 + { + SvMemoryStream aMemoryStream; + aMemoryStream.SetVersion(SOFFICE_FILEFORMAT_50); + aMemoryStream.SetCompressMode(SvStreamCompressFlags::NATIVE); + { + TypeSerializer aSerializer(aMemoryStream); + aSerializer.writeGraphic(aGraphic); + } + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(290), aMemoryStream.remainingSize()); + std::vector<unsigned char> aHash = calculateHash(aMemoryStream); + CPPUNIT_ASSERT_EQUAL(std::string("ee55ab6faa73b61b68bc3d5628d95f0d3c528e2a"), + toHexString(aHash)); + + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + sal_uInt32 nType; + aMemoryStream.ReadUInt32(nType); + CPPUNIT_ASSERT_EQUAL(COMPAT_FORMAT('N', 'A', 'T', '5'), nType); + } + + // Test TypeSerializer - Normal + { + SvMemoryStream aMemoryStream; + { + TypeSerializer aSerializer(aMemoryStream); + aSerializer.writeGraphic(aGraphic); + } + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(233), aMemoryStream.remainingSize()); + std::vector<unsigned char> aHash = calculateHash(aMemoryStream); + CPPUNIT_ASSERT_EQUAL(std::string("c2bed2099ce617f1cc035701de5186f0d43e3064"), + toHexString(aHash)); + } } void TypeSerializerTest::testGraphic_Bitmap_NoGfxLink() @@ -155,6 +192,26 @@ void TypeSerializerTest::testGraphic_Bitmap_NoGfxLink() aMemoryStream.ReadUInt16(nType); CPPUNIT_ASSERT_EQUAL(sal_uInt16(0x4D42), nType); // Magic written with WriteDIBBitmapEx } + + // Test TypeSerializer + { + SvMemoryStream aMemoryStream; + { + TypeSerializer aSerializer(aMemoryStream); + aSerializer.writeGraphic(aGraphic); + } + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(383), aMemoryStream.remainingSize()); + std::vector<unsigned char> aHash = calculateHash(aMemoryStream); + CPPUNIT_ASSERT_EQUAL(std::string("da831418499146d51bf245fadf60b9111faa76c2"), + toHexString(aHash)); + + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + sal_uInt16 nType; + aMemoryStream.ReadUInt16(nType); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(0x4D42), nType); // Magic written with WriteDIBBitmapEx + } } } // namespace diff --git a/vcl/source/gdi/TypeSerializer.cxx b/vcl/source/gdi/TypeSerializer.cxx index ad2f1400da85..8266c6ac9813 100644 --- a/vcl/source/gdi/TypeSerializer.cxx +++ b/vcl/source/gdi/TypeSerializer.cxx @@ -20,6 +20,8 @@ #include <TypeSerializer.hxx> #include <tools/vcompat.hxx> #include <sal/log.hxx> +#include <comphelper/fileformat.h> +#include <vcl/gdimtf.hxx> TypeSerializer::TypeSerializer(SvStream& rStream) : GenericTypeSerializer(rStream) @@ -148,4 +150,119 @@ void TypeSerializer::writeGfxLink(const GfxLink& rGfxLink) } } +namespace +{ +constexpr sal_uInt32 constSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) + | (sal_uInt32('g') << 8) | sal_uInt32('0')); +constexpr sal_uInt32 constWmfMagic((sal_uInt32('w') << 24) | (sal_uInt32('m') << 16) + | (sal_uInt32('f') << 8) | sal_uInt32('0')); +constexpr sal_uInt32 constEmfMagic((sal_uInt32('e') << 24) | (sal_uInt32('m') << 16) + | (sal_uInt32('f') << 8) | sal_uInt32('0')); +constexpr sal_uInt32 constPdfMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) + | (sal_uInt32('g') << 8) | sal_uInt32('0')); + +#define NATIVE_FORMAT_50 COMPAT_FORMAT('N', 'A', 'T', '5') + +} // end anonymous namespace + +void TypeSerializer::readGraphic(Graphic& /*rGraphic*/) {} + +void TypeSerializer::writeGraphic(const Graphic& rGraphic) +{ + Graphic aGraphic(rGraphic); + + if (!aGraphic.makeAvailable()) + return; + + auto pGfxLink = aGraphic.GetSharedGfxLink(); + + if (mrStream.GetVersion() >= SOFFICE_FILEFORMAT_50 + && (mrStream.GetCompressMode() & SvStreamCompressFlags::NATIVE) && pGfxLink + && pGfxLink->IsNative()) + { + // native format + mrStream.WriteUInt32(NATIVE_FORMAT_50); + + // write compat info, destructor writes stuff into the header + { + VersionCompat aCompat(mrStream, StreamMode::WRITE, 1); + } + pGfxLink->SetPrefMapMode(aGraphic.GetPrefMapMode()); + pGfxLink->SetPrefSize(aGraphic.GetPrefSize()); + writeGfxLink(*pGfxLink); + } + else + { + // own format + const SvStreamEndian nOldFormat = mrStream.GetEndian(); + mrStream.SetEndian(SvStreamEndian::LITTLE); + + switch (aGraphic.GetType()) + { + case GraphicType::NONE: + case GraphicType::Default: + break; + + case GraphicType::Bitmap: + { + auto pVectorGraphicData = aGraphic.getVectorGraphicData(); + if (pVectorGraphicData) + { + // 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 (pVectorGraphicData->getVectorGraphicDataType()) + { + case VectorGraphicDataType::Wmf: + { + mrStream.WriteUInt32(constWmfMagic); + break; + } + case VectorGraphicDataType::Emf: + { + mrStream.WriteUInt32(constEmfMagic); + break; + } + case VectorGraphicDataType::Svg: + { + mrStream.WriteUInt32(constSvgMagic); + break; + } + case VectorGraphicDataType::Pdf: + { + mrStream.WriteUInt32(constPdfMagic); + break; + } + } + + sal_uInt32 nSize = pVectorGraphicData->getVectorGraphicDataArrayLength(); + mrStream.WriteUInt32(nSize); + mrStream.WriteBytes( + pVectorGraphicData->getVectorGraphicDataArray().getConstArray(), nSize); + mrStream.WriteUniOrByteString(pVectorGraphicData->getPath(), + mrStream.GetStreamCharSet()); + } + else if (aGraphic.IsAnimated()) + { + WriteAnimation(mrStream, aGraphic.GetAnimation()); + } + else + { + WriteDIBBitmapEx(aGraphic.GetBitmapEx(), mrStream); + } + } + break; + + default: + { + if (aGraphic.IsSupportedGraphic()) + WriteGDIMetaFile(mrStream, rGraphic.GetGDIMetaFile()); + } + break; + } + mrStream.SetEndian(nOldFormat); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |