1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include <osl/file.h> 32 #include <tools/vcompat.hxx> 33 #include <tools/urlobj.hxx> 34 #include <tools/debug.hxx> 35 #include <unotools/ucbstreamhelper.hxx> 36 #include <unotools/tempfile.hxx> 37 #include <ucbhelper/content.hxx> 38 #include <vcl/graph.hxx> 39 #include <vcl/gfxlink.hxx> 40 #include <vcl/cvtgrf.hxx> 41 #include <com/sun/star/ucb/CommandAbortedException.hpp> 42 43 // ----------- 44 // - GfxLink - 45 // ----------- 46 47 GfxLink::GfxLink() : 48 meType ( GFX_LINK_TYPE_NONE ), 49 mpBuf ( NULL ), 50 mpSwap ( NULL ), 51 mnBufSize ( 0 ), 52 mnUserId ( 0UL ), 53 mpImpData ( new ImpGfxLink ) 54 { 55 } 56 57 // ------------------------------------------------------------------------ 58 59 GfxLink::GfxLink( const GfxLink& rGfxLink ) : 60 mpImpData( new ImpGfxLink ) 61 { 62 ImplCopy( rGfxLink ); 63 } 64 65 // ------------------------------------------------------------------------ 66 67 GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType, sal_Bool bOwns ) : 68 mpImpData( new ImpGfxLink ) 69 { 70 DBG_ASSERT( (pBuf != NULL && nSize) || (!bOwns && nSize == 0), 71 "GfxLink::GfxLink(): empty/NULL buffer given" ); 72 73 meType = nType; 74 mnBufSize = nSize; 75 mpSwap = NULL; 76 mnUserId = 0UL; 77 78 if( bOwns ) 79 mpBuf = new ImpBuffer( pBuf ); 80 else if( nSize ) 81 { 82 mpBuf = new ImpBuffer( nSize ); 83 memcpy( mpBuf->mpBuffer, pBuf, nSize ); 84 } 85 else 86 mpBuf = NULL; 87 } 88 89 // ------------------------------------------------------------------------ 90 91 GfxLink::~GfxLink() 92 { 93 if( mpBuf && !( --mpBuf->mnRefCount ) ) 94 delete mpBuf; 95 96 if( mpSwap && !( --mpSwap->mnRefCount ) ) 97 delete mpSwap; 98 99 delete mpImpData; 100 } 101 102 // ------------------------------------------------------------------------ 103 104 GfxLink& GfxLink::operator=( const GfxLink& rGfxLink ) 105 { 106 if( &rGfxLink != this ) 107 { 108 if ( mpBuf && !( --mpBuf->mnRefCount ) ) 109 delete mpBuf; 110 111 if( mpSwap && !( --mpSwap->mnRefCount ) ) 112 delete mpSwap; 113 114 ImplCopy( rGfxLink ); 115 } 116 117 return *this; 118 } 119 120 // ------------------------------------------------------------------------ 121 122 sal_Bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const 123 { 124 sal_Bool bIsEqual = sal_False; 125 126 if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) ) 127 { 128 const sal_uInt8* pSource = GetData(); 129 const sal_uInt8* pDest = rGfxLink.GetData(); 130 sal_uInt32 nSourceSize = GetDataSize(); 131 sal_uInt32 nDestSize = rGfxLink.GetDataSize(); 132 if ( pSource && pDest && ( nSourceSize == nDestSize ) ) 133 { 134 bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0; 135 } 136 else if ( ( pSource == 0 ) && ( pDest == 0 ) ) 137 bIsEqual = sal_True; 138 } 139 return bIsEqual; 140 } 141 142 // ------------------------------------------------------------------------ 143 144 void GfxLink::ImplCopy( const GfxLink& rGfxLink ) 145 { 146 mnBufSize = rGfxLink.mnBufSize; 147 meType = rGfxLink.meType; 148 mpBuf = rGfxLink.mpBuf; 149 mpSwap = rGfxLink.mpSwap; 150 mnUserId = rGfxLink.mnUserId; 151 *mpImpData = *rGfxLink.mpImpData; 152 153 if( mpBuf ) 154 mpBuf->mnRefCount++; 155 156 if( mpSwap ) 157 mpSwap->mnRefCount++; 158 } 159 160 // ------------------------------------------------------------------------ 161 162 GfxLinkType GfxLink::GetType() const 163 { 164 return meType; 165 } 166 167 // ------------------------------------------------------------------------ 168 169 sal_Bool GfxLink::IsNative() const 170 { 171 return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID ); 172 } 173 174 // ------------------------------------------------------------------------ 175 176 sal_uInt32 GfxLink::GetDataSize() const 177 { 178 return mnBufSize; 179 } 180 181 // ------------------------------------------------------------------------ 182 183 const sal_uInt8* GfxLink::GetData() const 184 { 185 if( IsSwappedOut() ) 186 ( (GfxLink*) this )->SwapIn(); 187 188 return( mpBuf ? mpBuf->mpBuffer : NULL ); 189 } 190 191 // ------------------------------------------------------------------------ 192 193 const Size& GfxLink::GetPrefSize() const 194 { 195 return mpImpData->maPrefSize; 196 } 197 198 // ------------------------------------------------------------------------ 199 200 void GfxLink::SetPrefSize( const Size& rPrefSize ) 201 { 202 mpImpData->maPrefSize = rPrefSize; 203 mpImpData->mbPrefSizeValid = true; 204 } 205 206 // ------------------------------------------------------------------------ 207 208 bool GfxLink::IsPrefSizeValid() 209 { 210 return mpImpData->mbPrefSizeValid; 211 } 212 213 // ------------------------------------------------------------------------ 214 215 const MapMode& GfxLink::GetPrefMapMode() const 216 { 217 return mpImpData->maPrefMapMode; 218 } 219 220 // ------------------------------------------------------------------------ 221 222 void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode ) 223 { 224 mpImpData->maPrefMapMode = rPrefMapMode; 225 mpImpData->mbPrefMapModeValid = true; 226 } 227 228 // ------------------------------------------------------------------------ 229 230 bool GfxLink::IsPrefMapModeValid() 231 { 232 return mpImpData->mbPrefMapModeValid; 233 } 234 235 // ------------------------------------------------------------------------ 236 237 sal_Bool GfxLink::LoadNative( Graphic& rGraphic ) 238 { 239 sal_Bool bRet = sal_False; 240 241 if( IsNative() && mnBufSize ) 242 { 243 const sal_uInt8* pData = GetData(); 244 245 if( pData ) 246 { 247 SvMemoryStream aMemStm; 248 sal_uLong nCvtType; 249 250 aMemStm.SetBuffer( (char*) pData, mnBufSize, sal_False, mnBufSize ); 251 252 switch( meType ) 253 { 254 case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break; 255 case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break; 256 case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break; 257 case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break; 258 case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break; 259 case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break; 260 case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break; 261 case( GFX_LINK_TYPE_NATIVE_SVG ): nCvtType = CVT_SVG; break; 262 263 default: nCvtType = CVT_UNKNOWN; break; 264 } 265 266 if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) ) 267 bRet = sal_True; 268 } 269 } 270 271 return bRet; 272 } 273 274 // ------------------------------------------------------------------------ 275 276 void GfxLink::SwapOut() 277 { 278 if( !IsSwappedOut() && mpBuf ) 279 { 280 mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize ); 281 282 if( !mpSwap->IsSwapped() ) 283 { 284 delete mpSwap; 285 mpSwap = NULL; 286 } 287 else 288 { 289 if( !( --mpBuf->mnRefCount ) ) 290 delete mpBuf; 291 292 mpBuf = NULL; 293 } 294 } 295 } 296 297 // ------------------------------------------------------------------------ 298 299 void GfxLink::SwapIn() 300 { 301 if( IsSwappedOut() ) 302 { 303 mpBuf = new ImpBuffer( mpSwap->GetData() ); 304 305 if( !( --mpSwap->mnRefCount ) ) 306 delete mpSwap; 307 308 mpSwap = NULL; 309 } 310 } 311 312 // ------------------------------------------------------------------------ 313 314 sal_Bool GfxLink::ExportNative( SvStream& rOStream ) const 315 { 316 if( GetDataSize() ) 317 { 318 if( IsSwappedOut() ) 319 mpSwap->WriteTo( rOStream ); 320 else if( GetData() ) 321 rOStream.Write( GetData(), GetDataSize() ); 322 } 323 324 return ( rOStream.GetError() == ERRCODE_NONE ); 325 } 326 327 // ------------------------------------------------------------------------ 328 329 SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink ) 330 { 331 VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 2 ); 332 333 // Version 1 334 rOStream << (sal_uInt16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId(); 335 336 // Version 2 337 rOStream << rGfxLink.GetPrefSize() << rGfxLink.GetPrefMapMode(); 338 339 delete pCompat; 340 341 if( rGfxLink.GetDataSize() ) 342 { 343 if( rGfxLink.IsSwappedOut() ) 344 rGfxLink.mpSwap->WriteTo( rOStream ); 345 else if( rGfxLink.GetData() ) 346 rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() ); 347 } 348 349 return rOStream; 350 } 351 352 // ------------------------------------------------------------------------ 353 354 SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink) 355 { 356 Size aSize; 357 MapMode aMapMode; 358 sal_uInt32 nSize; 359 sal_uInt32 nUserId; 360 sal_uInt16 nType; 361 sal_uInt8* pBuf; 362 bool bMapAndSizeValid( false ); 363 VersionCompat* pCompat = new VersionCompat( rIStream, STREAM_READ ); 364 365 // Version 1 366 rIStream >> nType >> nSize >> nUserId; 367 368 if( pCompat->GetVersion() >= 2 ) 369 { 370 rIStream >> aSize >> aMapMode; 371 bMapAndSizeValid = true; 372 } 373 374 delete pCompat; 375 376 pBuf = new sal_uInt8[ nSize ]; 377 rIStream.Read( pBuf, nSize ); 378 379 rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, sal_True ); 380 rGfxLink.SetUserId( nUserId ); 381 382 if( bMapAndSizeValid ) 383 { 384 rGfxLink.SetPrefSize( aSize ); 385 rGfxLink.SetPrefMapMode( aMapMode ); 386 } 387 388 return rIStream; 389 } 390 391 // ----------- 392 // - ImpSwap - 393 // ----------- 394 395 ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) : 396 mnDataSize( nDataSize ), 397 mnRefCount( 1UL ) 398 { 399 if( pData && mnDataSize ) 400 { 401 ::utl::TempFile aTempFile; 402 403 maURL = aTempFile.GetURL(); 404 if( maURL.getLength() ) 405 { 406 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 407 if( pOStm ) 408 { 409 pOStm->Write( pData, mnDataSize ); 410 sal_Bool bError = ( ERRCODE_NONE != pOStm->GetError() ); 411 delete pOStm; 412 413 if( bError ) 414 { 415 osl_removeFile( maURL.pData ); 416 maURL = String(); 417 } 418 } 419 } 420 } 421 } 422 423 // ------------------------------------------------------------------------ 424 425 ImpSwap::~ImpSwap() 426 { 427 if( IsSwapped() ) 428 osl_removeFile( maURL.pData ); 429 } 430 431 // ------------------------------------------------------------------------ 432 433 sal_uInt8* ImpSwap::GetData() const 434 { 435 sal_uInt8* pData; 436 437 if( IsSwapped() ) 438 { 439 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE ); 440 if( pIStm ) 441 { 442 pData = new sal_uInt8[ mnDataSize ]; 443 pIStm->Read( pData, mnDataSize ); 444 sal_Bool bError = ( ERRCODE_NONE != pIStm->GetError() ); 445 delete pIStm; 446 447 if( bError ) 448 delete[] pData, pData = NULL; 449 } 450 else 451 pData = NULL; 452 } 453 else 454 pData = NULL; 455 456 return pData; 457 } 458 459 // ------------------------------------------------------------------------ 460 461 void ImpSwap::WriteTo( SvStream& rOStm ) const 462 { 463 sal_uInt8* pData = GetData(); 464 465 if( pData ) 466 { 467 rOStm.Write( pData, mnDataSize ); 468 delete[] pData; 469 } 470 } 471