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