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 case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break; 252 case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break; 253 case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break; 254 case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break; 255 case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break; 256 case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break; 257 case( GFX_LINK_TYPE_NATIVE_SVG ): nCvtType = CVT_SVG; break; 258 259 default: nCvtType = CVT_UNKNOWN; break; 260 } 261 262 if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) ) 263 bRet = sal_True; 264 } 265 } 266 267 return bRet; 268 } 269 270 // ------------------------------------------------------------------------ 271 272 void GfxLink::SwapOut() 273 { 274 if( !IsSwappedOut() && mpBuf ) 275 { 276 mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize ); 277 278 if( !mpSwap->IsSwapped() ) 279 { 280 delete mpSwap; 281 mpSwap = NULL; 282 } 283 else 284 { 285 if( !( --mpBuf->mnRefCount ) ) 286 delete mpBuf; 287 288 mpBuf = NULL; 289 } 290 } 291 } 292 293 // ------------------------------------------------------------------------ 294 295 void GfxLink::SwapIn() 296 { 297 if( IsSwappedOut() ) 298 { 299 mpBuf = new ImpBuffer( mpSwap->GetData() ); 300 301 if( !( --mpSwap->mnRefCount ) ) 302 delete mpSwap; 303 304 mpSwap = NULL; 305 } 306 } 307 308 // ------------------------------------------------------------------------ 309 310 sal_Bool GfxLink::ExportNative( SvStream& rOStream ) const 311 { 312 if( GetDataSize() ) 313 { 314 if( IsSwappedOut() ) 315 mpSwap->WriteTo( rOStream ); 316 else if( GetData() ) 317 rOStream.Write( GetData(), GetDataSize() ); 318 } 319 320 return ( rOStream.GetError() == ERRCODE_NONE ); 321 } 322 323 // ------------------------------------------------------------------------ 324 325 SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink ) 326 { 327 VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 2 ); 328 329 // Version 1 330 rOStream << (sal_uInt16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId(); 331 332 // Version 2 333 rOStream << rGfxLink.GetPrefSize() << rGfxLink.GetPrefMapMode(); 334 335 delete pCompat; 336 337 if( rGfxLink.GetDataSize() ) 338 { 339 if( rGfxLink.IsSwappedOut() ) 340 rGfxLink.mpSwap->WriteTo( rOStream ); 341 else if( rGfxLink.GetData() ) 342 rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() ); 343 } 344 345 return rOStream; 346 } 347 348 // ------------------------------------------------------------------------ 349 350 SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink) 351 { 352 Size aSize; 353 MapMode aMapMode; 354 sal_uInt32 nSize; 355 sal_uInt32 nUserId; 356 sal_uInt16 nType; 357 sal_uInt8* pBuf; 358 bool bMapAndSizeValid( false ); 359 VersionCompat* pCompat = new VersionCompat( rIStream, STREAM_READ ); 360 361 // Version 1 362 rIStream >> nType >> nSize >> nUserId; 363 364 if( pCompat->GetVersion() >= 2 ) 365 { 366 rIStream >> aSize >> aMapMode; 367 bMapAndSizeValid = true; 368 } 369 370 delete pCompat; 371 372 pBuf = new sal_uInt8[ nSize ]; 373 rIStream.Read( pBuf, nSize ); 374 375 rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, sal_True ); 376 rGfxLink.SetUserId( nUserId ); 377 378 if( bMapAndSizeValid ) 379 { 380 rGfxLink.SetPrefSize( aSize ); 381 rGfxLink.SetPrefMapMode( aMapMode ); 382 } 383 384 return rIStream; 385 } 386 387 // ----------- 388 // - ImpSwap - 389 // ----------- 390 391 ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) : 392 mnDataSize( nDataSize ), 393 mnRefCount( 1UL ) 394 { 395 if( pData && mnDataSize ) 396 { 397 ::utl::TempFile aTempFile; 398 399 maURL = aTempFile.GetURL(); 400 if( maURL.getLength() ) 401 { 402 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 403 if( pOStm ) 404 { 405 pOStm->Write( pData, mnDataSize ); 406 sal_Bool bError = ( ERRCODE_NONE != pOStm->GetError() ); 407 delete pOStm; 408 409 if( bError ) 410 { 411 osl_removeFile( maURL.pData ); 412 maURL = String(); 413 } 414 } 415 } 416 } 417 } 418 419 // ------------------------------------------------------------------------ 420 421 ImpSwap::~ImpSwap() 422 { 423 if( IsSwapped() ) 424 osl_removeFile( maURL.pData ); 425 } 426 427 // ------------------------------------------------------------------------ 428 429 sal_uInt8* ImpSwap::GetData() const 430 { 431 sal_uInt8* pData; 432 433 if( IsSwapped() ) 434 { 435 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE ); 436 if( pIStm ) 437 { 438 pData = new sal_uInt8[ mnDataSize ]; 439 pIStm->Read( pData, mnDataSize ); 440 sal_Bool bError = ( ERRCODE_NONE != pIStm->GetError() ); 441 sal_Size nActReadSize = pIStm->Tell(); 442 if (nActReadSize != mnDataSize) 443 { 444 bError = sal_True; 445 } 446 delete pIStm; 447 448 if( bError ) 449 delete[] pData, pData = NULL; 450 } 451 else 452 pData = NULL; 453 } 454 else 455 pData = NULL; 456 457 return pData; 458 } 459 460 // ------------------------------------------------------------------------ 461 462 void ImpSwap::WriteTo( SvStream& rOStm ) const 463 { 464 sal_uInt8* pData = GetData(); 465 466 if( pData ) 467 { 468 rOStm.Write( pData, mnDataSize ); 469 delete[] pData; 470 } 471 } 472