1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <osl/file.h> 28 #include <tools/vcompat.hxx> 29 #include <tools/urlobj.hxx> 30 #include <tools/debug.hxx> 31 #include <unotools/ucbstreamhelper.hxx> 32 #include <unotools/tempfile.hxx> 33 #include <ucbhelper/content.hxx> 34 #include <vcl/graph.hxx> 35 #include <vcl/gfxlink.hxx> 36 #include <vcl/cvtgrf.hxx> 37 #include <com/sun/star/ucb/CommandAbortedException.hpp> 38 39 // ----------- 40 // - GfxLink - 41 // ----------- 42 43 GfxLink::GfxLink() : 44 meType ( GFX_LINK_TYPE_NONE ), 45 mpBuf ( NULL ), 46 mpSwap ( NULL ), 47 mnBufSize ( 0 ), 48 mnUserId ( 0UL ), 49 mpImpData ( new ImpGfxLink ) 50 { 51 } 52 53 // ------------------------------------------------------------------------ 54 55 GfxLink::GfxLink( const GfxLink& rGfxLink ) : 56 mpImpData( new ImpGfxLink ) 57 { 58 ImplCopy( rGfxLink ); 59 } 60 61 // ------------------------------------------------------------------------ 62 63 GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType, sal_Bool bOwns ) : 64 mpImpData( new ImpGfxLink ) 65 { 66 DBG_ASSERT( (pBuf != NULL && nSize) || (!bOwns && nSize == 0), 67 "GfxLink::GfxLink(): empty/NULL buffer given" ); 68 69 meType = nType; 70 mnBufSize = nSize; 71 mpSwap = NULL; 72 mnUserId = 0UL; 73 74 if( bOwns ) 75 mpBuf = new ImpBuffer( pBuf ); 76 else if( nSize ) 77 { 78 mpBuf = new ImpBuffer( nSize ); 79 memcpy( mpBuf->mpBuffer, pBuf, nSize ); 80 } 81 else 82 mpBuf = NULL; 83 } 84 85 // ------------------------------------------------------------------------ 86 87 GfxLink::~GfxLink() 88 { 89 if( mpBuf && !( --mpBuf->mnRefCount ) ) 90 delete mpBuf; 91 92 if( mpSwap && !( --mpSwap->mnRefCount ) ) 93 delete mpSwap; 94 95 delete mpImpData; 96 } 97 98 // ------------------------------------------------------------------------ 99 100 GfxLink& GfxLink::operator=( const GfxLink& rGfxLink ) 101 { 102 if( &rGfxLink != this ) 103 { 104 if ( mpBuf && !( --mpBuf->mnRefCount ) ) 105 delete mpBuf; 106 107 if( mpSwap && !( --mpSwap->mnRefCount ) ) 108 delete mpSwap; 109 110 ImplCopy( rGfxLink ); 111 } 112 113 return *this; 114 } 115 116 // ------------------------------------------------------------------------ 117 118 sal_Bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const 119 { 120 sal_Bool bIsEqual = sal_False; 121 122 if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) ) 123 { 124 const sal_uInt8* pSource = GetData(); 125 const sal_uInt8* pDest = rGfxLink.GetData(); 126 sal_uInt32 nSourceSize = GetDataSize(); 127 sal_uInt32 nDestSize = rGfxLink.GetDataSize(); 128 if ( pSource && pDest && ( nSourceSize == nDestSize ) ) 129 { 130 bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0; 131 } 132 else if ( ( pSource == 0 ) && ( pDest == 0 ) ) 133 bIsEqual = sal_True; 134 } 135 return bIsEqual; 136 } 137 138 // ------------------------------------------------------------------------ 139 140 void GfxLink::ImplCopy( const GfxLink& rGfxLink ) 141 { 142 mnBufSize = rGfxLink.mnBufSize; 143 meType = rGfxLink.meType; 144 mpBuf = rGfxLink.mpBuf; 145 mpSwap = rGfxLink.mpSwap; 146 mnUserId = rGfxLink.mnUserId; 147 *mpImpData = *rGfxLink.mpImpData; 148 149 if( mpBuf ) 150 mpBuf->mnRefCount++; 151 152 if( mpSwap ) 153 mpSwap->mnRefCount++; 154 } 155 156 // ------------------------------------------------------------------------ 157 158 GfxLinkType GfxLink::GetType() const 159 { 160 return meType; 161 } 162 163 // ------------------------------------------------------------------------ 164 165 sal_Bool GfxLink::IsNative() const 166 { 167 return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID ); 168 } 169 170 // ------------------------------------------------------------------------ 171 172 sal_uInt32 GfxLink::GetDataSize() const 173 { 174 return mnBufSize; 175 } 176 177 // ------------------------------------------------------------------------ 178 179 const sal_uInt8* GfxLink::GetData() const 180 { 181 if( IsSwappedOut() ) 182 ( (GfxLink*) this )->SwapIn(); 183 184 return( mpBuf ? mpBuf->mpBuffer : NULL ); 185 } 186 187 // ------------------------------------------------------------------------ 188 189 const Size& GfxLink::GetPrefSize() const 190 { 191 return mpImpData->maPrefSize; 192 } 193 194 // ------------------------------------------------------------------------ 195 196 void GfxLink::SetPrefSize( const Size& rPrefSize ) 197 { 198 mpImpData->maPrefSize = rPrefSize; 199 mpImpData->mbPrefSizeValid = true; 200 } 201 202 // ------------------------------------------------------------------------ 203 204 bool GfxLink::IsPrefSizeValid() 205 { 206 return mpImpData->mbPrefSizeValid; 207 } 208 209 // ------------------------------------------------------------------------ 210 211 const MapMode& GfxLink::GetPrefMapMode() const 212 { 213 return mpImpData->maPrefMapMode; 214 } 215 216 // ------------------------------------------------------------------------ 217 218 void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode ) 219 { 220 mpImpData->maPrefMapMode = rPrefMapMode; 221 mpImpData->mbPrefMapModeValid = true; 222 } 223 224 // ------------------------------------------------------------------------ 225 226 bool GfxLink::IsPrefMapModeValid() 227 { 228 return mpImpData->mbPrefMapModeValid; 229 } 230 231 // ------------------------------------------------------------------------ 232 233 sal_Bool GfxLink::LoadNative( Graphic& rGraphic ) 234 { 235 sal_Bool bRet = sal_False; 236 237 if( IsNative() && mnBufSize ) 238 { 239 const sal_uInt8* pData = GetData(); 240 241 if( pData ) 242 { 243 SvMemoryStream aMemStm; 244 sal_uLong nCvtType; 245 246 aMemStm.SetBuffer( (char*) pData, mnBufSize, sal_False, mnBufSize ); 247 248 switch( meType ) 249 { 250 case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break; 251 252 // #15508# added BMP type for better exports (reload when swapped - checked, works) 253 case( GFX_LINK_TYPE_NATIVE_BMP ): nCvtType = CVT_BMP; break; 254 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 sal_Size nActReadSize = pIStm->Tell(); 446 if (nActReadSize != mnDataSize) 447 { 448 bError = sal_True; 449 } 450 delete pIStm; 451 452 if( bError ) 453 delete[] pData, pData = NULL; 454 } 455 else 456 pData = NULL; 457 } 458 else 459 pData = NULL; 460 461 return pData; 462 } 463 464 // ------------------------------------------------------------------------ 465 466 void ImpSwap::WriteTo( SvStream& rOStm ) const 467 { 468 sal_uInt8* pData = GetData(); 469 470 if( pData ) 471 { 472 rOStm.Write( pData, mnDataSize ); 473 delete[] pData; 474 } 475 } 476