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