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_svtools.hxx" 30 31 #include <rtl/uuid.h> 32 #include <vos/mutex.hxx> 33 #include <vcl/svapp.hxx> 34 #include <vcl/image.hxx> 35 #include <vcl/metaact.hxx> 36 #include <vcl/msgbox.hxx> 37 #include <vcl/imagerepository.hxx> 38 #include <tools/rcid.h> 39 #include <tools/resid.hxx> 40 #include <tools/resmgr.hxx> 41 #include <unotools/ucbstreamhelper.hxx> 42 #include <svtools/filter.hxx> 43 #include <svl/solar.hrc> 44 #include <vcl/salbtype.hxx> 45 #include <vcl/virdev.hxx> 46 #include <com/sun/star/io/XStream.hpp> 47 #include <com/sun/star/text/GraphicCrop.hpp> 48 49 #include "descriptor.hxx" 50 #include "graphic.hxx" 51 #include <svtools/grfmgr.hxx> 52 #include "provider.hxx" 53 54 using namespace com::sun::star; 55 56 namespace unographic { 57 58 #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" 59 60 // ------------------- 61 // - GraphicProvider - 62 // ------------------- 63 64 uno::Reference< uno::XInterface > SAL_CALL GraphicProvider_CreateInstance( const uno::Reference< lang::XMultiServiceFactory >& ) 65 { 66 return SAL_STATIC_CAST( ::cppu::OWeakObject*, new GraphicProvider ); 67 } 68 69 GraphicProvider::GraphicProvider() 70 { 71 } 72 73 // ------------------------------------------------------------------------------ 74 75 GraphicProvider::~GraphicProvider() 76 { 77 } 78 79 // ------------------------------------------------------------------------------ 80 81 ::rtl::OUString GraphicProvider::getImplementationName_Static() 82 throw() 83 { 84 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.graphic.GraphicProvider" ) ); 85 } 86 87 // ------------------------------------------------------------------------------ 88 89 uno::Sequence< ::rtl::OUString > GraphicProvider::getSupportedServiceNames_Static() 90 throw() 91 { 92 uno::Sequence< ::rtl::OUString > aSeq( 1 ); 93 94 aSeq.getArray()[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) ); 95 96 return aSeq; 97 } 98 99 // ------------------------------------------------------------------------------ 100 101 ::rtl::OUString SAL_CALL GraphicProvider::getImplementationName() 102 throw( uno::RuntimeException ) 103 { 104 return getImplementationName_Static(); 105 } 106 107 // ------------------------------------------------------------------------------ 108 109 sal_Bool SAL_CALL GraphicProvider::supportsService( const ::rtl::OUString& ServiceName ) 110 throw( uno::RuntimeException ) 111 { 112 uno::Sequence< ::rtl::OUString > aSNL( getSupportedServiceNames() ); 113 const ::rtl::OUString* pArray = aSNL.getConstArray(); 114 115 for( int i = 0; i < aSNL.getLength(); i++ ) 116 if( pArray[i] == ServiceName ) 117 return true; 118 119 return false; 120 } 121 122 // ------------------------------------------------------------------------------ 123 124 uno::Sequence< ::rtl::OUString > SAL_CALL GraphicProvider::getSupportedServiceNames() 125 throw( uno::RuntimeException ) 126 { 127 return getSupportedServiceNames_Static(); 128 } 129 130 // ------------------------------------------------------------------------------ 131 132 uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes() 133 throw(uno::RuntimeException) 134 { 135 uno::Sequence< uno::Type > aTypes( 3 ); 136 uno::Type* pTypes = aTypes.getArray(); 137 138 *pTypes++ = ::getCppuType((const uno::Reference< lang::XServiceInfo>*)0); 139 *pTypes++ = ::getCppuType((const uno::Reference< lang::XTypeProvider>*)0); 140 *pTypes++ = ::getCppuType((const uno::Reference< graphic::XGraphicProvider>*)0); 141 142 return aTypes; 143 } 144 145 // ------------------------------------------------------------------------------ 146 147 uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId() 148 throw(uno::RuntimeException) 149 { 150 vos::OGuard aGuard( Application::GetSolarMutex() ); 151 static uno::Sequence< sal_Int8 > aId; 152 153 if( aId.getLength() == 0 ) 154 { 155 aId.realloc( 16 ); 156 rtl_createUuid( reinterpret_cast< sal_uInt8* >( aId.getArray() ), 0, sal_True ); 157 } 158 159 return aId; 160 } 161 162 // ------------------------------------------------------------------------------ 163 164 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadGraphicObject( const ::rtl::OUString& rResourceURL ) const 165 { 166 uno::Reference< ::graphic::XGraphic > xRet; 167 if( rResourceURL.compareToAscii( UNO_NAME_GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( UNO_NAME_GRAPHOBJ_URLPREFIX ) ) == 0 ) 168 { 169 // graphic manager url 170 String aTmpStr( rResourceURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 ) ); 171 ByteString aUniqueID( aTmpStr, RTL_TEXTENCODING_UTF8 ); 172 GraphicObject aGrafObj( aUniqueID ); 173 // I don't call aGrafObj.GetXGraphic because it will call us back 174 // into implLoadMemory ( with "private:memorygraphic" test ) 175 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; 176 pUnoGraphic->init( aGrafObj.GetGraphic() ); 177 xRet = pUnoGraphic; 178 } 179 return xRet; 180 } 181 182 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const ::rtl::OUString& rResourceURL ) const 183 { 184 uno::Reference< ::graphic::XGraphic > xRet; 185 sal_Int32 nIndex = 0; 186 187 if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:memorygraphic" ) ) ) 188 { 189 sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64(); 190 191 if( nGraphicAddress ) 192 { 193 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; 194 195 pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) ); 196 xRet = pUnoGraphic; 197 } 198 } 199 200 return xRet; 201 } 202 203 // ------------------------------------------------------------------------------ 204 205 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const ::rtl::OUString& rResourceURL ) const 206 { 207 uno::Reference< ::graphic::XGraphic > xRet; 208 sal_Int32 nIndex = 0; 209 210 if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:graphicrepository" ) ) ) 211 { 212 String sPathName( rResourceURL.copy( nIndex ) ); 213 BitmapEx aBitmap; 214 if ( ::vcl::ImageRepository::loadImage( sPathName, aBitmap, false ) ) 215 { 216 Image aImage( aBitmap ); 217 xRet = aImage.GetXGraphic(); 218 } 219 } 220 return xRet; 221 } 222 223 224 // ------------------------------------------------------------------------------ 225 226 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const ::rtl::OUString& rResourceURL ) const 227 { 228 uno::Reference< ::graphic::XGraphic > xRet; 229 sal_Int32 nIndex = 0; 230 231 if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:standardimage" ) ) ) 232 { 233 rtl::OUString sImageName( rResourceURL.copy( nIndex ) ); 234 if ( sImageName.equalsAscii( "info" ) ) 235 { 236 xRet = InfoBox::GetStandardImage().GetXGraphic(); 237 } 238 else if ( sImageName.equalsAscii( "warning" ) ) 239 { 240 xRet = WarningBox::GetStandardImage().GetXGraphic(); 241 } 242 else if ( sImageName.equalsAscii( "error" ) ) 243 { 244 xRet = ErrorBox::GetStandardImage().GetXGraphic(); 245 } 246 else if ( sImageName.equalsAscii( "query" ) ) 247 { 248 xRet = QueryBox::GetStandardImage().GetXGraphic(); 249 } 250 } 251 return xRet; 252 } 253 254 // ------------------------------------------------------------------------------ 255 256 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm ) const 257 { 258 uno::Reference< ::graphic::XGraphic > xRet; 259 uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() ); 260 uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() ); 261 SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), STREAM_READ ); 262 Bitmap aBmp; 263 aBmpStream >> aBmp; 264 265 BitmapEx aBmpEx; 266 267 if( aMaskSeq.getLength() ) 268 { 269 SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), STREAM_READ ); 270 Bitmap aMask; 271 aMaskStream >> aMask; 272 aBmpEx = BitmapEx( aBmp, aMask ); 273 } 274 else 275 aBmpEx = BitmapEx( aBmp ); 276 277 if( !aBmpEx.IsEmpty() ) 278 { 279 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; 280 281 pUnoGraphic->init( aBmpEx ); 282 xRet = pUnoGraphic; 283 } 284 return xRet; 285 } 286 287 // ------------------------------------------------------------------------------ 288 289 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadResource( const ::rtl::OUString& rResourceURL ) const 290 { 291 uno::Reference< ::graphic::XGraphic > xRet; 292 sal_Int32 nIndex = 0; 293 294 if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:resource" ) ) ) 295 { 296 ByteString aResMgrName( String( rResourceURL.getToken( 0, '/', nIndex ) ), RTL_TEXTENCODING_ASCII_US ); 297 298 ResMgr* pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() ); 299 300 if( pResMgr ) 301 { 302 const ::rtl::OUString aResourceType( rResourceURL.getToken( 0, '/', nIndex ) ); 303 const ResId aResId( rResourceURL.getToken( 0, '/', nIndex ).toInt32(), *pResMgr ); 304 305 if( aResourceType.getLength() ) 306 { 307 BitmapEx aBmpEx; 308 309 if( ( 0 == aResourceType.compareToAscii( "bitmap" ) ) || 310 ( 0 == aResourceType.compareToAscii( "bitmapex" ) ) ) 311 { 312 aResId.SetRT( RSC_BITMAP ); 313 314 if( pResMgr->IsAvailable( aResId ) ) 315 { 316 aBmpEx = BitmapEx( aResId ); 317 } 318 } 319 else if( 0 == aResourceType.compareToAscii( "image" ) ) 320 { 321 aResId.SetRT( RSC_IMAGE ); 322 323 if( pResMgr->IsAvailable( aResId ) ) 324 { 325 const Image aImage( aResId ); 326 aBmpEx = aImage.GetBitmapEx(); 327 } 328 } 329 else if( 0 == aResourceType.compareToAscii( "imagelist" ) ) 330 { 331 aResId.SetRT( RSC_IMAGELIST ); 332 333 if( pResMgr->IsAvailable( aResId ) ) 334 { 335 const ImageList aImageList( aResId ); 336 sal_Int32 nImageId = ( nIndex > -1 ) ? rResourceURL.getToken( 0, '/', nIndex ).toInt32() : 0; 337 338 if( 0 < nImageId ) 339 { 340 const Image aImage( aImageList.GetImage( sal::static_int_cast< sal_uInt16 >(nImageId) ) ); 341 aBmpEx = aImage.GetBitmapEx(); 342 } 343 else 344 { 345 aBmpEx = aImageList.GetAsHorizontalStrip(); 346 } 347 } 348 } 349 350 if( !aBmpEx.IsEmpty() ) 351 { 352 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; 353 354 pUnoGraphic->init( aBmpEx ); 355 xRet = pUnoGraphic; 356 } 357 } 358 359 delete pResMgr; 360 } 361 } 362 363 return xRet; 364 } 365 366 // ------------------------------------------------------------------------------ 367 368 uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties ) 369 throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) 370 { 371 uno::Reference< beans::XPropertySet > xRet; 372 373 ::rtl::OUString aURL; 374 uno::Reference< io::XInputStream > xIStm; 375 uno::Reference< awt::XBitmap >xBtm; 376 377 for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !xRet.is(); ++i ) 378 { 379 const ::rtl::OUString aName( rMediaProperties[ i ].Name ); 380 const uno::Any aValue( rMediaProperties[ i ].Value ); 381 382 if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) ) 383 { 384 aValue >>= aURL; 385 } 386 else if( COMPARE_EQUAL == aName.compareToAscii( "InputStream" ) ) 387 { 388 aValue >>= xIStm; 389 } 390 else if( COMPARE_EQUAL == aName.compareToAscii( "Bitmap" ) ) 391 { 392 aValue >>= xBtm; 393 } 394 } 395 396 if( xIStm.is() ) 397 { 398 GraphicDescriptor* pDescriptor = new GraphicDescriptor; 399 pDescriptor->init( xIStm, aURL ); 400 xRet = pDescriptor; 401 } 402 else if( aURL.getLength() ) 403 { 404 uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) ); 405 if( !xGraphic.is() ) 406 xGraphic = implLoadResource( aURL ); 407 if( !xGraphic.is() ) 408 xGraphic = implLoadGraphicObject( aURL ); 409 410 if ( !xGraphic.is() ) 411 xGraphic = implLoadRepositoryImage( aURL ); 412 413 if ( !xGraphic.is() ) 414 xGraphic = implLoadStandardImage( aURL ); 415 416 if( xGraphic.is() ) 417 { 418 xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY ); 419 } 420 else 421 { 422 GraphicDescriptor* pDescriptor = new GraphicDescriptor; 423 pDescriptor->init( aURL ); 424 xRet = pDescriptor; 425 } 426 } 427 else if( xBtm.is() ) 428 { 429 uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) ); 430 if( xGraphic.is() ) 431 xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY ); 432 } 433 434 return xRet; 435 } 436 437 // ------------------------------------------------------------------------------ 438 439 uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties ) 440 throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) 441 { 442 uno::Reference< ::graphic::XGraphic > xRet; 443 String aPath; 444 SvStream* pIStm = NULL; 445 446 uno::Reference< io::XInputStream > xIStm; 447 uno::Reference< awt::XBitmap >xBtm; 448 449 for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i ) 450 { 451 const ::rtl::OUString aName( rMediaProperties[ i ].Name ); 452 const uno::Any aValue( rMediaProperties[ i ].Value ); 453 454 if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) ) 455 { 456 ::rtl::OUString aURL; 457 aValue >>= aURL; 458 aPath = aURL; 459 } 460 else if( COMPARE_EQUAL == aName.compareToAscii( "InputStream" ) ) 461 { 462 aValue >>= xIStm; 463 } 464 else if( COMPARE_EQUAL == aName.compareToAscii( "Bitmap" ) ) 465 { 466 aValue >>= xBtm; 467 } 468 } 469 470 if( xIStm.is() ) 471 { 472 pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm ); 473 } 474 else if( aPath.Len() ) 475 { 476 xRet = implLoadMemory( aPath ); 477 478 if( !xRet.is() ) 479 xRet = implLoadGraphicObject( aPath ); 480 481 if( !xRet.is() ) 482 xRet = implLoadResource( aPath ); 483 484 if ( !xRet.is() ) 485 xRet = implLoadRepositoryImage( aPath ); 486 487 if ( !xRet.is() ) 488 xRet = implLoadStandardImage( aPath ); 489 490 if( !xRet.is() ) 491 pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, STREAM_READ ); 492 } 493 else if( xBtm.is() ) 494 { 495 xRet = implLoadBitmap( xBtm ); 496 } 497 498 if( pIStm ) 499 { 500 ::GraphicFilter* pFilter = ::GraphicFilter::GetGraphicFilter(); 501 502 if( pFilter ) 503 { 504 ::Graphic aVCLGraphic; 505 506 if( ( pFilter->ImportGraphic( aVCLGraphic, aPath, *pIStm ) == GRFILTER_OK ) && 507 ( aVCLGraphic.GetType() != GRAPHIC_NONE ) ) 508 { 509 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; 510 511 pUnoGraphic->init( aVCLGraphic ); 512 xRet = pUnoGraphic; 513 } 514 } 515 516 delete pIStm; 517 } 518 519 return xRet; 520 } 521 522 void ImplCalculateCropRect( ::Graphic& rGraphic, const text::GraphicCrop& rGraphicCropLogic, Rectangle& rGraphicCropPixel ) 523 { 524 if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom ) 525 { 526 Size aSourceSizePixel( rGraphic.GetSizePixel() ); 527 if ( aSourceSizePixel.Width() && aSourceSizePixel.Height() ) 528 { 529 if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom ) 530 { 531 Size aSize100thMM( 0, 0 ); 532 if( rGraphic.GetPrefMapMode().GetMapUnit() != MAP_PIXEL ) 533 { 534 aSize100thMM = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MAP_100TH_MM ); 535 } 536 else 537 { 538 aSize100thMM = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), MAP_100TH_MM ); 539 } 540 if ( aSize100thMM.Width() && aSize100thMM.Height() ) 541 { 542 double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width()); 543 double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height()); 544 rGraphicCropPixel.Left() = static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()); 545 rGraphicCropPixel.Top() = static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()); 546 rGraphicCropPixel.Right() = static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ); 547 rGraphicCropPixel.Bottom() = static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() ); 548 } 549 } 550 } 551 } 552 } 553 554 void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight ) 555 { 556 if ( nPixelWidth && nPixelHeight ) 557 { 558 BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); 559 MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() ); 560 Size aPrefSize( aBmpEx.GetPrefSize() ); 561 aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) ); 562 aBmpEx.SetPrefMapMode( aPrefMapMode ); 563 aBmpEx.SetPrefSize( aPrefSize ); 564 rGraphic = aBmpEx; 565 } 566 } 567 568 void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize ) 569 { 570 if ( nImageResolution && rLogicalSize.Width && rLogicalSize.Height ) 571 { 572 const double fImageResolution = static_cast<double>( nImageResolution ); 573 const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width); 574 const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height); 575 const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() ); 576 const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() ); 577 const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth ); 578 const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight ); 579 580 sal_Int32 nDestPixelWidth = nSourcePixelWidth; 581 sal_Int32 nDestPixelHeight = nSourcePixelHeight; 582 583 // check, if the bitmap DPI exceeds the maximum DPI 584 if( fSourceDPIX > fImageResolution ) 585 { 586 nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX); 587 if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) ) 588 nDestPixelWidth = nSourcePixelWidth; 589 } 590 if ( fSourceDPIY > fImageResolution ) 591 { 592 nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY); 593 if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) ) 594 nDestPixelHeight = nSourcePixelHeight; 595 } 596 if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) ) 597 ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight ); 598 } 599 } 600 601 void ImplApplyFilterData( ::Graphic& rGraphic, uno::Sequence< beans::PropertyValue >& rFilterData ) 602 { 603 /* this method applies following attributes to the graphic, in the first step the 604 cropping area (logical size in 100thmm) is applied, in the second step the resolution 605 is applied, in the third step the graphic is scaled to the corresponding pixelsize. 606 if a parameter value is zero or not available the corresponding step will be skipped */ 607 608 sal_Int32 nPixelWidth = 0; 609 sal_Int32 nPixelHeight= 0; 610 sal_Int32 nImageResolution = 0; 611 awt::Size aLogicalSize( 0, 0 ); 612 text::GraphicCrop aCropLogic( 0, 0, 0, 0 ); 613 sal_Bool bRemoveCropArea = sal_True; 614 615 for( sal_Int32 i = 0; i < rFilterData.getLength(); ++i ) 616 { 617 const ::rtl::OUString aName( rFilterData[ i ].Name ); 618 const uno::Any aValue( rFilterData[ i ].Value ); 619 620 if( COMPARE_EQUAL == aName.compareToAscii( "PixelWidth" ) ) 621 aValue >>= nPixelWidth; 622 else if( COMPARE_EQUAL == aName.compareToAscii( "PixelHeight" ) ) 623 aValue >>= nPixelHeight; 624 else if( COMPARE_EQUAL == aName.compareToAscii( "LogicalSize" ) ) 625 aValue >>= aLogicalSize; 626 else if (COMPARE_EQUAL == aName.compareToAscii( "GraphicCropLogic" ) ) 627 aValue >>= aCropLogic; 628 else if (COMPARE_EQUAL == aName.compareToAscii( "RemoveCropArea" ) ) 629 aValue >>= bRemoveCropArea; 630 else if (COMPARE_EQUAL == aName.compareToAscii( "ImageResolution" ) ) 631 aValue >>= nImageResolution; 632 } 633 if ( rGraphic.GetType() == GRAPHIC_BITMAP ) 634 { 635 Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() ); 636 ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel ); 637 if ( bRemoveCropArea ) 638 { 639 BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); 640 aBmpEx.Crop( aCropPixel ); 641 rGraphic = aBmpEx; 642 } 643 Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() ); 644 ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize ); 645 ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight ); 646 } 647 else if ( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && nImageResolution ) 648 { 649 VirtualDevice aDummyVDev; 650 GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() ); 651 Size aMtfSize( aDummyVDev.LogicToLogic( aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MAP_100TH_MM ) ); 652 if ( aMtfSize.Width() && aMtfSize.Height() ) 653 { 654 MapMode aNewMapMode( MAP_100TH_MM ); 655 aNewMapMode.SetScaleX( static_cast< double >( aLogicalSize.Width ) / static_cast< double >( aMtfSize.Width() ) ); 656 aNewMapMode.SetScaleY( static_cast< double >( aLogicalSize.Height ) / static_cast< double >( aMtfSize.Height() ) ); 657 aDummyVDev.EnableOutput( sal_False ); 658 aDummyVDev.SetMapMode( aNewMapMode ); 659 660 for( sal_uInt32 i = 0, nObjCount = aMtf.GetActionCount(); i < nObjCount; i++ ) 661 { 662 MetaAction* pAction = aMtf.GetAction( i ); 663 switch( pAction->GetType() ) 664 { 665 // only optimizing common bitmap actions: 666 case( META_MAPMODE_ACTION ): 667 { 668 const_cast< MetaAction* >( pAction )->Execute( &aDummyVDev ); 669 break; 670 } 671 case( META_PUSH_ACTION ): 672 { 673 const MetaPushAction* pA = (const MetaPushAction*)pAction; 674 aDummyVDev.Push( pA->GetFlags() ); 675 break; 676 } 677 case( META_POP_ACTION ): 678 { 679 aDummyVDev.Pop(); 680 break; 681 } 682 case( META_BMPSCALE_ACTION ): 683 case( META_BMPEXSCALE_ACTION ): 684 { 685 BitmapEx aBmpEx; 686 Point aPos; 687 Size aSize; 688 if ( pAction->GetType() == META_BMPSCALE_ACTION ) 689 { 690 MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction ); 691 aBmpEx = pScaleAction->GetBitmap(); 692 aPos = pScaleAction->GetPoint(); 693 aSize = pScaleAction->GetSize(); 694 } 695 else 696 { 697 MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction ); 698 aBmpEx = pScaleAction->GetBitmapEx(); 699 aPos = pScaleAction->GetPoint(); 700 aSize = pScaleAction->GetSize(); 701 } 702 ::Graphic aGraphic( aBmpEx ); 703 const Size aSize100thmm( aDummyVDev.LogicToPixel( aSize ) ); 704 Size aSize100thmm2( aDummyVDev.PixelToLogic( aSize100thmm, MAP_100TH_MM ) ); 705 706 ImplApplyBitmapResolution( aGraphic, nImageResolution, 707 aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) ); 708 709 MetaAction* pNewAction; 710 if ( pAction->GetType() == META_BMPSCALE_ACTION ) 711 pNewAction = new MetaBmpScaleAction ( aPos, aSize, aGraphic.GetBitmap() ); 712 else 713 pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() ); 714 715 aMtf.ReplaceAction( pNewAction, i ); 716 pAction->Delete(); 717 break; 718 } 719 default: 720 case( META_BMP_ACTION ): 721 case( META_BMPSCALEPART_ACTION ): 722 case( META_BMPEX_ACTION ): 723 case( META_BMPEXSCALEPART_ACTION ): 724 case( META_MASK_ACTION ): 725 case( META_MASKSCALE_ACTION ): 726 break; 727 } 728 } 729 rGraphic = aMtf; 730 } 731 } 732 } 733 734 // ------------------------------------------------------------------------------ 735 736 void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties ) 737 throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) 738 { 739 SvStream* pOStm = NULL; 740 String aPath; 741 sal_Int32 i; 742 743 for( i = 0; ( i < rMediaProperties.getLength() ) && !pOStm; ++i ) 744 { 745 const ::rtl::OUString aName( rMediaProperties[ i ].Name ); 746 const uno::Any aValue( rMediaProperties[ i ].Value ); 747 748 if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) ) 749 { 750 ::rtl::OUString aURL; 751 752 aValue >>= aURL; 753 pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, STREAM_WRITE | STREAM_TRUNC ); 754 aPath = aURL; 755 } 756 else if( COMPARE_EQUAL == aName.compareToAscii( "OutputStream" ) ) 757 { 758 uno::Reference< io::XStream > xOStm; 759 760 aValue >>= xOStm; 761 762 if( xOStm.is() ) 763 pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm ); 764 } 765 } 766 767 if( pOStm ) 768 { 769 uno::Sequence< beans::PropertyValue > aFilterDataSeq; 770 const char* pFilterShortName = NULL; 771 772 for( i = 0; i < rMediaProperties.getLength(); ++i ) 773 { 774 const ::rtl::OUString aName( rMediaProperties[ i ].Name ); 775 const uno::Any aValue( rMediaProperties[ i ].Value ); 776 777 if( COMPARE_EQUAL == aName.compareToAscii( "FilterData" ) ) 778 { 779 aValue >>= aFilterDataSeq; 780 } 781 else if( COMPARE_EQUAL == aName.compareToAscii( "MimeType" ) ) 782 { 783 ::rtl::OUString aMimeType; 784 785 aValue >>= aMimeType; 786 787 if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_BMP ) ) 788 pFilterShortName = "bmp"; 789 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EPS ) ) 790 pFilterShortName = "eps"; 791 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_GIF ) ) 792 pFilterShortName = "gif"; 793 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_JPG ) ) 794 pFilterShortName = "jpg"; 795 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_MET ) ) 796 pFilterShortName = "met"; 797 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PNG ) ) 798 pFilterShortName = "png"; 799 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PCT ) ) 800 pFilterShortName = "pct"; 801 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PBM ) ) 802 pFilterShortName = "pbm"; 803 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PGM ) ) 804 pFilterShortName = "pgm"; 805 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PPM ) ) 806 pFilterShortName = "ppm"; 807 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_RAS ) ) 808 pFilterShortName = "ras"; 809 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVM ) ) 810 pFilterShortName = "svm"; 811 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_TIF ) ) 812 pFilterShortName = "tif"; 813 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EMF ) ) 814 pFilterShortName = "emf"; 815 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_WMF ) ) 816 pFilterShortName = "wmf"; 817 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_XPM ) ) 818 pFilterShortName = "xpm"; 819 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVG ) ) 820 pFilterShortName = "svg"; 821 else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_VCLGRAPHIC ) ) 822 pFilterShortName = MIMETYPE_VCLGRAPHIC; 823 } 824 } 825 826 if( pFilterShortName ) 827 { 828 ::GraphicFilter* pFilter = ::GraphicFilter::GetGraphicFilter(); 829 830 if( pFilter ) 831 { 832 const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY ); 833 const ::Graphic* pGraphic = ::unographic::Graphic::getImplementation( xIFace ); 834 835 if( pGraphic && ( pGraphic->GetType() != GRAPHIC_NONE ) ) 836 { 837 ::Graphic aGraphic( *pGraphic ); 838 ImplApplyFilterData( aGraphic, aFilterDataSeq ); 839 840 /* sj: using a temporary memory stream, because some graphic filters are seeking behind 841 stream end (which leads to an invalid argument exception then). */ 842 SvMemoryStream aMemStrm; 843 aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); 844 if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) ) 845 aMemStrm << aGraphic; 846 else 847 { 848 pFilter->ExportGraphic( aGraphic, aPath, aMemStrm, 849 pFilter->GetExportFormatNumberForShortName( ::rtl::OUString::createFromAscii( pFilterShortName ) ), 850 ( aFilterDataSeq.getLength() ? &aFilterDataSeq : NULL ) ); 851 } 852 aMemStrm.Seek( STREAM_SEEK_TO_END ); 853 pOStm->Write( aMemStrm.GetData(), aMemStrm.Tell() ); 854 } 855 } 856 } 857 delete pOStm; 858 } 859 } 860 861 } 862