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_vcl.hxx" 30 31 #include <rtl/logfile.hxx> 32 #include <cppuhelper/compbase1.hxx> 33 34 #include <com/sun/star/geometry/RealSize2D.hpp> 35 #include <com/sun/star/geometry/RealPoint2D.hpp> 36 #include <com/sun/star/geometry/RealRectangle2D.hpp> 37 #include <com/sun/star/geometry/IntegerSize2D.hpp> 38 #include <com/sun/star/geometry/IntegerPoint2D.hpp> 39 #include <com/sun/star/geometry/IntegerRectangle2D.hpp> 40 #include <com/sun/star/geometry/RealBezierSegment2D.hpp> 41 42 #include <com/sun/star/rendering/ColorSpaceType.hpp> 43 #include <com/sun/star/rendering/RenderingIntent.hpp> 44 #include <com/sun/star/rendering/XGraphicDevice.hpp> 45 #include <com/sun/star/rendering/XBitmap.hpp> 46 #include <com/sun/star/rendering/XPolyPolygon2D.hpp> 47 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp> 48 #include <com/sun/star/rendering/XIntegerBitmap.hpp> 49 #include <com/sun/star/rendering/ColorComponentTag.hpp> 50 51 #include <basegfx/matrix/b2dhommatrix.hxx> 52 #include <basegfx/vector/b2dsize.hxx> 53 #include <basegfx/point/b2dpoint.hxx> 54 #include <basegfx/range/b2drectangle.hxx> 55 #include <basegfx/vector/b2isize.hxx> 56 #include <basegfx/point/b2ipoint.hxx> 57 #include <basegfx/range/b2irectangle.hxx> 58 59 // #i79917# 60 #include <basegfx/polygon/b2dpolygon.hxx> 61 #include <basegfx/tools/canvastools.hxx> 62 #include <basegfx/polygon/b2dpolypolygon.hxx> 63 64 #include <tools/poly.hxx> 65 #include <tools/diagnose_ex.h> 66 #include <rtl/uuid.h> 67 68 #include <vcl/salbtype.hxx> 69 #include <vcl/bmpacc.hxx> 70 #include <vcl/bitmapex.hxx> 71 72 #include <canvasbitmap.hxx> 73 #include <vcl/canvastools.hxx> 74 #include <hash_map> 75 76 77 using namespace ::com::sun::star; 78 79 namespace vcl 80 { 81 namespace unotools 82 { 83 // #i79917# removed helpers bezierSequenceFromPolygon and 84 // pointSequenceFromPolygon here 85 // Also all helpers using tools Polygon and PolyPolygon will get mapped to the 86 // B2DPolygon helpers for these cases, see comments with the same TaskID below. 87 // TODO: Remove those wrapped methods 88 89 //--------------------------------------------------------------------------------------- 90 91 uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice, 92 const ::Polygon& inputPolygon ) 93 { 94 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolygon()" ); 95 96 // #i79917# map to basegfx 97 const basegfx::B2DPolygon aB2DPolygon(inputPolygon.getB2DPolygon()); 98 return basegfx::unotools::xPolyPolygonFromB2DPolygon(xGraphicDevice, aB2DPolygon); 99 } 100 101 //--------------------------------------------------------------------------------------- 102 103 uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice, 104 const ::PolyPolygon& inputPolyPolygon ) 105 { 106 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolyPolygon()" ); 107 108 // #i79917# map to basegfx 109 const basegfx::B2DPolyPolygon aB2DPolyPolygon(inputPolyPolygon.getB2DPolyPolygon()); 110 return basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xGraphicDevice, aB2DPolyPolygon); 111 } 112 113 //--------------------------------------------------------------------------------------- 114 115 ::Polygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points ) 116 { 117 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polygonFromPoint2DSequence()" ); 118 119 const sal_uInt16 nCurrSize( sal::static_int_cast<sal_uInt16>(points.getLength()) ); 120 121 ::Polygon aPoly( nCurrSize ); 122 123 sal_uInt16 nCurrPoint; 124 for( nCurrPoint=0; nCurrPoint<nCurrSize; ++nCurrPoint ) 125 aPoly[nCurrPoint] = pointFromRealPoint2D( points[nCurrPoint] ); 126 127 return aPoly; 128 } 129 130 //--------------------------------------------------------------------------------------- 131 132 ::PolyPolygon polyPolygonFromPoint2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points ) 133 { 134 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polyPolygonFromPoint2DSequenceSequence()" ); 135 136 ::PolyPolygon aRes; 137 138 int nCurrPoly; 139 for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly ) 140 { 141 aRes.Insert( polygonFromPoint2DSequence( points[nCurrPoly] ) ); 142 } 143 144 return aRes; 145 } 146 147 //--------------------------------------------------------------------------------------- 148 149 ::Polygon polygonFromBezier2DSequence( const uno::Sequence< geometry::RealBezierSegment2D >& curves ) 150 { 151 // #i79917# map to basegfx 152 const basegfx::B2DPolygon aB2DPolygon(basegfx::unotools::polygonFromBezier2DSequence(curves)); 153 return ::Polygon(aB2DPolygon); 154 } 155 156 //--------------------------------------------------------------------------------------- 157 158 ::PolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves ) 159 { 160 // #i79917# map to basegfx 161 const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(curves)); 162 return ::PolyPolygon(aB2DPolyPolygon); 163 } 164 165 //--------------------------------------------------------------------------------------- 166 167 uno::Reference< rendering::XBitmap > xBitmapFromBitmap( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/, 168 const ::Bitmap& inputBitmap ) 169 { 170 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmap()" ); 171 172 return new vcl::unotools::VclCanvasBitmap( BitmapEx( inputBitmap ) ); 173 } 174 175 //--------------------------------------------------------------------------------------- 176 177 uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/, 178 const ::BitmapEx& inputBitmap ) 179 { 180 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" ); 181 182 return new vcl::unotools::VclCanvasBitmap( inputBitmap ); 183 } 184 185 //--------------------------------------------------------------------------------------- 186 187 const uno::Sequence< sal_Int8 > getTunnelIdentifier( TunnelIdentifierType eType ) 188 { 189 static std::hash_map< int, uno::Sequence< sal_Int8 > > aIds; 190 std::hash_map< int, uno::Sequence< sal_Int8 > >::iterator it = 191 aIds.find( eType ); 192 if( it == aIds.end() ) 193 { 194 uno::Sequence< sal_Int8 > aNewId( 16 ); 195 rtl_createUuid( (sal_uInt8*)aNewId.getArray(), NULL, sal_True ); 196 aIds[ eType ] = aNewId; 197 it = aIds.find( eType ); 198 } 199 return it->second; 200 } 201 202 //--------------------------------------------------------------------------------------- 203 204 namespace 205 { 206 inline bool operator==( const rendering::IntegerBitmapLayout& rLHS, 207 const rendering::IntegerBitmapLayout& rRHS ) 208 { 209 return 210 rLHS.ScanLineBytes == rRHS.ScanLineBytes && 211 rLHS.ScanLineStride == rRHS.ScanLineStride && 212 rLHS.PlaneStride == rRHS.PlaneStride && 213 rLHS.ColorSpace == rRHS.ColorSpace && 214 rLHS.Palette == rRHS.Palette && 215 rLHS.IsMsbFirst == rRHS.IsMsbFirst; 216 } 217 218 bool readBmp( sal_Int32 nWidth, 219 sal_Int32 nHeight, 220 const rendering::IntegerBitmapLayout& rLayout, 221 const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap, 222 ScopedBitmapWriteAccess& rWriteAcc, 223 ScopedBitmapWriteAccess& rAlphaAcc ) 224 { 225 rendering::IntegerBitmapLayout aCurrLayout; 226 geometry::IntegerRectangle2D aRect; 227 uno::Sequence<sal_Int8> aPixelData; 228 uno::Sequence<rendering::RGBColor> aRGBColors; 229 uno::Sequence<rendering::ARGBColor> aARGBColors; 230 231 for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 ) 232 { 233 aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1; 234 try 235 { 236 aPixelData = xInputBitmap->getData(aCurrLayout,aRect); 237 } 238 catch( rendering::VolatileContentDestroyedException& ) 239 { 240 // re-read bmp from the start 241 return false; 242 } 243 if( !(aCurrLayout == rLayout) ) 244 return false; // re-read bmp from the start 245 246 if( rAlphaAcc.get() ) 247 { 248 // read ARGB color 249 aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData); 250 251 if( rWriteAcc->HasPalette() ) 252 { 253 for( sal_Int32 x=0; x<nWidth; ++x ) 254 { 255 const rendering::ARGBColor& rColor=aARGBColors[x]; 256 rWriteAcc->SetPixel( aRect.Y1, x, 257 (sal_uInt8)rWriteAcc->GetBestPaletteIndex( 258 BitmapColor( toByteColor(rColor.Red), 259 toByteColor(rColor.Green), 260 toByteColor(rColor.Blue))) ); 261 rAlphaAcc->SetPixel( aRect.Y1, x, 262 BitmapColor( 255 - toByteColor(rColor.Alpha) )); 263 } 264 } 265 else 266 { 267 for( sal_Int32 x=0; x<nWidth; ++x ) 268 { 269 const rendering::ARGBColor& rColor=aARGBColors[x]; 270 rWriteAcc->SetPixel( aRect.Y1, x, 271 BitmapColor( toByteColor(rColor.Red), 272 toByteColor(rColor.Green), 273 toByteColor(rColor.Blue) )); 274 rAlphaAcc->SetPixel( aRect.Y1, x, 275 BitmapColor( 255 - toByteColor(rColor.Alpha) )); 276 } 277 } 278 } 279 else 280 { 281 // read RGB color 282 aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData); 283 if( rWriteAcc->HasPalette() ) 284 { 285 for( sal_Int32 x=0; x<nWidth; ++x ) 286 { 287 const rendering::RGBColor& rColor=aRGBColors[x]; 288 rWriteAcc->SetPixel( aRect.Y1, x, 289 (sal_uInt8)rWriteAcc->GetBestPaletteIndex( 290 BitmapColor( toByteColor(rColor.Red), 291 toByteColor(rColor.Green), 292 toByteColor(rColor.Blue))) ); 293 } 294 } 295 else 296 { 297 for( sal_Int32 x=0; x<nWidth; ++x ) 298 { 299 const rendering::RGBColor& rColor=aRGBColors[x]; 300 rWriteAcc->SetPixel( aRect.Y1, x, 301 BitmapColor( toByteColor(rColor.Red), 302 toByteColor(rColor.Green), 303 toByteColor(rColor.Blue) )); 304 } 305 } 306 } 307 } 308 309 return true; 310 } 311 } 312 313 ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap ) 314 { 315 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" ); 316 317 if( !xInputBitmap.is() ) 318 return ::BitmapEx(); 319 320 // tunnel directly for known implementation 321 // ---------------------------------------------------------------- 322 VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get()); 323 if( pImplBitmap ) 324 return pImplBitmap->getBitmapEx(); 325 326 // retrieve data via UNO interface 327 // ---------------------------------------------------------------- 328 329 // volatile bitmaps are a bit more complicated to read 330 // from.. 331 uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap( 332 xInputBitmap, uno::UNO_QUERY); 333 334 // loop a few times, until successfully read (for XVolatileBitmap) 335 for( int i=0; i<10; ++i ) 336 { 337 sal_Int32 nDepth=0; 338 sal_Int32 nAlphaDepth=0; 339 const rendering::IntegerBitmapLayout aLayout( 340 xInputBitmap->getMemoryLayout()); 341 342 OSL_ENSURE(aLayout.ColorSpace.is(), 343 "Cannot convert image without color space!"); 344 if( !aLayout.ColorSpace.is() ) 345 return ::BitmapEx(); 346 347 nDepth = aLayout.ColorSpace->getBitsPerPixel(); 348 349 if( xInputBitmap->hasAlpha() ) 350 { 351 // determine alpha channel depth 352 const uno::Sequence<sal_Int8> aTags( 353 aLayout.ColorSpace->getComponentTags() ); 354 const uno::Sequence<sal_Int32> aDepths( 355 aLayout.ColorSpace->getComponentBitCounts() ); 356 const sal_Int8* pStart(aTags.getConstArray()); 357 const sal_Size nLen(aTags.getLength()); 358 const sal_Int8* pEnd(pStart+nLen); 359 360 const std::ptrdiff_t nAlphaIndex = 361 std::find(pStart,pEnd, 362 rendering::ColorComponentTag::ALPHA) - pStart; 363 364 if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) ) 365 { 366 nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1; 367 nDepth -= nAlphaDepth; 368 } 369 } 370 371 BitmapPalette aPalette; 372 if( aLayout.Palette.is() ) 373 { 374 uno::Reference< rendering::XColorSpace > xPaletteColorSpace( 375 aLayout.Palette->getColorSpace()); 376 ENSURE_OR_THROW(xPaletteColorSpace.is(), 377 "Palette without color space"); 378 379 const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() ); 380 if( nEntryCount <= 256 ) 381 { 382 if( nEntryCount <= 2 ) 383 nDepth = 1; 384 else 385 nDepth = 8; 386 387 const sal_uInt16 nPaletteEntries( 388 sal::static_int_cast<sal_uInt16>( 389 std::min(sal_Int32(255), nEntryCount))); 390 391 // copy palette entries 392 aPalette.SetEntryCount(nPaletteEntries); 393 uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette ); 394 uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() ); 395 396 uno::Sequence<double> aPaletteEntry; 397 for( sal_uInt16 j=0; j<nPaletteEntries; ++j ) 398 { 399 if( !xPalette->getIndex(aPaletteEntry,j) && 400 nAlphaDepth == 0 ) 401 { 402 nAlphaDepth = 1; 403 } 404 uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry); 405 ENSURE_OR_THROW(aColors.getLength() == 1, 406 "Palette returned more or less than one entry"); 407 const rendering::RGBColor& rColor=aColors[0]; 408 aPalette[j] = BitmapColor(toByteColor(rColor.Red), 409 toByteColor(rColor.Green), 410 toByteColor(rColor.Blue)); 411 } 412 } 413 } 414 415 const ::Size aPixelSize( 416 sizeFromIntegerSize2D(xInputBitmap->getSize())); 417 418 // normalize bitcount 419 nDepth = 420 ( nDepth <= 1 ) ? 1 : 421 ( nDepth <= 4 ) ? 4 : 422 ( nDepth <= 8 ) ? 8 : 24; 423 424 ::Bitmap aBitmap( aPixelSize, 425 sal::static_int_cast<sal_uInt16>(nDepth), 426 aLayout.Palette.is() ? &aPalette : NULL ); 427 ::Bitmap aAlpha; 428 if( nAlphaDepth ) 429 aAlpha = ::Bitmap( aPixelSize, 430 sal::static_int_cast<sal_uInt16>(nAlphaDepth), 431 &::Bitmap::GetGreyPalette( 432 sal::static_int_cast<sal_uInt16>(1L << nAlphaDepth)) ); 433 434 { // limit scoped access 435 ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(), 436 aBitmap ); 437 ScopedBitmapWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL, 438 aAlpha ); 439 440 ENSURE_OR_THROW(pWriteAccess.get() != NULL, 441 "Cannot get write access to bitmap"); 442 443 const sal_Int32 nWidth(aPixelSize.Width()); 444 const sal_Int32 nHeight(aPixelSize.Height()); 445 446 if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap, 447 pWriteAccess,pAlphaWriteAccess) ) 448 continue; 449 } // limit scoped access 450 451 if( nAlphaDepth ) 452 return ::BitmapEx( aBitmap, 453 AlphaMask( aAlpha ) ); 454 else 455 return ::BitmapEx( aBitmap ); 456 } 457 458 // failed to read data 10 times - bail out 459 return ::BitmapEx(); 460 } 461 462 //--------------------------------------------------------------------------------------- 463 464 geometry::RealSize2D size2DFromSize( const Size& rSize ) 465 { 466 return geometry::RealSize2D( rSize.Width(), 467 rSize.Height() ); 468 } 469 470 geometry::RealPoint2D point2DFromPoint( const Point& rPoint ) 471 { 472 return geometry::RealPoint2D( rPoint.X(), 473 rPoint.Y() ); 474 } 475 476 geometry::RealRectangle2D rectangle2DFromRectangle( const Rectangle& rRect ) 477 { 478 return geometry::RealRectangle2D( rRect.Left(), rRect.Top(), 479 rRect.Right(), rRect.Bottom() ); 480 } 481 482 Size sizeFromRealSize2D( const geometry::RealSize2D& rSize ) 483 { 484 return Size( static_cast<long>(rSize.Width + .5), 485 static_cast<long>(rSize.Height + .5) ); 486 } 487 488 Point pointFromRealPoint2D( const geometry::RealPoint2D& rPoint ) 489 { 490 return Point( static_cast<long>(rPoint.X + .5), 491 static_cast<long>(rPoint.Y + .5) ); 492 } 493 494 Rectangle rectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect ) 495 { 496 return Rectangle( static_cast<long>(rRect.X1 + .5), 497 static_cast<long>(rRect.Y1 + .5), 498 static_cast<long>(rRect.X2 + .5), 499 static_cast<long>(rRect.Y2 + .5) ); 500 } 501 502 ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec ) 503 { 504 return ::Size( FRound( rVec.getX() ), 505 FRound( rVec.getY() ) ); 506 } 507 508 ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint ) 509 { 510 return ::Point( FRound( rPoint.getX() ), 511 FRound( rPoint.getY() ) ); 512 } 513 514 ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect ) 515 { 516 return ::Rectangle( FRound( rRect.getMinX() ), 517 FRound( rRect.getMinY() ), 518 FRound( rRect.getMaxX() ), 519 FRound( rRect.getMaxY() ) ); 520 } 521 522 Size sizeFromB2ISize( const ::basegfx::B2IVector& rVec ) 523 { 524 return ::Size( rVec.getX(), 525 rVec.getY() ); 526 } 527 528 Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint ) 529 { 530 return ::Point( rPoint.getX(), 531 rPoint.getY() ); 532 } 533 534 Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect ) 535 { 536 return ::Rectangle( rRect.getMinX(), 537 rRect.getMinY(), 538 rRect.getMaxX(), 539 rRect.getMaxY() ); 540 } 541 542 ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize ) 543 { 544 return ::basegfx::B2DVector( rSize.Width(), 545 rSize.Height() ); 546 } 547 548 ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint ) 549 { 550 return ::basegfx::B2DPoint( rPoint.X(), 551 rPoint.Y() ); 552 } 553 554 ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect ) 555 { 556 return ::basegfx::B2DRange( rRect.Left(), 557 rRect.Top(), 558 rRect.Right(), 559 rRect.Bottom() ); 560 } 561 562 basegfx::B2IVector b2ISizeFromSize( const Size& rSize ) 563 { 564 return ::basegfx::B2IVector( rSize.Width(), 565 rSize.Height() ); 566 } 567 568 basegfx::B2IPoint b2IPointFromPoint( const Point& rPoint ) 569 { 570 return ::basegfx::B2IPoint( rPoint.X(), 571 rPoint.Y() ); 572 } 573 574 basegfx::B2IRange b2IRectangleFromRectangle( const Rectangle& rRect ) 575 { 576 return ::basegfx::B2IRange( rRect.Left(), 577 rRect.Top(), 578 rRect.Right(), 579 rRect.Bottom() ); 580 } 581 582 geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize ) 583 { 584 return geometry::IntegerSize2D( rSize.Width(), 585 rSize.Height() ); 586 } 587 588 geometry::IntegerPoint2D integerPoint2DFromPoint( const Point& rPoint ) 589 { 590 return geometry::IntegerPoint2D( rPoint.X(), 591 rPoint.Y() ); 592 } 593 594 geometry::IntegerRectangle2D integerRectangle2DFromRectangle( const Rectangle& rRectangle ) 595 { 596 return geometry::IntegerRectangle2D( rRectangle.Left(), rRectangle.Top(), 597 rRectangle.Right(), rRectangle.Bottom() ); 598 } 599 600 Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize ) 601 { 602 return Size( rSize.Width, 603 rSize.Height ); 604 } 605 606 Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint ) 607 { 608 return Point( rPoint.X, 609 rPoint.Y ); 610 } 611 612 Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle ) 613 { 614 return Rectangle( rRectangle.X1, rRectangle.Y1, 615 rRectangle.X2, rRectangle.Y2 ); 616 } 617 618 namespace 619 { 620 class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace > 621 { 622 private: 623 uno::Sequence< sal_Int8 > m_aComponentTags; 624 625 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) 626 { 627 return rendering::ColorSpaceType::RGB; 628 } 629 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) 630 { 631 return m_aComponentTags; 632 } 633 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) 634 { 635 return rendering::RenderingIntent::PERCEPTUAL; 636 } 637 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) 638 { 639 return uno::Sequence< beans::PropertyValue >(); 640 } 641 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, 642 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, 643 uno::RuntimeException) 644 { 645 // TODO(P3): if we know anything about target 646 // colorspace, this can be greatly sped up 647 uno::Sequence<rendering::ARGBColor> aIntermediate( 648 convertToARGB(deviceColor)); 649 return targetColorSpace->convertFromARGB(aIntermediate); 650 } 651 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 652 { 653 const double* pIn( deviceColor.getConstArray() ); 654 const sal_Size nLen( deviceColor.getLength() ); 655 ENSURE_ARG_OR_THROW2(nLen%4==0, 656 "number of channels no multiple of 4", 657 static_cast<rendering::XColorSpace*>(this), 0); 658 659 uno::Sequence< rendering::RGBColor > aRes(nLen/4); 660 rendering::RGBColor* pOut( aRes.getArray() ); 661 for( sal_Size i=0; i<nLen; i+=4 ) 662 { 663 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]); 664 pIn += 4; 665 } 666 return aRes; 667 } 668 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 669 { 670 const double* pIn( deviceColor.getConstArray() ); 671 const sal_Size nLen( deviceColor.getLength() ); 672 ENSURE_ARG_OR_THROW2(nLen%4==0, 673 "number of channels no multiple of 4", 674 static_cast<rendering::XColorSpace*>(this), 0); 675 676 uno::Sequence< rendering::ARGBColor > aRes(nLen/4); 677 rendering::ARGBColor* pOut( aRes.getArray() ); 678 for( sal_Size i=0; i<nLen; i+=4 ) 679 { 680 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]); 681 pIn += 4; 682 } 683 return aRes; 684 } 685 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 686 { 687 const double* pIn( deviceColor.getConstArray() ); 688 const sal_Size nLen( deviceColor.getLength() ); 689 ENSURE_ARG_OR_THROW2(nLen%4==0, 690 "number of channels no multiple of 4", 691 static_cast<rendering::XColorSpace*>(this), 0); 692 693 uno::Sequence< rendering::ARGBColor > aRes(nLen/4); 694 rendering::ARGBColor* pOut( aRes.getArray() ); 695 for( sal_Size i=0; i<nLen; i+=4 ) 696 { 697 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]); 698 pIn += 4; 699 } 700 return aRes; 701 } 702 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 703 { 704 const rendering::RGBColor* pIn( rgbColor.getConstArray() ); 705 const sal_Size nLen( rgbColor.getLength() ); 706 707 uno::Sequence< double > aRes(nLen*4); 708 double* pColors=aRes.getArray(); 709 for( sal_Size i=0; i<nLen; ++i ) 710 { 711 *pColors++ = pIn->Red; 712 *pColors++ = pIn->Green; 713 *pColors++ = pIn->Blue; 714 *pColors++ = 1.0; 715 ++pIn; 716 } 717 return aRes; 718 } 719 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 720 { 721 const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); 722 const sal_Size nLen( rgbColor.getLength() ); 723 724 uno::Sequence< double > aRes(nLen*4); 725 double* pColors=aRes.getArray(); 726 for( sal_Size i=0; i<nLen; ++i ) 727 { 728 *pColors++ = pIn->Red; 729 *pColors++ = pIn->Green; 730 *pColors++ = pIn->Blue; 731 *pColors++ = pIn->Alpha; 732 ++pIn; 733 } 734 return aRes; 735 } 736 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 737 { 738 const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); 739 const sal_Size nLen( rgbColor.getLength() ); 740 741 uno::Sequence< double > aRes(nLen*4); 742 double* pColors=aRes.getArray(); 743 for( sal_Size i=0; i<nLen; ++i ) 744 { 745 *pColors++ = pIn->Red/pIn->Alpha; 746 *pColors++ = pIn->Green/pIn->Alpha; 747 *pColors++ = pIn->Blue/pIn->Alpha; 748 *pColors++ = pIn->Alpha; 749 ++pIn; 750 } 751 return aRes; 752 } 753 754 public: 755 StandardColorSpace() : m_aComponentTags(4) 756 { 757 sal_Int8* pTags = m_aComponentTags.getArray(); 758 pTags[0] = rendering::ColorComponentTag::RGB_RED; 759 pTags[1] = rendering::ColorComponentTag::RGB_GREEN; 760 pTags[2] = rendering::ColorComponentTag::RGB_BLUE; 761 pTags[3] = rendering::ColorComponentTag::ALPHA; 762 } 763 }; 764 } 765 766 uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace() 767 { 768 return new StandardColorSpace(); 769 } 770 771 //--------------------------------------------------------------------------------------- 772 773 uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor ) 774 { 775 uno::Sequence< double > aRet(4); 776 double* pRet = aRet.getArray(); 777 778 pRet[0] = toDoubleColor(rColor.GetRed()); 779 pRet[1] = toDoubleColor(rColor.GetGreen()); 780 pRet[2] = toDoubleColor(rColor.GetBlue()); 781 782 // VCL's notion of alpha is different from the rest of the world's 783 pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency()); 784 785 return aRet; 786 } 787 788 Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor ) 789 { 790 ENSURE_ARG_OR_THROW( rColor.getLength() == 4, 791 "color must have 4 channels" ); 792 793 Color aColor; 794 795 aColor.SetRed ( toByteColor(rColor[0]) ); 796 aColor.SetGreen( toByteColor(rColor[1]) ); 797 aColor.SetBlue ( toByteColor(rColor[2]) ); 798 // VCL's notion of alpha is different from the rest of the world's 799 aColor.SetTransparency( 255 - toByteColor(rColor[3]) ); 800 801 return aColor; 802 } 803 804 uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence( 805 const Color& rColor, 806 const uno::Reference< rendering::XColorSpace >& xColorSpace ) 807 { 808 uno::Sequence<rendering::ARGBColor> aSeq(1); 809 aSeq[0] = rendering::ARGBColor( 810 1.0-toDoubleColor(rColor.GetTransparency()), 811 toDoubleColor(rColor.GetRed()), 812 toDoubleColor(rColor.GetGreen()), 813 toDoubleColor(rColor.GetBlue()) ); 814 815 return xColorSpace->convertFromARGB(aSeq); 816 } 817 818 Color VCL_DLLPUBLIC doubleSequenceToColor( 819 const uno::Sequence< double > rColor, 820 const uno::Reference< rendering::XColorSpace >& xColorSpace ) 821 { 822 const rendering::ARGBColor& rARGBColor( 823 xColorSpace->convertToARGB(rColor)[0]); 824 825 return Color( 255-toByteColor(rARGBColor.Alpha), 826 toByteColor(rARGBColor.Red), 827 toByteColor(rARGBColor.Green), 828 toByteColor(rARGBColor.Blue) ); 829 } 830 831 //--------------------------------------------------------------------------------------- 832 833 } // namespace vcltools 834 835 } // namespace canvas 836 837 // eof 838