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