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_svx.hxx" 26 #include <com/sun/star/embed/XTransactedObject.hpp> 27 #ifndef _COM_SUN_STAR_EMBED_ElementModes_HPP_ 28 #include <com/sun/star/embed/ElementModes.hpp> 29 #endif 30 #include <com/sun/star/beans/XPropertySet.hpp> 31 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32 #include <com/sun/star/lang/XServiceInfo.hpp> 33 #include <com/sun/star/lang/XInitialization.hpp> 34 #include <cppuhelper/compbase4.hxx> 35 36 #include <unotools/ucbstreamhelper.hxx> 37 #include <unotools/streamwrap.hxx> 38 #include <unotools/tempfile.hxx> 39 #include <tools/debug.hxx> 40 #include <vcl/cvtgrf.hxx> 41 #include <vcl/gfxlink.hxx> 42 #include <vcl/metaact.hxx> 43 #include <tools/zcodec.hxx> 44 45 #include "svtools/filter.hxx" 46 #include "svx/xmlgrhlp.hxx" 47 48 #include <algorithm> 49 50 // ----------- 51 // - Defines - 52 // ----------- 53 54 using namespace com::sun::star; 55 using namespace com::sun::star::uno; 56 using namespace com::sun::star::io; 57 58 using ::com::sun::star::lang::XMultiServiceFactory; 59 60 #define XML_GRAPHICSTORAGE_NAME "Pictures" 61 #define XML_PACKAGE_URL_BASE "vnd.sun.star.Package:" 62 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:" 63 64 // --------------------------- 65 // - SvXMLGraphicInputStream - 66 // --------------------------- 67 68 const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf ) 69 { 70 static ByteString aComment( (const sal_Char*)"EPSReplacementGraphic" ); 71 const MetaCommentAction* pComment = NULL; 72 73 if ( ( rMtf.GetActionCount() >= 2 ) 74 && ( rMtf.FirstAction()->GetType() == META_EPS_ACTION ) 75 && ( ((const MetaAction*)rMtf.GetAction( 1 ))->GetType() == META_COMMENT_ACTION ) 76 && ( ((const MetaCommentAction*)rMtf.GetAction( 1 ))->GetComment() == aComment ) ) 77 pComment = (const MetaCommentAction*)rMtf.GetAction( 1 ); 78 79 return pComment; 80 } 81 82 class SvXMLGraphicInputStream : public::cppu::WeakImplHelper1< XInputStream > 83 { 84 private: 85 86 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead); 87 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead); 88 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip); 89 virtual sal_Int32 SAL_CALL available(); 90 virtual void SAL_CALL closeInput(); 91 92 private: 93 94 ::utl::TempFile maTmp; 95 Reference< XInputStream > mxStmWrapper; 96 97 // not available 98 SvXMLGraphicInputStream(); 99 SvXMLGraphicInputStream( const SvXMLGraphicInputStream& ); 100 SvXMLGraphicInputStream& operator==( SvXMLGraphicInputStream& ); 101 102 public: 103 104 SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId ); 105 virtual ~SvXMLGraphicInputStream(); 106 107 sal_Bool Exists() const { return mxStmWrapper.is(); } 108 }; 109 110 // ----------------------------------------------------------------------------- 111 112 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId ) 113 { 114 String aGraphicId( rGraphicId ); 115 GraphicObject aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) ); 116 117 maTmp.EnableKillingFile(); 118 119 if( aGrfObject.GetType() != GRAPHIC_NONE ) 120 { 121 SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), STREAM_WRITE | STREAM_TRUNC ); 122 123 if( pStm ) 124 { 125 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() ); 126 const GfxLink aGfxLink( aGraphic.GetLink() ); 127 sal_Bool bRet = sal_False; 128 129 if( aGfxLink.GetDataSize() && aGfxLink.GetData() ) 130 { 131 pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() ); 132 bRet = ( pStm->GetError() == 0 ); 133 } 134 else 135 { 136 if( aGraphic.GetType() == GRAPHIC_BITMAP ) 137 { 138 GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); 139 String aFormat; 140 141 if( aGraphic.IsAnimated() ) 142 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) ); 143 else 144 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) ); 145 146 bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStm, pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 ); 147 } 148 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE ) 149 { 150 pStm->SetVersion( SOFFICE_FILEFORMAT_8 ); 151 pStm->SetCompressMode( COMPRESSMODE_ZBITMAP ); 152 ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm ); 153 bRet = ( pStm->GetError() == 0 ); 154 } 155 } 156 157 if( bRet ) 158 { 159 pStm->Seek( 0 ); 160 mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, sal_True ); 161 } 162 else 163 delete pStm; 164 } 165 } 166 } 167 168 // ----------------------------------------------------------------------------- 169 170 SvXMLGraphicInputStream::~SvXMLGraphicInputStream() 171 { 172 } 173 174 // ----------------------------------------------------------------------------- 175 176 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) 177 { 178 if( !mxStmWrapper.is() ) 179 throw NotConnectedException(); 180 181 return mxStmWrapper->readBytes( rData, nBytesToRead ); 182 } 183 184 // ----------------------------------------------------------------------------- 185 186 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) 187 { 188 if( !mxStmWrapper.is() ) 189 throw NotConnectedException() ; 190 191 return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead ); 192 } 193 194 // ----------------------------------------------------------------------------- 195 196 void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip ) 197 { 198 if( !mxStmWrapper.is() ) 199 throw NotConnectedException() ; 200 201 mxStmWrapper->skipBytes( nBytesToSkip ); 202 } 203 204 // ----------------------------------------------------------------------------- 205 206 sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() 207 { 208 if( !mxStmWrapper.is() ) 209 throw NotConnectedException() ; 210 211 return mxStmWrapper->available(); 212 } 213 214 // ----------------------------------------------------------------------------- 215 216 void SAL_CALL SvXMLGraphicInputStream::closeInput() 217 { 218 if( !mxStmWrapper.is() ) 219 throw NotConnectedException() ; 220 221 mxStmWrapper->closeInput(); 222 } 223 224 // ---------------------------- 225 // - SvXMLGraphicOutputStream - 226 // ---------------------------- 227 228 class SvXMLGraphicOutputStream : public::cppu::WeakImplHelper1< XOutputStream > 229 { 230 private: 231 232 // XOutputStream 233 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ); 234 virtual void SAL_CALL flush(); 235 virtual void SAL_CALL closeOutput(); 236 237 private: 238 239 ::utl::TempFile* mpTmp; 240 SvStream* mpOStm; 241 Reference< XOutputStream > mxStmWrapper; 242 GraphicObject maGrfObj; 243 sal_Bool mbClosed; 244 245 // not available 246 SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream& ); 247 SvXMLGraphicOutputStream& operator==( SvXMLGraphicOutputStream& ); 248 249 public: 250 251 SvXMLGraphicOutputStream(); 252 virtual ~SvXMLGraphicOutputStream(); 253 254 sal_Bool Exists() const { return mxStmWrapper.is(); } 255 const GraphicObject& GetGraphicObject(); 256 }; 257 258 // ----------------------------------------------------------------------------- 259 260 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() : 261 mpTmp( new ::utl::TempFile ), 262 mbClosed( sal_False ) 263 { 264 mpTmp->EnableKillingFile(); 265 266 mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), STREAM_WRITE | STREAM_TRUNC ); 267 268 if( mpOStm ) 269 mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm ); 270 } 271 272 // ----------------------------------------------------------------------------- 273 274 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream() 275 { 276 delete mpTmp; 277 delete mpOStm; 278 } 279 280 // ----------------------------------------------------------------------------- 281 282 void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData ) 283 { 284 if( !mxStmWrapper.is() ) 285 throw NotConnectedException() ; 286 287 mxStmWrapper->writeBytes( rData ); 288 } 289 290 // ----------------------------------------------------------------------------- 291 292 void SAL_CALL SvXMLGraphicOutputStream::flush() 293 { 294 if( !mxStmWrapper.is() ) 295 throw NotConnectedException() ; 296 297 mxStmWrapper->flush(); 298 } 299 300 // ----------------------------------------------------------------------------- 301 302 void SAL_CALL SvXMLGraphicOutputStream::closeOutput() 303 { 304 if( !mxStmWrapper.is() ) 305 throw NotConnectedException() ; 306 307 mxStmWrapper->closeOutput(); 308 mxStmWrapper = Reference< XOutputStream >(); 309 310 mbClosed = sal_True; 311 } 312 313 // ------------------------------------------------------------------------------ 314 315 const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject() 316 { 317 if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm ) 318 { 319 Graphic aGraphic; 320 321 mpOStm->Seek( 0 ); 322 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW; 323 sal_uInt16 pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW; 324 GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *mpOStm ,nFormat,&pDeterminedFormat ); 325 326 if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW) 327 { 328 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format 329 //unzip them and try again 330 331 sal_uInt8 sFirstBytes[ 2 ]; 332 333 mpOStm->Seek( STREAM_SEEK_TO_END ); 334 sal_uIntPtr nStreamLen = mpOStm->Tell(); 335 mpOStm->Seek( 0 ); 336 337 if ( !nStreamLen ) 338 { 339 SvLockBytes* pLockBytes = mpOStm->GetLockBytes(); 340 if ( pLockBytes ) 341 pLockBytes->SetSynchronMode( sal_True ); 342 343 mpOStm->Seek( STREAM_SEEK_TO_END ); 344 nStreamLen = mpOStm->Tell(); 345 mpOStm->Seek( 0 ); 346 } 347 if( nStreamLen >= 2 ) 348 { 349 //read two byte 350 mpOStm->Read( sFirstBytes, 2 ); 351 352 if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b ) 353 { 354 SvMemoryStream* pDest = new SvMemoryStream; 355 ZCodec aZCodec( 0x8000, 0x8000 ); 356 aZCodec.BeginCompression(ZCODEC_GZ_LIB); 357 mpOStm->Seek( 0 ); 358 aZCodec.Decompress( *mpOStm, *pDest ); 359 360 if (aZCodec.EndCompression() && pDest ) 361 { 362 pDest->Seek( STREAM_SEEK_TO_END ); 363 sal_uIntPtr nStreamLen_ = pDest->Tell(); 364 if (nStreamLen_) 365 { 366 pDest->Seek(0L); 367 GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat ); 368 } 369 } 370 delete pDest; 371 } 372 } 373 } 374 375 maGrfObj = aGraphic; 376 if( maGrfObj.GetType() != GRAPHIC_NONE ) 377 { 378 delete mpOStm, mpOStm = NULL; 379 delete mpTmp, mpTmp = NULL; 380 } 381 } 382 383 return maGrfObj; 384 } 385 386 // ---------------------- 387 // - SvXMLGraphicHelper - 388 // ---------------------- 389 390 SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode ) : 391 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver, 392 ::com::sun::star::document::XBinaryStreamResolver >( maMutex ) 393 { 394 Init( NULL, eCreateMode, sal_False ); 395 } 396 397 SvXMLGraphicHelper::SvXMLGraphicHelper() : 398 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver, 399 ::com::sun::star::document::XBinaryStreamResolver >( maMutex ) 400 { 401 } 402 403 // ----------------------------------------------------------------------------- 404 405 SvXMLGraphicHelper::~SvXMLGraphicHelper() 406 { 407 } 408 409 // ----------------------------------------------------------------------------- 410 411 void SAL_CALL SvXMLGraphicHelper::disposing() 412 { 413 } 414 415 // ----------------------------------------------------------------------------- 416 417 sal_Bool SvXMLGraphicHelper::ImplGetStreamNames( const ::rtl::OUString& rURLStr, 418 ::rtl::OUString& rPictureStorageName, 419 ::rtl::OUString& rPictureStreamName ) 420 { 421 String aURLStr( rURLStr ); 422 sal_Bool bRet = sal_False; 423 424 if( aURLStr.Len() ) 425 { 426 aURLStr = aURLStr.GetToken( aURLStr.GetTokenCount( ':' ) - 1, ':' ); 427 const sal_uInt32 nTokenCount = aURLStr.GetTokenCount( '/' ); 428 429 if( 1 == nTokenCount ) 430 { 431 rPictureStorageName = String( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICSTORAGE_NAME ) ); 432 rPictureStreamName = aURLStr; 433 bRet = sal_True; 434 } 435 else if( 2 == nTokenCount ) 436 { 437 rPictureStorageName = aURLStr.GetToken( 0, '/' ); 438 439 DBG_ASSERT( rPictureStorageName.getLength() && 440 rPictureStorageName.getStr()[ 0 ] != '#', 441 "invalid relative URL" ); 442 443 rPictureStreamName = aURLStr.GetToken( 1, '/' ); 444 bRet = sal_True; 445 } 446 else 447 { 448 DBG_ERROR( "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme" ); 449 } 450 } 451 452 return bRet; 453 } 454 455 // ----------------------------------------------------------------------------- 456 457 uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const ::rtl::OUString& rStorageName ) 458 { 459 uno::Reference < embed::XStorage > xRetStorage; 460 if( mxRootStorage.is() ) 461 { 462 try 463 { 464 xRetStorage = mxRootStorage->openStorageElement( 465 maCurStorageName = rStorageName, 466 ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) 467 ? embed::ElementModes::READWRITE 468 : embed::ElementModes::READ ); 469 } 470 catch ( uno::Exception& ) 471 { 472 } 473 //#i43196# try again to open the storage element - this time readonly 474 if(!xRetStorage.is()) 475 { 476 try 477 { 478 xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ ); 479 } 480 catch ( uno::Exception& ) 481 { 482 } 483 } 484 } 485 486 return xRetStorage; 487 } 488 489 // ----------------------------------------------------------------------------- 490 491 SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const ::rtl::OUString& rPictureStorageName, 492 const ::rtl::OUString& rPictureStreamName, 493 sal_Bool bTruncate ) 494 { 495 SvxGraphicHelperStream_Impl aRet; 496 aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName ); 497 498 if( aRet.xStorage.is() ) 499 { 500 sal_Int32 nMode = embed::ElementModes::READ; 501 if ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) 502 { 503 nMode = embed::ElementModes::READWRITE; 504 if ( bTruncate ) 505 nMode |= embed::ElementModes::TRUNCATE; 506 } 507 508 aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode ); 509 if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) ) 510 { 511 //REMOVE ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("Encrypted") ); 512 ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") ); 513 uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY ); 514 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) ); 515 } 516 } 517 518 return aRet; 519 } 520 521 // ----------------------------------------------------------------------------- 522 523 String SvXMLGraphicHelper::ImplGetGraphicMimeType( const String& rFileName ) const 524 { 525 struct XMLGraphicMimeTypeMapper 526 { 527 const char* pExt; 528 const char* pMimeType; 529 }; 530 531 static XMLGraphicMimeTypeMapper aMapper[] = 532 { 533 { "gif", "image/gif" }, 534 { "png", "image/png" }, 535 { "jpg", "image/jpeg" }, 536 { "tif", "image/tiff" }, 537 { "svg", "image/svg+xml" } 538 }; 539 540 String aMimeType; 541 542 if( ( rFileName.Len() >= 4 ) && ( rFileName.GetChar( rFileName.Len() - 4 ) == '.' ) ) 543 { 544 const ByteString aExt( rFileName.Copy( rFileName.Len() - 3 ), RTL_TEXTENCODING_ASCII_US ); 545 546 for( long i = 0, nCount = sizeof( aMapper ) / sizeof( aMapper[ 0 ] ); ( i < nCount ) && !aMimeType.Len(); i++ ) 547 if( aExt == aMapper[ i ].pExt ) 548 aMimeType = String( aMapper[ i ].pMimeType, RTL_TEXTENCODING_ASCII_US ); 549 } 550 551 return aMimeType; 552 } 553 554 // ----------------------------------------------------------------------------- 555 556 Graphic SvXMLGraphicHelper::ImplReadGraphic( const ::rtl::OUString& rPictureStorageName, 557 const ::rtl::OUString& rPictureStreamName ) 558 { 559 Graphic aGraphic; 560 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) ); 561 if( aStream.xStream.is() ) 562 { 563 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream ); 564 GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pStream ); 565 delete pStream; 566 } 567 568 return aGraphic; 569 } 570 571 // ----------------------------------------------------------------------------- 572 573 sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString& rPictureStorageName, 574 const ::rtl::OUString& rPictureStreamName, 575 const ::rtl::OUString& rGraphicId ) 576 { 577 String aGraphicId( rGraphicId ); 578 GraphicObject aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) ); 579 sal_Bool bRet = sal_False; 580 581 if( aGrfObject.GetType() != GRAPHIC_NONE ) 582 { 583 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) ); 584 if( aStream.xStream.is() ) 585 { 586 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() ); 587 const GfxLink aGfxLink( aGraphic.GetLink() ); 588 const ::rtl::OUString aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) ); 589 uno::Any aAny; 590 uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY ); 591 592 // set stream properties (MediaType/Compression) 593 if( aMimeType.getLength() ) 594 { 595 aAny <<= aMimeType; 596 xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), aAny ); 597 } 598 599 const sal_Bool bCompressed = ( ( 0 == aMimeType.getLength() ) || ( aMimeType == ::rtl::OUString::createFromAscii( "image/tiff" ) ) ); 600 aAny <<= bCompressed; 601 xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), aAny ); 602 603 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream ); 604 if( aGfxLink.GetDataSize() && aGfxLink.GetData() ) 605 pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() ); 606 else 607 { 608 if( aGraphic.GetType() == GRAPHIC_BITMAP ) 609 { 610 GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); 611 String aFormat; 612 613 if( aGraphic.IsAnimated() ) 614 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) ); 615 else 616 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) ); 617 618 bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStream, 619 pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 ); 620 } 621 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE ) 622 { 623 pStream->SetVersion( SOFFICE_FILEFORMAT_8 ); 624 pStream->SetCompressMode( COMPRESSMODE_ZBITMAP ); 625 626 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm 627 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() ); 628 const MetaCommentAction* pComment = ImplCheckForEPS( rMtf ); 629 if ( pComment ) 630 { 631 sal_uInt32 nSize = pComment->GetDataSize(); 632 const sal_uInt8* pData = pComment->GetData(); 633 if ( nSize && pData ) 634 pStream->Write( pData, nSize ); 635 636 const MetaEPSAction* pAct = ( (const MetaEPSAction*)rMtf.FirstAction() ); 637 const GfxLink& rLink = pAct->GetLink(); 638 639 pStream->Write( rLink.GetData(), rLink.GetDataSize() ); 640 } 641 else 642 rMtf.Write( *pStream ); 643 644 bRet = ( pStream->GetError() == 0 ); 645 } 646 } 647 uno::Reference < embed::XTransactedObject > xStorage( 648 aStream.xStorage, uno::UNO_QUERY); 649 delete pStream; 650 aStream.xStream->getOutputStream()->closeOutput(); 651 if( xStorage.is() ) 652 xStorage->commit(); 653 } 654 } 655 656 return bRet; 657 } 658 659 // ----------------------------------------------------------------------------- 660 661 void SvXMLGraphicHelper::ImplInsertGraphicURL( const ::rtl::OUString& rURLStr, sal_uInt32 nInsertPos, rtl::OUString& rRequestedFileName ) 662 { 663 rtl::OUString aURLString( rURLStr ); 664 ::rtl::OUString aPictureStorageName, aPictureStreamName; 665 if( ( maURLSet.find( aURLString ) != maURLSet.end() ) ) 666 { 667 URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() ); 668 while( aIter != aEnd ) 669 { 670 if( aURLString == (*aIter).first ) 671 { 672 maGrfURLs[ nInsertPos ].second = (*aIter).second; 673 aIter = aEnd; 674 } 675 else 676 aIter++; 677 } 678 } 679 else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) ) 680 { 681 URLPair& rURLPair = maGrfURLs[ nInsertPos ]; 682 683 if( GRAPHICHELPER_MODE_READ == meCreateMode ) 684 { 685 const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) ); 686 687 if( aObj.GetType() != GRAPHIC_NONE ) 688 { 689 const static ::rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICOBJECT_URL_BASE ) ); 690 691 maGrfObjs.push_back( aObj ); 692 rURLPair.second = aBaseURL; 693 rURLPair.second += String( aObj.GetUniqueID().GetBuffer(), RTL_TEXTENCODING_ASCII_US ); 694 } 695 else 696 rURLPair.second = String(); 697 } 698 else 699 { 700 const String aGraphicObjectId( aPictureStreamName ); 701 const ByteString aAsciiObjectID( aGraphicObjectId, RTL_TEXTENCODING_ASCII_US ); 702 const GraphicObject aGrfObject( aAsciiObjectID ); 703 if( aGrfObject.GetType() != GRAPHIC_NONE ) 704 { 705 String aStreamName( aGraphicObjectId ); 706 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() ); 707 const GfxLink aGfxLink( aGraphic.GetLink() ); 708 String aExtension; 709 710 if( aGfxLink.GetDataSize() ) 711 { 712 switch( aGfxLink.GetType() ) 713 { 714 case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) ); break; 715 case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) ); break; 716 717 // #15508# added BMP type for better exports (checked, works) 718 case( GFX_LINK_TYPE_NATIVE_BMP ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".bmp" ) ); break; 719 720 case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".jpg" ) ); break; 721 case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ); break; 722 case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".tif" ) ); break; 723 case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".wmf" ) ); break; 724 case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".met" ) ); break; 725 case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".pct" ) ); break; 726 case( GFX_LINK_TYPE_NATIVE_SVG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".svg" ) ); break; 727 728 default: 729 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".grf" ) ); 730 break; 731 } 732 } 733 else 734 { 735 if( aGrfObject.GetType() == GRAPHIC_BITMAP ) 736 { 737 if( aGrfObject.IsAnimated() ) 738 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) ); 739 else 740 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ); 741 } 742 else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE ) 743 { 744 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm 745 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() ); 746 if ( ImplCheckForEPS( rMtf ) ) 747 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) ); 748 else 749 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".svm" ) ); 750 } 751 } 752 753 rtl::OUString aURLEntry; 754 const String sPictures( RTL_CONSTASCII_USTRINGPARAM( "Pictures/" ) ); 755 756 if ( rRequestedFileName.getLength() ) 757 { 758 aURLEntry = sPictures; 759 aURLEntry += rRequestedFileName; 760 aURLEntry += aExtension; 761 762 URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() ); 763 while( aIter != aEnd ) 764 { 765 if( aURLEntry == (*aIter).second ) 766 break; 767 aIter++; 768 } 769 if ( aIter == aEnd ) 770 aStreamName = rRequestedFileName; 771 } 772 773 aStreamName += aExtension; 774 775 if( mbDirect && aStreamName.Len() ) 776 ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId ); 777 778 rURLPair.second = sPictures; 779 rURLPair.second += aStreamName; 780 } 781 #if OSL_DEBUG_LEVEL > 0 782 else 783 { 784 ByteString sMessage = "graphic object with ID '"; 785 sMessage += aAsciiObjectID; 786 sMessage += "' has an unknown type"; 787 OSL_ENSURE( false, sMessage.GetBuffer() ); 788 } 789 #endif 790 } 791 792 maURLSet.insert( aURLString ); 793 } 794 } 795 796 // ----------------------------------------------------------------------------- 797 798 void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage, 799 SvXMLGraphicHelperMode eCreateMode, 800 sal_Bool bDirect ) 801 { 802 mxRootStorage = rXMLStorage; 803 meCreateMode = eCreateMode; 804 mbDirect = ( ( GRAPHICHELPER_MODE_READ == meCreateMode ) ? bDirect : sal_True ); 805 } 806 807 // ----------------------------------------------------------------------------- 808 809 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage, 810 SvXMLGraphicHelperMode eCreateMode, 811 sal_Bool bDirect ) 812 { 813 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper; 814 815 pThis->acquire(); 816 pThis->Init( rXMLStorage, eCreateMode, bDirect ); 817 818 return pThis; 819 } 820 821 // ----------------------------------------------------------------------------- 822 823 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode ) 824 { 825 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper; 826 827 pThis->acquire(); 828 pThis->Init( NULL, eCreateMode, sal_False ); 829 830 return pThis; 831 } 832 833 // ----------------------------------------------------------------------------- 834 835 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper ) 836 { 837 if( pSvXMLGraphicHelper ) 838 { 839 pSvXMLGraphicHelper->dispose(); 840 pSvXMLGraphicHelper->release(); 841 } 842 } 843 844 // ----------------------------------------------------------------------------- 845 846 // XGraphicObjectResolver 847 ::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const ::rtl::OUString& rURL ) 848 { 849 ::osl::MutexGuard aGuard( maMutex ); 850 const sal_Int32 nIndex = maGrfURLs.size(); 851 852 rtl::OUString aURL( rURL ); 853 rtl::OUString aUserData; 854 rtl::OUString aRequestedFileName; 855 856 sal_Int32 nUser = rURL.indexOf( '?', 0 ); 857 if ( nUser >= 0 ) 858 { 859 aURL = rtl::OUString( rURL.copy( 0, nUser ) ); 860 nUser++; 861 aUserData = rURL.copy( nUser, rURL.getLength() - nUser ); 862 } 863 if ( aUserData.getLength() ) 864 { 865 sal_Int32 nIndex2 = 0; 866 do 867 { 868 rtl::OUString aToken = aUserData.getToken( 0, ';', nIndex2 ); 869 sal_Int32 n = aToken.indexOf( '=' ); 870 if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) ) 871 { 872 rtl::OUString aParam( aToken.copy( 0, n ) ); 873 rtl::OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) ); 874 875 const rtl::OUString sRequestedName( RTL_CONSTASCII_USTRINGPARAM("requestedName") ); 876 if ( aParam.match( sRequestedName ) ) 877 aRequestedFileName = aValue; 878 } 879 } 880 while ( nIndex2 >= 0 ); 881 } 882 883 maGrfURLs.push_back( ::std::make_pair( aURL, ::rtl::OUString() ) ); 884 ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName ); 885 886 return maGrfURLs[ nIndex ].second; 887 } 888 889 // ----------------------------------------------------------------------------- 890 891 // XBinaryStreamResolver 892 Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const ::rtl::OUString& rURL ) 893 { 894 Reference< XInputStream > xRet; 895 ::rtl::OUString aPictureStorageName, aGraphicId; 896 897 898 if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) && 899 ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) ) 900 { 901 SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId ); 902 903 if( pInputStream->Exists() ) 904 xRet = pInputStream; 905 else 906 delete pInputStream; 907 } 908 909 return xRet; 910 } 911 912 // ----------------------------------------------------------------------------- 913 914 Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream() 915 { 916 Reference< XOutputStream > xRet; 917 918 if( GRAPHICHELPER_MODE_READ == meCreateMode ) 919 { 920 SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream; 921 922 if( pOutputStream->Exists() ) 923 maGrfStms.push_back( xRet = pOutputStream ); 924 else 925 delete pOutputStream; 926 } 927 928 return xRet; 929 } 930 931 // ----------------------------------------------------------------------------- 932 933 ::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream ) 934 { 935 ::rtl::OUString aRet; 936 937 if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() ) 938 { 939 if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() ) 940 { 941 SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() ); 942 943 if( pOStm ) 944 { 945 const GraphicObject& rGrfObj = pOStm->GetGraphicObject(); 946 const ::rtl::OUString aId( ::rtl::OUString::createFromAscii( rGrfObj.GetUniqueID().GetBuffer() ) ); 947 948 if( aId.getLength() ) 949 { 950 aRet = ::rtl::OUString::createFromAscii( XML_GRAPHICOBJECT_URL_BASE ); 951 aRet += aId; 952 } 953 } 954 } 955 } 956 957 return aRet; 958 } 959 960 961 // -------------------------------------------------------------------------------- 962 963 // for instantiation via service manager 964 namespace svx 965 { 966 967 namespace impl 968 { 969 typedef ::cppu::WeakComponentImplHelper4< 970 lang::XInitialization, 971 document::XGraphicObjectResolver, 972 document::XBinaryStreamResolver, 973 lang::XServiceInfo > 974 SvXMLGraphicImportExportHelper_Base; 975 class MutexContainer 976 { 977 public: 978 virtual ~MutexContainer(); 979 980 protected: 981 mutable ::osl::Mutex m_aMutex; 982 }; 983 MutexContainer::~MutexContainer() 984 {} 985 } // namespace impl 986 987 class SvXMLGraphicImportExportHelper : 988 public impl::MutexContainer, 989 public impl::SvXMLGraphicImportExportHelper_Base 990 { 991 public: 992 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ); 993 994 protected: 995 // is called from WeakComponentImplHelper when XComponent::dispose() was 996 // called from outside 997 virtual void SAL_CALL disposing(); 998 999 // ____ XInitialization ____ 1000 // one argument is allowed, which is the XStorage 1001 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ); 1002 1003 // ____ XGraphicObjectResolver ____ 1004 virtual ::rtl::OUString SAL_CALL resolveGraphicObjectURL( const ::rtl::OUString& aURL ); 1005 1006 // ____ XBinaryStreamResolver ____ 1007 virtual Reference< io::XInputStream > SAL_CALL getInputStream( const ::rtl::OUString& aURL ); 1008 virtual Reference< io::XOutputStream > SAL_CALL createOutputStream(); 1009 virtual ::rtl::OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream ); 1010 1011 // ____ XServiceInfo ____ 1012 virtual ::rtl::OUString SAL_CALL getImplementationName(); 1013 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ); 1014 virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(); 1015 1016 private: 1017 SvXMLGraphicHelperMode m_eGraphicHelperMode; 1018 Reference< XGraphicObjectResolver > m_xGraphicObjectResolver; 1019 Reference< XBinaryStreamResolver > m_xBinaryStreamResolver; 1020 }; 1021 1022 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) : 1023 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ), 1024 m_eGraphicHelperMode( eMode ) 1025 {} 1026 1027 void SAL_CALL SvXMLGraphicImportExportHelper::disposing() 1028 { 1029 Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY ); 1030 OSL_ASSERT( xComp.is()); 1031 if( xComp.is()) 1032 xComp->dispose(); 1033 // m_xBinaryStreamResolver is a reference to the same object => don't call 1034 // dispose() again 1035 } 1036 1037 // ____ XInitialization ____ 1038 void SAL_CALL SvXMLGraphicImportExportHelper::initialize( 1039 const Sequence< Any >& aArguments ) 1040 { 1041 Reference< embed::XStorage > xStorage; 1042 if( aArguments.getLength() > 0 ) 1043 aArguments[0] >>= xStorage; 1044 1045 SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode )); 1046 m_xGraphicObjectResolver.set( pHelper ); 1047 m_xBinaryStreamResolver.set( pHelper ); 1048 // SvXMLGraphicHelper::Create calls acquire. Since we have two references 1049 // now it is safe (and necessary) to undo this acquire 1050 pHelper->release(); 1051 } 1052 1053 // ____ XGraphicObjectResolver ____ 1054 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const ::rtl::OUString& aURL ) 1055 { 1056 return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL ); 1057 } 1058 1059 1060 // ____ XBinaryStreamResolver ____ 1061 Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const ::rtl::OUString& aURL ) 1062 { 1063 return m_xBinaryStreamResolver->getInputStream( aURL ); 1064 } 1065 Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream() 1066 { 1067 return m_xBinaryStreamResolver->createOutputStream(); 1068 } 1069 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream ) 1070 { 1071 return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream ); 1072 } 1073 1074 // ____ XServiceInfo ____ 1075 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName() 1076 { 1077 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ ) 1078 return SvXMLGraphicImportHelper_getImplementationName(); 1079 return SvXMLGraphicExportHelper_getImplementationName(); 1080 } 1081 ::sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const ::rtl::OUString& ServiceName ) 1082 { 1083 Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames()); 1084 const ::rtl::OUString * pBegin = aServiceNames.getConstArray(); 1085 const ::rtl::OUString * pEnd = pBegin + aServiceNames.getLength(); 1086 return (::std::find( pBegin, pEnd, ServiceName ) != pEnd); 1087 } 1088 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames() 1089 { 1090 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ ) 1091 return SvXMLGraphicImportHelper_getSupportedServiceNames(); 1092 return SvXMLGraphicExportHelper_getSupportedServiceNames(); 1093 } 1094 1095 // import 1096 Reference< XInterface > SAL_CALL SvXMLGraphicImportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ ) 1097 { 1098 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ )); 1099 } 1100 ::rtl::OUString SAL_CALL SvXMLGraphicImportHelper_getImplementationName() 1101 throw() 1102 { 1103 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicImportHelper" )); 1104 } 1105 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportHelper_getSupportedServiceNames() 1106 throw() 1107 { 1108 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service 1109 Sequence< ::rtl::OUString > aSupportedServiceNames( 2 ); 1110 aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) ); 1111 aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) ); 1112 return aSupportedServiceNames; 1113 } 1114 1115 // export 1116 Reference< XInterface > SAL_CALL SvXMLGraphicExportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ ) 1117 { 1118 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE )); 1119 } 1120 ::rtl::OUString SAL_CALL SvXMLGraphicExportHelper_getImplementationName() 1121 throw() 1122 { 1123 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicExportHelper" )); 1124 } 1125 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicExportHelper_getSupportedServiceNames() 1126 throw() 1127 { 1128 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service 1129 Sequence< ::rtl::OUString > aSupportedServiceNames( 2 ); 1130 aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) ); 1131 aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) ); 1132 return aSupportedServiceNames; 1133 } 1134 1135 } // namespace svx 1136