Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / source / gdi / gfxlink.cxx
blob70e31776c1374be41f5fd978ff359ccf53b7d4fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/file.h>
21 #include <tools/stream.hxx>
22 #include <tools/vcompat.hxx>
23 #include <unotools/tempfile.hxx>
24 #include <vcl/graph.hxx>
25 #include <vcl/gfxlink.hxx>
26 #include <vcl/cvtgrf.hxx>
27 #include <memory>
28 #include <o3tl/make_shared.hxx>
30 GfxLink::GfxLink()
34 GfxLink::GfxLink( std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nSize, GfxLinkType nType )
36 SAL_WARN_IF( pBuf == nullptr || !nSize, "vcl",
37 "GfxLink::GfxLink(): empty/NULL buffer given" );
39 meType = nType;
40 mnSwapInDataSize = nSize;
41 mpSwapInData = std::shared_ptr<sal_uInt8>(pBuf.release(), pBuf.get_deleter()); // std::move(pBuf) does not compile on Jenkins MacOSX (24 May 2016)
44 bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const
46 bool bIsEqual = false;
48 if ( ( mnSwapInDataSize == rGfxLink.mnSwapInDataSize ) && ( meType == rGfxLink.meType ) )
50 const sal_uInt8* pSource = GetData();
51 const sal_uInt8* pDest = rGfxLink.GetData();
52 sal_uInt32 nSourceSize = GetDataSize();
53 sal_uInt32 nDestSize = rGfxLink.GetDataSize();
54 if ( pSource && pDest && ( nSourceSize == nDestSize ) )
56 bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0;
58 else if ( ( pSource == nullptr ) && ( pDest == nullptr ) )
59 bIsEqual = true;
61 return bIsEqual;
65 bool GfxLink::IsNative() const
67 return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
71 const sal_uInt8* GfxLink::GetData() const
73 if( IsSwappedOut() )
74 const_cast<GfxLink*>(this)->SwapIn();
76 return( mpSwapInData.get() );
80 void GfxLink::SetPrefSize( const Size& rPrefSize )
82 maPrefSize = rPrefSize;
83 mbPrefSizeValid = true;
87 void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode )
89 maPrefMapMode = rPrefMapMode;
90 mbPrefMapModeValid = true;
94 bool GfxLink::LoadNative( Graphic& rGraphic )
96 bool bRet = false;
98 if( IsNative() && mnSwapInDataSize )
100 const sal_uInt8* pData = GetData();
102 if( pData )
104 SvMemoryStream aMemStm;
105 ConvertDataFormat nCvtType;
107 aMemStm.SetBuffer( const_cast<sal_uInt8*>(pData), mnSwapInDataSize, mnSwapInDataSize );
109 switch( meType )
111 case GfxLinkType::NativeGif: nCvtType = ConvertDataFormat::GIF; break;
112 case GfxLinkType::NativeBmp: nCvtType = ConvertDataFormat::BMP; break;
113 case GfxLinkType::NativeJpg: nCvtType = ConvertDataFormat::JPG; break;
114 case GfxLinkType::NativePng: nCvtType = ConvertDataFormat::PNG; break;
115 case GfxLinkType::NativeTif: nCvtType = ConvertDataFormat::TIF; break;
116 case GfxLinkType::NativeWmf: nCvtType = ConvertDataFormat::WMF; break;
117 case GfxLinkType::NativeMet: nCvtType = ConvertDataFormat::MET; break;
118 case GfxLinkType::NativePct: nCvtType = ConvertDataFormat::PCT; break;
119 case GfxLinkType::NativeSvg: nCvtType = ConvertDataFormat::SVG; break;
121 default: nCvtType = ConvertDataFormat::Unknown; break;
124 if( nCvtType != ConvertDataFormat::Unknown && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
125 bRet = true;
129 return bRet;
132 void GfxLink::SwapOut()
134 if( !IsSwappedOut() && mpSwapInData && mnSwapInDataSize )
136 ::utl::TempFile aTempFile;
138 OUString aURL = aTempFile.GetURL();
140 if (!aURL.isEmpty())
142 std::shared_ptr<GfxLink::SwapOutData> pSwapOut = std::make_shared<SwapOutData>(aURL); // aURL is removed in the destructor
143 SvStream* pOStm = aTempFile.GetStream(StreamMode::STD_WRITE);
144 if (pOStm)
146 pOStm->WriteBytes(mpSwapInData.get(), mnSwapInDataSize);
147 bool bError = (ERRCODE_NONE != pOStm->GetError());
148 aTempFile.CloseStream();
150 if( !bError )
152 mpSwapOutData = pSwapOut;
153 mpSwapInData.reset();
160 void GfxLink::SwapIn()
162 if( IsSwappedOut() )
164 auto pData = GetSwapInData();
165 if (pData)
167 mpSwapInData = pData;
168 mpSwapOutData.reset();
173 bool GfxLink::ExportNative( SvStream& rOStream ) const
175 if( GetDataSize() )
177 auto pData = GetSwapInData();
178 if (pData)
179 rOStream.WriteBytes( pData.get(), mnSwapInDataSize );
182 return ( rOStream.GetError() == ERRCODE_NONE );
185 SvStream& WriteGfxLink( SvStream& rOStream, const GfxLink& rGfxLink )
187 std::unique_ptr<VersionCompat> pCompat(new VersionCompat( rOStream, StreamMode::WRITE, 2 ));
189 // Version 1
190 rOStream.WriteUInt16( (sal_uInt16)rGfxLink.GetType() ).WriteUInt32( rGfxLink.GetDataSize() ).WriteUInt32( rGfxLink.GetUserId() );
192 // Version 2
193 WritePair( rOStream, rGfxLink.GetPrefSize() );
194 WriteMapMode( rOStream, rGfxLink.GetPrefMapMode() );
196 pCompat.reset(); // destructor writes stuff into the header
198 if( rGfxLink.GetDataSize() )
200 auto pData = rGfxLink.GetSwapInData();
201 if (pData)
202 rOStream.WriteBytes( pData.get(), rGfxLink.mnSwapInDataSize );
205 return rOStream;
208 SvStream& ReadGfxLink( SvStream& rIStream, GfxLink& rGfxLink)
210 Size aSize;
211 MapMode aMapMode;
212 bool bMapAndSizeValid( false );
213 std::unique_ptr<VersionCompat> pCompat(new VersionCompat( rIStream, StreamMode::READ ));
215 // Version 1
216 sal_uInt16 nType(0);
217 sal_uInt32 nSize(0), nUserId(0);
218 rIStream.ReadUInt16(nType).ReadUInt32(nSize).ReadUInt32(nUserId);
220 if( pCompat->GetVersion() >= 2 )
222 ReadPair( rIStream, aSize );
223 ReadMapMode( rIStream, aMapMode );
224 bMapAndSizeValid = true;
227 pCompat.reset(); // destructor writes stuff into the header
229 auto nRemainingData = rIStream.remainingSize();
230 if (nSize > nRemainingData)
232 SAL_WARN("vcl", "graphic link stream is smaller than requested size");
233 nSize = nRemainingData;
236 std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ nSize ]);
237 rIStream.ReadBytes( pBuf.get(), nSize );
239 rGfxLink = GfxLink( std::move(pBuf), nSize, (GfxLinkType) nType );
240 rGfxLink.SetUserId( nUserId );
242 if( bMapAndSizeValid )
244 rGfxLink.SetPrefSize( aSize );
245 rGfxLink.SetPrefMapMode( aMapMode );
248 return rIStream;
251 GfxLink::SwapOutData::SwapOutData(const OUString &aURL) : maURL(aURL)
255 GfxLink::SwapOutData::~SwapOutData()
257 if( maURL.getLength() > 0 )
258 osl_removeFile( maURL.pData );
261 std::shared_ptr<sal_uInt8> GfxLink::GetSwapInData() const
263 if( !IsSwappedOut() )
264 return mpSwapInData;
266 std::shared_ptr<sal_uInt8> pData;
268 SvFileStream aFileStream(mpSwapOutData->maURL, StreamMode::STD_READ);
269 pData = o3tl::make_shared_array<sal_uInt8>(mnSwapInDataSize);
270 aFileStream.ReadBytes(pData.get(), mnSwapInDataSize);
271 bool bError = (ERRCODE_NONE != aFileStream.GetError());
272 sal_uInt64 const nActReadSize = aFileStream.Tell();
273 if (nActReadSize != mnSwapInDataSize)
274 bError = true;
275 if (bError)
276 pData.reset();
277 return pData;
280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */