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 // bootstrap stuff 28 #include <sal/main.h> 29 #include <rtl/bootstrap.hxx> 30 #include <rtl/ref.hxx> 31 #include <comphelper/processfactory.hxx> 32 #include <comphelper/regpathhelper.hxx> 33 #include <cppuhelper/servicefactory.hxx> 34 #include <cppuhelper/bootstrap.hxx> 35 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 36 #include <com/sun/star/lang/XInitialization.hpp> 37 #include <com/sun/star/registry/XSimpleRegistry.hpp> 38 #include <com/sun/star/util/Endianness.hpp> 39 #include <com/sun/star/rendering/ColorComponentTag.hpp> 40 #include <com/sun/star/rendering/ColorSpaceType.hpp> 41 #include <com/sun/star/rendering/RenderingIntent.hpp> 42 #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp> 43 #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp> 44 #include <com/sun/star/rendering/XBitmapPalette.hpp> 45 46 #include <ucbhelper/contentbroker.hxx> 47 #include <ucbhelper/configurationkeys.hxx> 48 #include <cppuhelper/compbase3.hxx> 49 50 #include <tools/diagnose_ex.h> 51 #include <tools/extendapplicationenvironment.hxx> 52 53 #include "vcl/svapp.hxx" 54 #include "vcl/canvastools.hxx" 55 #include "vcl/canvasbitmap.hxx" 56 #include "vcl/dialog.hxx" 57 #include "vcl/outdev.hxx" 58 #include "vcl/bmpacc.hxx" 59 #include "vcl/virdev.hxx" 60 #include "vcl/bitmapex.hxx" 61 62 63 using namespace ::com::sun::star; 64 using namespace ::vcl::unotools; 65 66 // ----------------------------------------------------------------------- 67 68 void Main(); 69 70 // ----------------------------------------------------------------------- 71 72 SAL_IMPLEMENT_MAIN() 73 { 74 tools::extendApplicationEnvironment(); 75 76 uno::Reference< lang::XMultiServiceFactory > xMS; 77 xMS = cppu::createRegistryServiceFactory( 78 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" ) ), 79 sal_True ); 80 81 InitVCL( xMS ); 82 ::Main(); 83 DeInitVCL(); 84 85 return 0; 86 } 87 88 // ----------------------------------------------------------------------- 89 90 namespace com { namespace sun { namespace star { namespace rendering 91 { 92 93 bool operator==( const RGBColor& rLHS, const ARGBColor& rRHS ) 94 { 95 return rLHS.Red == rRHS.Red && rLHS.Green == rRHS.Green && rLHS.Blue == rRHS.Blue; 96 } 97 bool operator==( const ARGBColor& rLHS, const RGBColor& rRHS ) 98 { 99 return rLHS.Red == rRHS.Red && rLHS.Green == rRHS.Green && rLHS.Blue == rRHS.Blue; 100 } 101 102 } } } } 103 104 //---------------------------------------------------------------------------------- 105 106 namespace 107 { 108 109 class TestApp : public Application 110 { 111 public: 112 virtual void Main(); 113 virtual USHORT Exception( USHORT nError ); 114 }; 115 116 class TestWindow : public Dialog 117 { 118 public: 119 TestWindow() : Dialog( (Window *) NULL ) 120 { 121 SetText( rtl::OUString::createFromAscii( "CanvasBitmap test harness" ) ); 122 SetSizePixel( Size( 1024, 1024 ) ); 123 EnablePaint( true ); 124 Show(); 125 } 126 127 virtual ~TestWindow() {} 128 virtual void Paint( const Rectangle& rRect ); 129 }; 130 131 //---------------------------------------------------------------------------------- 132 133 static bool g_failure=false; 134 135 void test( bool bResult, const char* msg ) 136 { 137 if( bResult ) 138 { 139 OSL_TRACE("Testing: %s - PASSED", msg); 140 } 141 else 142 { 143 g_failure = true; 144 OSL_TRACE("Testing: %s - FAILED", msg); 145 } 146 } 147 148 //---------------------------------------------------------------------------------- 149 150 bool rangeCheck( const rendering::RGBColor& rColor ) 151 { 152 return rColor.Red < 0.0 || rColor.Red > 1.0 || 153 rColor.Green < 0.0 || rColor.Green > 1.0 || 154 rColor.Blue < 0.0 || rColor.Blue > 1.0; 155 } 156 157 //---------------------------------------------------------------------------------- 158 159 void checkCanvasBitmap( const rtl::Reference<VclCanvasBitmap>& xBmp, 160 const char* msg, 161 int nOriginalDepth ) 162 { 163 OSL_TRACE("-------------------------"); 164 OSL_TRACE("Testing %s, with depth %d", msg, nOriginalDepth); 165 166 BitmapEx aContainedBmpEx( xBmp->getBitmapEx() ); 167 Bitmap aContainedBmp( aContainedBmpEx.GetBitmap() ); 168 int nDepth = nOriginalDepth; 169 170 { 171 ScopedBitmapReadAccess pAcc( aContainedBmp.AcquireReadAccess(), 172 aContainedBmp ); 173 nDepth = pAcc->GetBitCount(); 174 } 175 176 test( aContainedBmp.GetSizePixel() == Size(200,200), 177 "Original bitmap size" ); 178 179 test( xBmp->getSize().Width == 200 && xBmp->getSize().Height == 200, 180 "Original bitmap size via API" ); 181 182 test( xBmp->hasAlpha() == aContainedBmpEx.IsTransparent(), 183 "Correct alpha state" ); 184 185 test( xBmp->getScaledBitmap( geometry::RealSize2D(500,500), sal_False ).is(), 186 "getScaledBitmap()" ); 187 188 rendering::IntegerBitmapLayout aLayout; 189 uno::Sequence<sal_Int8> aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,1,1)); 190 191 const sal_Int32 nExpectedBitsPerPixel( 192 aContainedBmpEx.IsTransparent() ? std::max(8,nDepth)+8 : nDepth); 193 test( aLayout.ScanLines == 1, 194 "# scanlines" ); 195 test( aLayout.ScanLineBytes == (nExpectedBitsPerPixel+7)/8, 196 "# scanline bytes" ); 197 test( aLayout.ScanLineStride == (nExpectedBitsPerPixel+7)/8 || 198 aLayout.ScanLineStride == -(nExpectedBitsPerPixel+7)/8, 199 "# scanline stride" ); 200 test( aLayout.PlaneStride == 0, 201 "# plane stride" ); 202 203 test( aLayout.ColorSpace.is(), 204 "Color space there" ); 205 206 test( aLayout.Palette.is() == (nDepth <= 8), 207 "Palette existance conforms to bitmap" ); 208 209 uno::Sequence<sal_Int8> aPixelData2 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(0,0) ); 210 211 test( aPixelData2.getLength() == aPixelData.getLength(), 212 "getData and getPixel return same amount of data" ); 213 214 aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,200,1)); 215 test( aLayout.ScanLines == 1, 216 "# scanlines" ); 217 test( aLayout.ScanLineBytes == (200*nExpectedBitsPerPixel+7)/8, 218 "# scanline bytes" ); 219 test( aLayout.ScanLineStride == (200*nExpectedBitsPerPixel+7)/8 || 220 aLayout.ScanLineStride == -(200*nExpectedBitsPerPixel+7)/8, 221 "# scanline stride" ); 222 223 uno::Sequence< rendering::RGBColor > aRGBColors = xBmp->convertIntegerToRGB( aPixelData ); 224 uno::Sequence< rendering::ARGBColor > aARGBColors = xBmp->convertIntegerToARGB( aPixelData ); 225 226 const rendering::RGBColor* pRGBStart ( aRGBColors.getConstArray() ); 227 const rendering::RGBColor* pRGBEnd ( aRGBColors.getConstArray()+aRGBColors.getLength() ); 228 const rendering::ARGBColor* pARGBStart( aARGBColors.getConstArray() ); 229 std::pair<const rendering::RGBColor*, 230 const rendering::ARGBColor*> aRes = std::mismatch( pRGBStart, pRGBEnd, pARGBStart ); 231 test( aRes.first == pRGBEnd, 232 "argb and rgb colors are equal" ); 233 234 test( std::find_if(pRGBStart,pRGBEnd,&rangeCheck) == pRGBEnd, 235 "rgb colors are within [0,1] range" ); 236 237 test( pRGBStart[0].Red == 1.0 && pRGBStart[0].Green == 1.0 && pRGBStart[0].Blue == 1.0, 238 "First pixel is white" ); 239 test( pARGBStart[1].Alpha == 1.0, 240 "Second pixel is opaque" ); 241 if( aContainedBmpEx.IsTransparent() ) 242 { 243 test( pARGBStart[0].Alpha == 0.0, 244 "First pixel is fully transparent" ); 245 } 246 247 test( pRGBStart[1].Red == 0.0 && pRGBStart[1].Green == 0.0 && pRGBStart[1].Blue == 0.0, 248 "Second pixel is black" ); 249 250 if( nOriginalDepth > 8 ) 251 { 252 const Color aCol(COL_GREEN); 253 test( pRGBStart[5].Red == vcl::unotools::toDoubleColor(aCol.GetRed()) && 254 pRGBStart[5].Green == vcl::unotools::toDoubleColor(aCol.GetGreen()) && 255 pRGBStart[5].Blue == vcl::unotools::toDoubleColor(aCol.GetBlue()), 256 "Sixth pixel is green" ); 257 } 258 else if( nDepth <= 8 ) 259 { 260 uno::Reference<rendering::XBitmapPalette> xPal = xBmp->getPalette(); 261 test( xPal.is(), 262 "8bit or less: needs palette" ); 263 test( xPal->getNumberOfEntries() == 1L << nOriginalDepth, 264 "Palette has correct entry count" ); 265 uno::Sequence<double> aIndex; 266 test( xPal->setIndex(aIndex,sal_True,0) == sal_False, 267 "Palette is read-only" ); 268 test( xPal->getIndex(aIndex,0), 269 "Palette entry 0 is opaque" ); 270 test( xPal->getColorSpace().is(), 271 "Palette has a valid color space" ); 272 } 273 274 test( pRGBStart[150].Red == 1.0 && pRGBStart[150].Green == 1.0 && pRGBStart[150].Blue == 1.0, 275 "150th pixel is white" ); 276 277 if( nOriginalDepth > 8 ) 278 { 279 const uno::Sequence<sal_Int8> aComponentTags( xBmp->getComponentTags() ); 280 uno::Sequence<rendering::ARGBColor> aARGBColor(1); 281 uno::Sequence<rendering::RGBColor> aRGBColor(1); 282 uno::Sequence<sal_Int8> aPixel3, aPixel4; 283 284 const Color aCol(COL_GREEN); 285 aARGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed()); 286 aARGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen()); 287 aARGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue()); 288 aARGBColor[0].Alpha = 1.0; 289 290 aRGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed()); 291 aRGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen()); 292 aRGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue()); 293 294 aPixel3 = xBmp->convertIntegerFromARGB( aARGBColor ); 295 aPixel4 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(5,0) ); 296 test( aPixel3 == aPixel4, 297 "Green pixel from bitmap matches with manually converted green pixel" ); 298 299 if( !aContainedBmpEx.IsTransparent() ) 300 { 301 aPixel3 = xBmp->convertIntegerFromRGB( aRGBColor ); 302 test( aPixel3 == aPixel4, 303 "Green pixel from bitmap matches with manually RGB-converted green pixel" ); 304 } 305 } 306 } 307 308 //---------------------------------------------------------------------------------- 309 310 void checkBitmapImport( const rtl::Reference<VclCanvasBitmap>& xBmp, 311 const char* msg, 312 int nOriginalDepth ) 313 { 314 OSL_TRACE("-------------------------"); 315 OSL_TRACE("Testing %s, with depth %d", msg, nOriginalDepth); 316 317 BitmapEx aContainedBmpEx( xBmp->getBitmapEx() ); 318 Bitmap aContainedBmp( aContainedBmpEx.GetBitmap() ); 319 int nDepth = nOriginalDepth; 320 321 { 322 ScopedBitmapReadAccess pAcc( aContainedBmp.AcquireReadAccess(), 323 aContainedBmp ); 324 nDepth = pAcc->GetBitCount(); 325 } 326 327 test( aContainedBmp.GetSizePixel() == Size(200,200), 328 "Original bitmap size" ); 329 330 test( xBmp->getSize().Width == 200 && xBmp->getSize().Height == 200, 331 "Original bitmap size via API" ); 332 333 test( xBmp->hasAlpha() == aContainedBmpEx.IsTransparent(), 334 "Correct alpha state" ); 335 336 test( xBmp->getScaledBitmap( geometry::RealSize2D(500,500), sal_False ).is(), 337 "getScaledBitmap()" ); 338 339 rendering::IntegerBitmapLayout aLayout; 340 uno::Sequence<sal_Int8> aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,1,1)); 341 342 const sal_Int32 nExpectedBitsPerPixel( 343 aContainedBmpEx.IsTransparent() ? std::max(8,nDepth)+8 : nDepth); 344 test( aLayout.ScanLines == 1, 345 "# scanlines" ); 346 test( aLayout.ScanLineBytes == (nExpectedBitsPerPixel+7)/8, 347 "# scanline bytes" ); 348 test( aLayout.ScanLineStride == (nExpectedBitsPerPixel+7)/8 || 349 aLayout.ScanLineStride == -(nExpectedBitsPerPixel+7)/8, 350 "# scanline stride" ); 351 test( aLayout.PlaneStride == 0, 352 "# plane stride" ); 353 354 test( aLayout.ColorSpace.is(), 355 "Color space there" ); 356 357 test( aLayout.Palette.is() == (nDepth <= 8), 358 "Palette existance conforms to bitmap" ); 359 360 uno::Sequence<sal_Int8> aPixelData2 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(0,0) ); 361 362 test( aPixelData2.getLength() == aPixelData.getLength(), 363 "getData and getPixel return same amount of data" ); 364 365 aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,200,1)); 366 test( aLayout.ScanLines == 1, 367 "# scanlines" ); 368 test( aLayout.ScanLineBytes == (200*nExpectedBitsPerPixel+7)/8, 369 "# scanline bytes" ); 370 test( aLayout.ScanLineStride == (200*nExpectedBitsPerPixel+7)/8 || 371 aLayout.ScanLineStride == -(200*nExpectedBitsPerPixel+7)/8, 372 "# scanline stride" ); 373 374 uno::Sequence< rendering::RGBColor > aRGBColors = xBmp->convertIntegerToRGB( aPixelData ); 375 uno::Sequence< rendering::ARGBColor > aARGBColors = xBmp->convertIntegerToARGB( aPixelData ); 376 377 const rendering::RGBColor* pRGBStart ( aRGBColors.getConstArray() ); 378 const rendering::RGBColor* pRGBEnd ( aRGBColors.getConstArray()+aRGBColors.getLength() ); 379 const rendering::ARGBColor* pARGBStart( aARGBColors.getConstArray() ); 380 std::pair<const rendering::RGBColor*, 381 const rendering::ARGBColor*> aRes = std::mismatch( pRGBStart, pRGBEnd, pARGBStart ); 382 test( aRes.first == pRGBEnd, 383 "argb and rgb colors are equal" ); 384 385 test( std::find_if(pRGBStart,pRGBEnd,&rangeCheck) == pRGBEnd, 386 "rgb colors are within [0,1] range" ); 387 388 test( pRGBStart[0].Red == 1.0 && pRGBStart[0].Green == 1.0 && pRGBStart[0].Blue == 1.0, 389 "First pixel is white" ); 390 test( pARGBStart[1].Alpha == 1.0, 391 "Second pixel is opaque" ); 392 if( aContainedBmpEx.IsTransparent() ) 393 { 394 test( pARGBStart[0].Alpha == 0.0, 395 "First pixel is fully transparent" ); 396 } 397 398 test( pRGBStart[1].Red == 0.0 && pRGBStart[1].Green == 0.0 && pRGBStart[1].Blue == 0.0, 399 "Second pixel is black" ); 400 401 if( nOriginalDepth > 8 ) 402 { 403 const Color aCol(COL_GREEN); 404 test( pRGBStart[5].Red == vcl::unotools::toDoubleColor(aCol.GetRed()) && 405 pRGBStart[5].Green == vcl::unotools::toDoubleColor(aCol.GetGreen()) && 406 pRGBStart[5].Blue == vcl::unotools::toDoubleColor(aCol.GetBlue()), 407 "Sixth pixel is green" ); 408 } 409 else if( nDepth <= 8 ) 410 { 411 uno::Reference<rendering::XBitmapPalette> xPal = xBmp->getPalette(); 412 test( xPal.is(), 413 "8bit or less: needs palette" ); 414 test( xPal->getNumberOfEntries() == 1L << nOriginalDepth, 415 "Palette has correct entry count" ); 416 uno::Sequence<double> aIndex; 417 test( xPal->setIndex(aIndex,sal_True,0) == sal_False, 418 "Palette is read-only" ); 419 test( xPal->getIndex(aIndex,0), 420 "Palette entry 0 is opaque" ); 421 test( xPal->getColorSpace().is(), 422 "Palette has a valid color space" ); 423 } 424 425 test( pRGBStart[150].Red == 1.0 && pRGBStart[150].Green == 1.0 && pRGBStart[150].Blue == 1.0, 426 "150th pixel is white" ); 427 428 if( nOriginalDepth > 8 ) 429 { 430 const uno::Sequence<sal_Int8> aComponentTags( xBmp->getComponentTags() ); 431 uno::Sequence<rendering::ARGBColor> aARGBColor(1); 432 uno::Sequence<rendering::RGBColor> aRGBColor(1); 433 uno::Sequence<sal_Int8> aPixel3, aPixel4; 434 435 const Color aCol(COL_GREEN); 436 aARGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed()); 437 aARGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen()); 438 aARGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue()); 439 aARGBColor[0].Alpha = 1.0; 440 441 aRGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed()); 442 aRGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen()); 443 aRGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue()); 444 445 aPixel3 = xBmp->convertIntegerFromARGB( aARGBColor ); 446 aPixel4 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(5,0) ); 447 test( aPixel3 == aPixel4, 448 "Green pixel from bitmap matches with manually converted green pixel" ); 449 450 if( !aContainedBmpEx.IsTransparent() ) 451 { 452 aPixel3 = xBmp->convertIntegerFromRGB( aRGBColor ); 453 test( aPixel3 == aPixel4, 454 "Green pixel from bitmap matches with manually RGB-converted green pixel" ); 455 } 456 } 457 } 458 459 //---------------------------------------------------------------------------------- 460 461 class TestBitmap : public cppu::WeakImplHelper3< rendering::XIntegerReadOnlyBitmap, 462 rendering::XBitmapPalette, 463 rendering::XIntegerBitmapColorSpace > 464 { 465 private: 466 geometry::IntegerSize2D maSize; 467 uno::Sequence<sal_Int8> maComponentTags; 468 uno::Sequence<sal_Int32> maComponentBitCounts; 469 rendering::IntegerBitmapLayout maLayout; 470 const sal_Int32 mnBitsPerPixel; 471 472 // XBitmap 473 virtual geometry::IntegerSize2D SAL_CALL getSize() throw (uno::RuntimeException) { return maSize; } 474 virtual ::sal_Bool SAL_CALL hasAlpha( ) throw (uno::RuntimeException) { return mnBitsPerPixel != 8; } 475 virtual uno::Reference< rendering::XBitmap > SAL_CALL getScaledBitmap( const geometry::RealSize2D&, 476 sal_Bool ) throw (uno::RuntimeException) { return this; } 477 478 // XIntegerReadOnlyBitmap 479 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getData( rendering::IntegerBitmapLayout& bitmapLayout, 480 const geometry::IntegerRectangle2D& rect ) throw (lang::IndexOutOfBoundsException, 481 rendering::VolatileContentDestroyedException, uno::RuntimeException) 482 { 483 test( rect.X1 >= 0, "X1 within bounds" ); 484 test( rect.Y1 >= 0, "Y1 within bounds" ); 485 test( rect.X2 <= maSize.Width, "X2 within bounds" ); 486 test( rect.Y2 <= maSize.Height, "Y2 within bounds" ); 487 488 bitmapLayout = getMemoryLayout(); 489 490 const sal_Int32 nWidth = rect.X2-rect.X1; 491 const sal_Int32 nHeight = rect.Y2-rect.Y1; 492 const sal_Int32 nScanlineLen = (nWidth * mnBitsPerPixel + 7)/8; 493 uno::Sequence<sal_Int8> aRes( nScanlineLen * nHeight ); 494 sal_Int8* pOut = aRes.getArray(); 495 496 bitmapLayout.ScanLines = nHeight; 497 bitmapLayout.ScanLineBytes = 498 bitmapLayout.ScanLineStride= nScanlineLen; 499 500 if( mnBitsPerPixel == 8 ) 501 { 502 for( sal_Int32 y=0; y<nHeight; ++y ) 503 { 504 for( sal_Int32 x=0; x<nWidth; ++x ) 505 pOut[ y*nScanlineLen + x ] = sal_Int8(x); 506 } 507 } 508 else 509 { 510 for( sal_Int32 y=0; y<nHeight; ++y ) 511 { 512 for( sal_Int32 x=0; x<nWidth; ++x ) 513 { 514 pOut[ y*nScanlineLen + 4*x ] = sal_Int8(rect.X1); 515 pOut[ y*nScanlineLen + 4*x + 1 ] = sal_Int8(rect.Y2); 516 pOut[ y*nScanlineLen + 4*x + 2 ] = sal_Int8(x); 517 pOut[ y*nScanlineLen + 4*x + 3 ] = sal_Int8(rect.Y1); 518 } 519 } 520 } 521 522 return aRes; 523 } 524 525 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getPixel( rendering::IntegerBitmapLayout&, 526 const geometry::IntegerPoint2D& ) throw (lang::IndexOutOfBoundsException, 527 rendering::VolatileContentDestroyedException, uno::RuntimeException) 528 { 529 test(false, "Method not implemented"); 530 return uno::Sequence< sal_Int8 >(); 531 } 532 533 virtual uno::Reference< rendering::XBitmapPalette > SAL_CALL getPalette( ) throw (uno::RuntimeException) 534 { 535 uno::Reference< XBitmapPalette > aRet; 536 if( mnBitsPerPixel == 8 ) 537 aRet.set(this); 538 return aRet; 539 } 540 541 virtual rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout( ) throw (uno::RuntimeException) 542 { 543 rendering::IntegerBitmapLayout aLayout( maLayout ); 544 545 const sal_Int32 nScanlineLen = (maSize.Width * mnBitsPerPixel + 7)/8; 546 547 aLayout.ScanLines = maSize.Height; 548 aLayout.ScanLineBytes = 549 aLayout.ScanLineStride= nScanlineLen; 550 aLayout.Palette = getPalette(); 551 aLayout.ColorSpace.set( this ); 552 553 return aLayout; 554 } 555 556 // XBitmapPalette 557 virtual sal_Int32 SAL_CALL getNumberOfEntries() throw (uno::RuntimeException) 558 { 559 test( getPalette().is(), 560 "Got palette interface call without handing out palette?!" ); 561 562 return 255; 563 } 564 565 virtual ::sal_Bool SAL_CALL getIndex( uno::Sequence< double >& entry, 566 ::sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, 567 uno::RuntimeException) 568 { 569 test( getPalette().is(), 570 "Got palette interface call without handing out palette?!" ); 571 test( nIndex >= 0 && nIndex < 256, 572 "Index out of range" ); 573 entry = colorToStdColorSpaceSequence( 574 Color(UINT8(nIndex), 575 UINT8(nIndex), 576 UINT8(nIndex)) ); 577 578 return sal_True; // no palette transparency here. 579 } 580 581 virtual ::sal_Bool SAL_CALL setIndex( const uno::Sequence< double >&, 582 ::sal_Bool, 583 ::sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, 584 lang::IllegalArgumentException, 585 uno::RuntimeException) 586 { 587 test( getPalette().is(), 588 "Got palette interface call without handing out palette?!" ); 589 test( nIndex >= 0 && nIndex < 256, 590 "Index out of range" ); 591 return sal_False; 592 } 593 594 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>, 595 PaletteColorSpaceHolder> 596 { 597 uno::Reference<rendering::XColorSpace> operator()() 598 { 599 return vcl::unotools::createStandardColorSpace(); 600 } 601 }; 602 603 virtual uno::Reference< rendering::XColorSpace > SAL_CALL getColorSpace( ) throw (uno::RuntimeException) 604 { 605 // this is the method from XBitmapPalette. Return palette color 606 // space here 607 return PaletteColorSpaceHolder::get(); 608 } 609 610 // XIntegerBitmapColorSpace 611 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) 612 { 613 return rendering::ColorSpaceType::RGB; 614 } 615 616 virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) 617 { 618 return maComponentTags; 619 } 620 621 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) 622 { 623 return rendering::RenderingIntent::PERCEPTUAL; 624 } 625 626 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) 627 { 628 test(false, "Method not implemented"); 629 return uno::Sequence< ::beans::PropertyValue >(); 630 } 631 632 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >&, 633 const uno::Reference< rendering::XColorSpace >& ) throw (uno::RuntimeException) 634 { 635 test(false, "Method not implemented"); 636 return uno::Sequence< double >(); 637 } 638 639 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& ) throw (lang::IllegalArgumentException, 640 uno::RuntimeException) 641 { 642 test(false, "Method not implemented"); 643 return uno::Sequence< rendering::RGBColor >(); 644 } 645 646 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& ) throw (lang::IllegalArgumentException, 647 uno::RuntimeException) 648 { 649 test(false, "Method not implemented"); 650 return uno::Sequence< rendering::ARGBColor >(); 651 } 652 653 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& ) throw (lang::IllegalArgumentException, 654 uno::RuntimeException) 655 { 656 test(false, "Method not implemented"); 657 return uno::Sequence< rendering::ARGBColor >(); 658 } 659 660 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& ) throw (lang::IllegalArgumentException, 661 uno::RuntimeException) 662 { 663 test(false, "Method not implemented"); 664 return uno::Sequence< double >(); 665 } 666 667 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException, 668 uno::RuntimeException) 669 { 670 test(false, "This method is not expected to be called!"); 671 return uno::Sequence< double >(); 672 } 673 674 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException, 675 uno::RuntimeException) 676 { 677 test(false, "This method is not expected to be called!"); 678 return uno::Sequence< double >(); 679 } 680 681 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException) 682 { 683 return mnBitsPerPixel; 684 } 685 686 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException) 687 { 688 return maComponentBitCounts; 689 } 690 691 virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException) 692 { 693 return util::Endianness::LITTLE; 694 } 695 696 virtual uno::Sequence< double > SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& , 697 const uno::Reference< rendering::XColorSpace >& ) throw (lang::IllegalArgumentException, 698 uno::RuntimeException) 699 { 700 test(false, "Method not implemented"); 701 return uno::Sequence< double >(); 702 } 703 704 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& , 705 const uno::Reference< rendering::XIntegerBitmapColorSpace >& ) throw (lang::IllegalArgumentException, 706 uno::RuntimeException) 707 { 708 test(false, "Method not implemented"); 709 return uno::Sequence< sal_Int8 >(); 710 } 711 712 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, 713 uno::RuntimeException) 714 { 715 const uno::Sequence< rendering::ARGBColor > aTemp( convertIntegerToARGB(deviceColor) ); 716 const sal_Size nLen(aTemp.getLength()); 717 uno::Sequence< rendering::RGBColor > aRes( nLen ); 718 rendering::RGBColor* pOut = aRes.getArray(); 719 for( sal_Size i=0; i<nLen; ++i ) 720 { 721 *pOut++ = rendering::RGBColor(aTemp[i].Red, 722 aTemp[i].Green, 723 aTemp[i].Blue); 724 } 725 726 return aRes; 727 } 728 729 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, 730 uno::RuntimeException) 731 { 732 const sal_Size nLen( deviceColor.getLength() ); 733 const sal_Int32 nBytesPerPixel(mnBitsPerPixel == 8 ? 1 : 4); 734 test(nLen%nBytesPerPixel==0, 735 "number of channels no multiple of pixel element count"); 736 737 uno::Sequence< rendering::ARGBColor > aRes( nLen / nBytesPerPixel ); 738 rendering::ARGBColor* pOut( aRes.getArray() ); 739 740 if( getPalette().is() ) 741 { 742 for( sal_Size i=0; i<nLen; ++i ) 743 { 744 *pOut++ = rendering::ARGBColor( 745 1.0, 746 vcl::unotools::toDoubleColor(deviceColor[i]), 747 vcl::unotools::toDoubleColor(deviceColor[i]), 748 vcl::unotools::toDoubleColor(deviceColor[i])); 749 } 750 } 751 else 752 { 753 for( sal_Size i=0; i<nLen; i+=4 ) 754 { 755 *pOut++ = rendering::ARGBColor( 756 vcl::unotools::toDoubleColor(deviceColor[i+3]), 757 vcl::unotools::toDoubleColor(deviceColor[i+0]), 758 vcl::unotools::toDoubleColor(deviceColor[i+1]), 759 vcl::unotools::toDoubleColor(deviceColor[i+2])); 760 } 761 } 762 763 return aRes; 764 } 765 766 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, 767 uno::RuntimeException) 768 { 769 const sal_Size nLen( deviceColor.getLength() ); 770 const sal_Int32 nBytesPerPixel(mnBitsPerPixel == 8 ? 1 : 4); 771 test(nLen%nBytesPerPixel==0, 772 "number of channels no multiple of pixel element count"); 773 774 uno::Sequence< rendering::ARGBColor > aRes( nLen / nBytesPerPixel ); 775 rendering::ARGBColor* pOut( aRes.getArray() ); 776 777 if( getPalette().is() ) 778 { 779 for( sal_Size i=0; i<nLen; ++i ) 780 { 781 *pOut++ = rendering::ARGBColor( 782 1.0, 783 vcl::unotools::toDoubleColor(deviceColor[i]), 784 vcl::unotools::toDoubleColor(deviceColor[i]), 785 vcl::unotools::toDoubleColor(deviceColor[i])); 786 } 787 } 788 else 789 { 790 for( sal_Size i=0; i<nLen; i+=4 ) 791 { 792 const double fAlpha=vcl::unotools::toDoubleColor(deviceColor[i+3]); 793 *pOut++ = rendering::ARGBColor( 794 fAlpha, 795 fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+0]), 796 fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+1]), 797 fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+2])); 798 } 799 } 800 801 return aRes; 802 } 803 804 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& ) throw (lang::IllegalArgumentException, 805 uno::RuntimeException) 806 { 807 test(false, "Method not implemented"); 808 return uno::Sequence< sal_Int8 >(); 809 } 810 811 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException, 812 uno::RuntimeException) 813 { 814 test(false, "Method not implemented"); 815 return uno::Sequence< sal_Int8 >(); 816 } 817 818 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException, 819 uno::RuntimeException) 820 { 821 test(false, "Method not implemented"); 822 return uno::Sequence< sal_Int8 >(); 823 } 824 825 public: 826 TestBitmap( const geometry::IntegerSize2D& rSize, bool bPalette ) : 827 maSize(rSize), 828 maComponentTags(), 829 maComponentBitCounts(), 830 maLayout(), 831 mnBitsPerPixel( bPalette ? 8 : 32 ) 832 { 833 if( bPalette ) 834 { 835 maComponentTags.realloc(1); 836 maComponentTags[0] = rendering::ColorComponentTag::INDEX; 837 838 maComponentBitCounts.realloc(1); 839 maComponentBitCounts[0] = 8; 840 } 841 else 842 { 843 maComponentTags.realloc(4); 844 sal_Int8* pTags = maComponentTags.getArray(); 845 pTags[0] = rendering::ColorComponentTag::RGB_BLUE; 846 pTags[1] = rendering::ColorComponentTag::RGB_GREEN; 847 pTags[2] = rendering::ColorComponentTag::RGB_RED; 848 pTags[3] = rendering::ColorComponentTag::ALPHA; 849 850 maComponentBitCounts.realloc(4); 851 sal_Int32* pCounts = maComponentBitCounts.getArray(); 852 pCounts[0] = 8; 853 pCounts[1] = 8; 854 pCounts[2] = 8; 855 pCounts[3] = 8; 856 } 857 858 maLayout.ScanLines = 0; 859 maLayout.ScanLineBytes = 0; 860 maLayout.ScanLineStride = 0; 861 maLayout.PlaneStride = 0; 862 maLayout.ColorSpace.clear(); 863 maLayout.Palette.clear(); 864 maLayout.IsMsbFirst = sal_False; 865 } 866 }; 867 868 869 //---------------------------------------------------------------------------------- 870 871 void TestWindow::Paint( const Rectangle& ) 872 { 873 static sal_Int8 lcl_depths[]={1,4,8,16,24}; 874 875 try 876 { 877 // Testing VclCanvasBitmap wrapper 878 // =============================== 879 880 for( unsigned int i=0; i<sizeof(lcl_depths)/sizeof(*lcl_depths); ++i ) 881 { 882 const sal_Int8 nDepth( lcl_depths[i] ); 883 Bitmap aBitmap(Size(200,200),nDepth); 884 aBitmap.Erase(COL_WHITE); 885 { 886 ScopedBitmapWriteAccess pAcc(aBitmap.AcquireWriteAccess(), 887 aBitmap); 888 if( pAcc.get() ) 889 { 890 BitmapColor aBlack(0); 891 BitmapColor aWhite(0); 892 if( pAcc->HasPalette() ) 893 { 894 aBlack.SetIndex( sal::static_int_cast<BYTE>(pAcc->GetBestPaletteIndex(BitmapColor(0,0,0))) ); 895 aWhite.SetIndex( sal::static_int_cast<BYTE>(pAcc->GetBestPaletteIndex(BitmapColor(255,255,255))) ); 896 } 897 else 898 { 899 aBlack = Color(COL_BLACK); 900 aWhite = Color(COL_WHITE); 901 } 902 pAcc->SetFillColor(COL_GREEN); 903 pAcc->FillRect(Rectangle(0,0,100,100)); 904 pAcc->SetPixel(0,0,aWhite); 905 pAcc->SetPixel(0,1,aBlack); 906 pAcc->SetPixel(0,2,aWhite); 907 } 908 } 909 910 rtl::Reference<VclCanvasBitmap> xBmp( new VclCanvasBitmap(aBitmap) ); 911 912 checkCanvasBitmap( xBmp, "single bitmap", nDepth ); 913 914 Bitmap aMask(Size(200,200),1); 915 aMask.Erase(COL_WHITE); 916 { 917 ScopedBitmapWriteAccess pAcc(aMask.AcquireWriteAccess(), 918 aMask); 919 if( pAcc.get() ) 920 { 921 pAcc->SetFillColor(COL_BLACK); 922 pAcc->FillRect(Rectangle(0,0,100,100)); 923 pAcc->SetPixel(0,0,BitmapColor(1)); 924 pAcc->SetPixel(0,1,BitmapColor(0)); 925 pAcc->SetPixel(0,2,BitmapColor(1)); 926 } 927 } 928 929 xBmp.set( new VclCanvasBitmap(BitmapEx(aBitmap,aMask)) ); 930 931 checkCanvasBitmap( xBmp, "masked bitmap", nDepth ); 932 933 AlphaMask aAlpha(Size(200,200)); 934 aAlpha.Erase(255); 935 { 936 BitmapWriteAccess* pAcc = aAlpha.AcquireWriteAccess(); 937 if( pAcc ) 938 { 939 pAcc->SetFillColor(COL_BLACK); 940 pAcc->FillRect(Rectangle(0,0,100,100)); 941 pAcc->SetPixel(0,0,BitmapColor(255)); 942 pAcc->SetPixel(0,1,BitmapColor(0)); 943 pAcc->SetPixel(0,2,BitmapColor(255)); 944 aAlpha.ReleaseAccess(pAcc); 945 } 946 } 947 948 xBmp.set( new VclCanvasBitmap(BitmapEx(aBitmap,aAlpha)) ); 949 950 checkCanvasBitmap( xBmp, "alpha bitmap", nDepth ); 951 } 952 953 // Testing XBitmap import 954 // ====================== 955 uno::Reference< rendering::XIntegerReadOnlyBitmap > xTestBmp( 956 new TestBitmap( geometry::IntegerSize2D(10,10), true )); 957 958 BitmapEx aBmp = vcl::unotools::bitmapExFromXBitmap(xTestBmp); 959 test( aBmp.IsTransparent() == false, 960 "Palette bitmap is not transparent" ); 961 test( aBmp.GetSizePixel() == Size(10,10), 962 "Bitmap has size (10,10)" ); 963 test( aBmp.GetBitCount() == 8, 964 "Bitmap has bitcount of 8" ); 965 { 966 BitmapReadAccess* pBmpAcc = aBmp.GetBitmap().AcquireReadAccess(); 967 968 test( pBmpAcc, 969 "Bitmap has valid BitmapReadAccess" ); 970 971 test(pBmpAcc->GetPixel(0,0) == BitmapColor(0), 972 "(0,0) correct content"); 973 test(pBmpAcc->GetPixel(2,2) == BitmapColor(2), 974 "(2,2) correct content"); 975 test(pBmpAcc->GetPixel(2,9) == BitmapColor(9), 976 "(9,2) correct content"); 977 978 aBmp.GetBitmap().ReleaseAccess(pBmpAcc); 979 } 980 981 xTestBmp.set( new TestBitmap( geometry::IntegerSize2D(10,10), false )); 982 983 aBmp = vcl::unotools::bitmapExFromXBitmap(xTestBmp); 984 test( aBmp.IsTransparent() == TRUE, 985 "Palette bitmap is transparent" ); 986 test( aBmp.IsAlpha() == TRUE, 987 "Palette bitmap has alpha" ); 988 test( aBmp.GetSizePixel() == Size(10,10), 989 "Bitmap has size (10,10)" ); 990 test( aBmp.GetBitCount() == 24, 991 "Bitmap has bitcount of 24" ); 992 { 993 BitmapReadAccess* pBmpAcc = aBmp.GetBitmap().AcquireReadAccess(); 994 BitmapReadAccess* pAlphaAcc = aBmp.GetAlpha().AcquireReadAccess(); 995 996 test( pBmpAcc, 997 "Bitmap has valid BitmapReadAccess" ); 998 test( pAlphaAcc, 999 "Bitmap has valid alpha BitmapReadAccess" ); 1000 1001 test(pBmpAcc->GetPixel(0,0) == BitmapColor(0,1,0), 1002 "(0,0) correct content"); 1003 test(pAlphaAcc->GetPixel(0,0) == BitmapColor(255), 1004 "(0,0) correct alpha content"); 1005 test(pBmpAcc->GetPixel(2,2) == BitmapColor(0,3,2), 1006 "(2,2) correct content"); 1007 test(pAlphaAcc->GetPixel(2,2) == BitmapColor(253), 1008 "(2,2) correct alpha content"); 1009 test(pBmpAcc->GetPixel(2,9) == BitmapColor(0,3,9), 1010 "(9,2) correct content"); 1011 test(pAlphaAcc->GetPixel(2,9) == BitmapColor(253), 1012 "(9,2) correct alpha content"); 1013 1014 aBmp.GetAlpha().ReleaseAccess(pAlphaAcc); 1015 aBmp.GetBitmap().ReleaseAccess(pBmpAcc); 1016 } 1017 } 1018 catch( uno::Exception& ) 1019 { 1020 DBG_UNHANDLED_EXCEPTION(); 1021 exit(2); 1022 } 1023 catch( std::exception& ) 1024 { 1025 OSL_TRACE( "Caught std exception!" ); 1026 } 1027 1028 if( g_failure ) 1029 exit(2); 1030 } 1031 1032 } // namespace 1033 1034 void Main() 1035 { 1036 TestWindow aWindow; 1037 aWindow.Execute(); 1038 aWindow.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "VCL - canvasbitmaptest" ) ) ); 1039 1040 Application::Execute(); 1041 } 1042 1043