1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include <string.h> 32 #include <stdio.h> 33 #include <errno.h> 34 #ifdef FREEBSD 35 #include <sys/types.h> 36 #endif 37 38 #include <osl/endian.h> 39 #include <rtl/memory.h> 40 41 #include <vcl/bitmap.hxx> 42 #include <vcl/salbtype.hxx> 43 44 #include <tools/prex.h> 45 #include "unx/Xproto.h" 46 #include <tools/postx.h> 47 #include <unx/salunx.h> 48 #include <unx/saldata.hxx> 49 #include <unx/saldisp.hxx> 50 #include <unx/salgdi.h> 51 #include <unx/salbmp.h> 52 #include <unx/salinst.h> 53 54 // ----------- 55 // - Defines - 56 // ----------- 57 58 #define SAL_DRAWPIXMAP_MAX_EXT 4096 59 60 // ------------- 61 // - SalBitmap - 62 // ------------- 63 64 SalBitmap* X11SalInstance::CreateSalBitmap() 65 { 66 return new X11SalBitmap(); 67 } 68 69 ImplSalBitmapCache* X11SalBitmap::mpCache = NULL; 70 sal_uLong X11SalBitmap::mnCacheInstCount = 0; 71 72 // ----------------------------------------------------------------------------- 73 74 X11SalBitmap::X11SalBitmap() : 75 mpDIB( NULL ), 76 mpDDB( NULL ) 77 { 78 } 79 80 // ----------------------------------------------------------------------------- 81 82 X11SalBitmap::~X11SalBitmap() 83 { 84 Destroy(); 85 } 86 87 // ----------------------------------------------------------------------------- 88 89 void X11SalBitmap::ImplCreateCache() 90 { 91 if( !mnCacheInstCount++ ) 92 mpCache = new ImplSalBitmapCache; 93 } 94 95 // ----------------------------------------------------------------------------- 96 97 void X11SalBitmap::ImplDestroyCache() 98 { 99 DBG_ASSERT( mnCacheInstCount, "X11SalBitmap::ImplDestroyCache(): underflow" ); 100 101 if( mnCacheInstCount && !--mnCacheInstCount ) 102 delete mpCache, mpCache = NULL; 103 } 104 105 // ----------------------------------------------------------------------------- 106 107 void X11SalBitmap::ImplRemovedFromCache() 108 { 109 if( mpDDB ) 110 delete mpDDB, mpDDB = NULL; 111 } 112 113 // ----------------------------------------------------------------------------- 114 115 BitmapBuffer* X11SalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) 116 { 117 DBG_ASSERT( nBitCount == 1 || nBitCount == 4 || nBitCount == 8 || nBitCount == 16 || nBitCount == 24, "Unsupported BitCount!" ); 118 119 BitmapBuffer* pDIB = NULL; 120 121 if( rSize.Width() && rSize.Height() ) 122 { 123 try 124 { 125 pDIB = new BitmapBuffer; 126 } 127 catch( std::bad_alloc& ) 128 { 129 pDIB = NULL; 130 } 131 132 if( pDIB ) 133 { 134 const sal_uInt16 nColors = ( nBitCount <= 8 ) ? ( 1 << nBitCount ) : 0; 135 136 pDIB->mnFormat = BMP_FORMAT_BOTTOM_UP; 137 138 switch( nBitCount ) 139 { 140 case( 1 ): pDIB->mnFormat |= BMP_FORMAT_1BIT_MSB_PAL; break; 141 case( 4 ): pDIB->mnFormat |= BMP_FORMAT_4BIT_MSN_PAL; break; 142 case( 8 ): pDIB->mnFormat |= BMP_FORMAT_8BIT_PAL; break; 143 #ifdef OSL_BIGENDIAN 144 case(16 ): 145 pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_MSB_MASK; 146 pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f ); 147 break; 148 #else 149 case(16 ): 150 pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_LSB_MASK; 151 pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f ); 152 break; 153 #endif 154 default: 155 nBitCount = 24; 156 //fall through 157 case 24: 158 pDIB->mnFormat |= BMP_FORMAT_24BIT_TC_BGR; 159 break; 160 } 161 162 pDIB->mnWidth = rSize.Width(); 163 pDIB->mnHeight = rSize.Height(); 164 pDIB->mnScanlineSize = AlignedWidth4Bytes( pDIB->mnWidth * nBitCount ); 165 pDIB->mnBitCount = nBitCount; 166 167 if( nColors ) 168 { 169 pDIB->maPalette = rPal; 170 pDIB->maPalette.SetEntryCount( nColors ); 171 } 172 173 try 174 { 175 pDIB->mpBits = new sal_uInt8[ pDIB->mnScanlineSize * pDIB->mnHeight ]; 176 } 177 catch(std::bad_alloc&) 178 { 179 delete pDIB; 180 pDIB = NULL; 181 } 182 } 183 } 184 else 185 pDIB = NULL; 186 187 return pDIB; 188 } 189 190 // ----------------------------------------------------------------------------- 191 192 BitmapBuffer* X11SalBitmap::ImplCreateDIB( Drawable aDrawable, 193 int nScreen, 194 long nDrawableDepth, 195 long nX, long nY, 196 long nWidth, long nHeight ) 197 { 198 BitmapBuffer* pDIB = NULL; 199 200 if( aDrawable && nWidth && nHeight && nDrawableDepth ) 201 { 202 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 203 SalXLib* pXLib = pSalDisp->GetXLib(); 204 Display* pXDisp = pSalDisp->GetDisplay(); 205 206 // do not die on XError here 207 // alternatively one could check the coordinates for being offscreen 208 // but this call can actually work on servers with backing store 209 // defaults even if the rectangle is offscreen 210 // so better catch the XError 211 pXLib->PushXErrorLevel( true ); 212 XImage* pImage = XGetImage( pXDisp, aDrawable, nX, nY, nWidth, nHeight, AllPlanes, ZPixmap ); 213 bool bWasError = pXLib->HasXErrorOccured() && pXLib->GetLastXErrorRequestCode() == X_GetImage; 214 pXLib->PopXErrorLevel(); 215 216 if( ! bWasError && pImage && pImage->data ) 217 { 218 const SalTwoRect aTwoRect = { 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight }; 219 BitmapBuffer aSrcBuf; 220 sal_uLong nDstFormat = BMP_FORMAT_BOTTOM_UP; 221 const BitmapPalette* pDstPal = NULL; 222 223 aSrcBuf.mnFormat = BMP_FORMAT_TOP_DOWN; 224 aSrcBuf.mnWidth = nWidth; 225 aSrcBuf.mnHeight = nHeight; 226 aSrcBuf.mnBitCount = pImage->bits_per_pixel; 227 aSrcBuf.mnScanlineSize = pImage->bytes_per_line; 228 aSrcBuf.mpBits = (sal_uInt8*) pImage->data; 229 230 pImage->red_mask = pSalDisp->GetVisual( nScreen ).red_mask; 231 pImage->green_mask = pSalDisp->GetVisual( nScreen ).green_mask; 232 pImage->blue_mask = pSalDisp->GetVisual( nScreen ).blue_mask; 233 234 switch( aSrcBuf.mnBitCount ) 235 { 236 case( 1 ): 237 { 238 aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_1BIT_LSB_PAL : BMP_FORMAT_1BIT_MSB_PAL ); 239 nDstFormat |= BMP_FORMAT_1BIT_MSB_PAL; 240 } 241 break; 242 243 case( 4 ): 244 { 245 aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_4BIT_LSN_PAL : BMP_FORMAT_4BIT_MSN_PAL ); 246 nDstFormat |= BMP_FORMAT_4BIT_MSN_PAL; 247 } 248 break; 249 250 case( 8 ): 251 { 252 aSrcBuf.mnFormat |= BMP_FORMAT_8BIT_PAL; 253 nDstFormat |= BMP_FORMAT_8BIT_PAL; 254 } 255 break; 256 257 case( 16 ): 258 { 259 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; 260 aSrcBuf.maColorMask = ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask ); 261 262 if( LSBFirst == pImage->byte_order ) 263 { 264 aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK; 265 } 266 else 267 { 268 aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK; 269 // aSrcBuf.maColorMask = ColorMask( pImage->red_mask ), SWAPSHORT( pImage->green_mask ), SWAPSHORT( pImage->blue_mask ) ); 270 } 271 } 272 break; 273 274 case( 24 ): 275 { 276 if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) ) 277 aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_RGB; 278 else 279 aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_BGR; 280 281 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; 282 } 283 break; 284 285 case( 32 ): 286 { 287 if( LSBFirst == pImage->byte_order ) 288 aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_RGBA : BMP_FORMAT_32BIT_TC_BGRA ); 289 else 290 aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_ABGR : BMP_FORMAT_32BIT_TC_ARGB ); 291 292 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; 293 } 294 break; 295 } 296 297 BitmapPalette& rPal = aSrcBuf.maPalette; 298 299 if( aSrcBuf.mnBitCount == 1 ) 300 { 301 rPal.SetEntryCount( 2 ); 302 pDstPal = &rPal; 303 304 rPal[ 0 ] = Color( COL_BLACK ); 305 rPal[ 1 ] = Color( COL_WHITE ); 306 } 307 else if( aSrcBuf.mnBitCount <= 8 ) 308 { 309 const SalColormap& rColMap = pSalDisp->GetColormap( nScreen ); 310 const sal_uInt16 nCols = Min( (sal_uLong)rColMap.GetUsed(), (sal_uLong)(1 << nDrawableDepth) ); 311 312 rPal.SetEntryCount( nCols ); 313 pDstPal = &rPal; 314 315 for( sal_uInt16 i = 0; i < nCols; i++ ) 316 { 317 const SalColor nColor( rColMap.GetColor( i ) ); 318 BitmapColor& rBmpCol = rPal[ i ]; 319 320 rBmpCol.SetRed( SALCOLOR_RED( nColor ) ); 321 rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) ); 322 rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) ); 323 } 324 } 325 326 nDstFormat = aSrcBuf.mnFormat; 327 pDIB = StretchAndConvert( aSrcBuf, aTwoRect, nDstFormat, 328 const_cast<BitmapPalette*>(pDstPal), &aSrcBuf.maColorMask ); 329 XDestroyImage( pImage ); 330 } 331 } 332 333 return pDIB; 334 } 335 336 // ----------------------------------------------------------------------------- 337 338 XImage* X11SalBitmap::ImplCreateXImage( SalDisplay *pSalDisp, int nScreen, long nDepth, const SalTwoRect& rTwoRect ) const 339 { 340 XImage* pImage = NULL; 341 342 if( !mpDIB && mpDDB ) 343 { 344 const_cast<X11SalBitmap*>(this)->mpDIB = 345 ImplCreateDIB( mpDDB->ImplGetPixmap(), 346 mpDDB->ImplGetScreen(), 347 mpDDB->ImplGetDepth(), 348 0, 0, 349 mpDDB->ImplGetWidth(), 350 mpDDB->ImplGetHeight() ); 351 } 352 353 if( mpDIB && mpDIB->mnWidth && mpDIB->mnHeight ) 354 { 355 Display* pXDisp = pSalDisp->GetDisplay(); 356 long nWidth = rTwoRect.mnDestWidth; 357 long nHeight = rTwoRect.mnDestHeight; 358 359 if( 1 == GetBitCount() ) 360 nDepth = 1; 361 362 pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(), 363 nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, NULL, 364 nWidth, nHeight, 32, 0 ); 365 366 if( pImage ) 367 { 368 BitmapBuffer* pDstBuf; 369 sal_uLong nDstFormat = BMP_FORMAT_TOP_DOWN; 370 BitmapPalette* pPal = NULL; 371 ColorMask* pMask = NULL; 372 373 switch( pImage->bits_per_pixel ) 374 { 375 case( 1 ): 376 nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_1BIT_LSB_PAL : BMP_FORMAT_1BIT_MSB_PAL ); 377 break; 378 379 case( 4 ): 380 nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_4BIT_LSN_PAL : BMP_FORMAT_4BIT_MSN_PAL ); 381 break; 382 383 case( 8 ): 384 nDstFormat |= BMP_FORMAT_8BIT_PAL; 385 break; 386 387 case( 16 ): 388 { 389 #ifdef OSL_BIGENDIAN 390 391 if( MSBFirst == pImage->byte_order ) 392 nDstFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK; 393 else 394 nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK; 395 396 #else /* OSL_LITENDIAN */ 397 398 nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK; 399 if( MSBFirst == pImage->byte_order ) 400 pImage->byte_order = LSBFirst; 401 402 #endif 403 404 pMask = new ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask ); 405 } 406 break; 407 408 case( 24 ): 409 { 410 if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) ) 411 nDstFormat |= BMP_FORMAT_24BIT_TC_RGB; 412 else 413 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; 414 } 415 break; 416 417 case( 32 ): 418 { 419 if( LSBFirst == pImage->byte_order ) 420 nDstFormat |= ( pImage->red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_RGBA : BMP_FORMAT_32BIT_TC_BGRA ); 421 else 422 nDstFormat |= ( pImage->red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_ABGR : BMP_FORMAT_32BIT_TC_ARGB ); 423 } 424 break; 425 } 426 427 if( pImage->depth == 1 ) 428 { 429 pPal = new BitmapPalette( 2 ); 430 (*pPal)[ 0 ] = Color( COL_BLACK ); 431 (*pPal)[ 1 ] = Color( COL_WHITE ); 432 } 433 else if( pImage->depth <= 8 ) 434 { 435 const SalColormap& rColMap = pSalDisp->GetColormap( nScreen ); 436 const sal_uInt16 nCols = Min( (sal_uLong)rColMap.GetUsed(), (sal_uLong)(1 << pImage->depth) ); 437 438 pPal = new BitmapPalette( nCols ); 439 440 for( sal_uInt16 i = 0; i < nCols; i++ ) 441 { 442 const SalColor nColor( rColMap.GetColor( i ) ); 443 BitmapColor& rBmpCol = (*pPal)[ i ]; 444 445 rBmpCol.SetRed( SALCOLOR_RED( nColor ) ); 446 rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) ); 447 rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) ); 448 } 449 } 450 451 pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, pPal, pMask ); 452 delete pPal; 453 delete pMask; 454 455 if( pDstBuf && pDstBuf->mpBits ) 456 { 457 // set data in buffer as data member in pImage 458 pImage->data = (char*) pDstBuf->mpBits; 459 460 // destroy buffer; don't destroy allocated data in buffer 461 delete pDstBuf; 462 } 463 else 464 { 465 XDestroyImage( pImage ); 466 pImage = NULL; 467 } 468 } 469 } 470 471 return pImage; 472 } 473 474 // ----------------------------------------------------------------------------- 475 bool X11SalBitmap::ImplCreateFromDrawable( Drawable aDrawable, 476 int nScreen, long nDrawableDepth, 477 long nX, long nY, long nWidth, long nHeight ) 478 { 479 Destroy(); 480 481 if( aDrawable && nWidth && nHeight && nDrawableDepth ) 482 mpDDB = new ImplSalDDB( aDrawable, nScreen, nDrawableDepth, nX, nY, nWidth, nHeight ); 483 484 return( mpDDB != NULL ); 485 } 486 // ----------------------------------------------------------------------------- 487 488 bool 489 X11SalBitmap::SnapShot (Display* pDisplay, XLIB_Window hWindow) 490 { 491 if (hWindow != None) 492 { 493 XWindowAttributes aAttribute; 494 XGetWindowAttributes (pDisplay, hWindow, &aAttribute); 495 if (aAttribute.map_state == IsViewable) 496 { 497 // get coordinates relative to root window 498 XLIB_Window hPetitFleur; 499 int nRootX, nRootY; 500 501 if (XTranslateCoordinates (pDisplay, hWindow, aAttribute.root, 502 0, 0, &nRootX, &nRootY, &hPetitFleur)) 503 { 504 XWindowAttributes aRootAttribute; 505 XGetWindowAttributes (pDisplay, aAttribute.root, &aRootAttribute); 506 507 int width = aAttribute.width; 508 int height = aAttribute.height; 509 int x = nRootX; 510 int y = nRootY; 511 512 // horizontal range check 513 if (x < 0) 514 { 515 width = width + x; 516 x = 0; 517 } 518 else 519 if (x > aRootAttribute.width) 520 { 521 width = 0; 522 x = aRootAttribute.width; 523 } 524 else 525 if (x + width > aRootAttribute.width) 526 { 527 width = aRootAttribute.width - x; 528 } 529 530 // vertical range check 531 if (y < 0) 532 { 533 height = height + y; 534 y = 0; 535 } 536 else 537 if (y > aRootAttribute.height) 538 { 539 height = 0; 540 y = aRootAttribute.height; 541 } 542 else 543 if (y + height > aRootAttribute.height) 544 { 545 height = aRootAttribute.height - y; 546 } 547 548 if ((width > 0) && (height > 0)) 549 { 550 XImage* pImage = XGetImage( pDisplay, aAttribute.root, 551 x, y, width, height, AllPlanes, ZPixmap ); 552 bool bSnapShot = ImplCreateFromXImage( pDisplay, 553 aAttribute.root, 554 XScreenNumberOfScreen( aAttribute.screen ), 555 pImage ); 556 XDestroyImage (pImage); 557 558 return bSnapShot; 559 } 560 } 561 } 562 } 563 564 return False; 565 } 566 567 bool 568 X11SalBitmap::ImplCreateFromXImage (Display* pDisplay, XLIB_Window hWindow, int nScreen, XImage* pImage) 569 { 570 Destroy(); 571 572 if (pImage != NULL && pImage->width != 0 && pImage->height != 0 && pImage->depth != 0) 573 { 574 mpDDB = new ImplSalDDB (pDisplay, hWindow, nScreen, pImage); 575 return True; 576 } 577 return False; 578 } 579 580 ImplSalDDB* X11SalBitmap::ImplGetDDB( Drawable aDrawable, 581 int nScreen, 582 long nDrawableDepth, 583 const SalTwoRect& rTwoRect ) const 584 { 585 if( !mpDDB || !mpDDB->ImplMatches( nScreen, nDrawableDepth, rTwoRect ) ) 586 { 587 if( mpDDB ) 588 { 589 // do we already have a DIB? if not, create aDIB from current DDB first 590 if( !mpDIB ) 591 { 592 const_cast<X11SalBitmap*>(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(), 593 mpDDB->ImplGetScreen(), 594 mpDDB->ImplGetDepth(), 595 0, 0, 596 mpDDB->ImplGetWidth(), 597 mpDDB->ImplGetHeight() ); 598 } 599 600 delete mpDDB, const_cast<X11SalBitmap*>(this)->mpDDB = NULL; 601 } 602 603 if( mpCache ) 604 mpCache->ImplRemove( const_cast<X11SalBitmap*>(this) ); 605 606 SalTwoRect aTwoRect( rTwoRect ); 607 if( aTwoRect.mnSrcX < 0 ) 608 { 609 aTwoRect.mnSrcWidth += aTwoRect.mnSrcX; 610 aTwoRect.mnSrcX = 0; 611 } 612 if( aTwoRect.mnSrcY < 0 ) 613 { 614 aTwoRect.mnSrcHeight += aTwoRect.mnSrcY; 615 aTwoRect.mnSrcY = 0; 616 } 617 618 // create new DDB from DIB 619 const Size aSize( GetSize() ); 620 if( aTwoRect.mnSrcWidth == aTwoRect.mnDestWidth && 621 aTwoRect.mnSrcHeight == aTwoRect.mnDestHeight ) 622 { 623 aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0; 624 aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width(); 625 aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height(); 626 } 627 else if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() || 628 aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() ) 629 { 630 // #i47823# this should not happen at all, but does nonetheless 631 // because BitmapEx allows for mask bitmaps of different size 632 // than image bitmap (broken) 633 if( aTwoRect.mnSrcX >= aSize.Width() || 634 aTwoRect.mnSrcY >= aSize.Height() ) 635 return NULL; // this would be a really mad case 636 637 if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() ) 638 { 639 aTwoRect.mnSrcWidth = aSize.Width()-aTwoRect.mnSrcX; 640 if( aTwoRect.mnSrcWidth < 1 ) 641 { 642 aTwoRect.mnSrcX = 0; 643 aTwoRect.mnSrcWidth = aSize.Width(); 644 } 645 } 646 if( aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() ) 647 { 648 aTwoRect.mnSrcHeight = aSize.Height() - aTwoRect.mnSrcY; 649 if( aTwoRect.mnSrcHeight < 1 ) 650 { 651 aTwoRect.mnSrcY = 0; 652 aTwoRect.mnSrcHeight = aSize.Height(); 653 } 654 } 655 } 656 657 XImage* pImage = ImplCreateXImage( GetX11SalData()->GetDisplay(), nScreen, 658 nDrawableDepth, aTwoRect ); 659 660 if( pImage ) 661 { 662 const_cast<X11SalBitmap*>(this)->mpDDB = new ImplSalDDB( pImage, aDrawable, nScreen, aTwoRect ); 663 delete[] pImage->data, pImage->data = NULL; 664 XDestroyImage( pImage ); 665 666 if( mpCache ) 667 mpCache->ImplAdd( const_cast<X11SalBitmap*>(this), mpDDB->ImplGetMemSize() ); 668 } 669 } 670 671 return mpDDB; 672 } 673 674 // ----------------------------------------------------------------------------- 675 676 void X11SalBitmap::ImplDraw( Drawable aDrawable, 677 int nScreen, 678 long nDrawableDepth, 679 const SalTwoRect& rTwoRect, 680 const GC& rGC ) const 681 { 682 ImplGetDDB( aDrawable, nScreen, nDrawableDepth, rTwoRect ); 683 if( mpDDB ) 684 mpDDB->ImplDraw( aDrawable, nDrawableDepth, rTwoRect, rGC ); 685 } 686 687 // ----------------------------------------------------------------------------- 688 689 bool X11SalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) 690 { 691 Destroy(); 692 mpDIB = ImplCreateDIB( rSize, nBitCount, rPal ); 693 694 return( mpDIB != NULL ); 695 } 696 697 // ----------------------------------------------------------------------------- 698 699 bool X11SalBitmap::Create( const SalBitmap& rSSalBmp ) 700 { 701 Destroy(); 702 703 const X11SalBitmap& rSalBmp = static_cast<const X11SalBitmap&>( rSSalBmp ); 704 705 if( rSalBmp.mpDIB ) 706 { 707 // TODO: reference counting... 708 mpDIB = new BitmapBuffer( *rSalBmp.mpDIB ); 709 // TODO: get rid of this when BitmapBuffer gets copy constructor 710 try 711 { 712 mpDIB->mpBits = new sal_uInt8[ mpDIB->mnScanlineSize * mpDIB->mnHeight ]; 713 } 714 catch( std::bad_alloc& ) 715 { 716 delete mpDIB; 717 mpDIB = NULL; 718 } 719 720 if( mpDIB ) 721 memcpy( mpDIB->mpBits, rSalBmp.mpDIB->mpBits, mpDIB->mnScanlineSize * mpDIB->mnHeight ); 722 } 723 else if( rSalBmp.mpDDB ) 724 ImplCreateFromDrawable( rSalBmp.mpDDB->ImplGetPixmap(), 725 rSalBmp.mpDDB->ImplGetScreen(), 726 rSalBmp.mpDDB->ImplGetDepth(), 727 0, 0, rSalBmp.mpDDB->ImplGetWidth(), rSalBmp.mpDDB->ImplGetHeight() ); 728 729 return( ( !rSalBmp.mpDIB && !rSalBmp.mpDDB ) || 730 ( rSalBmp.mpDIB && ( mpDIB != NULL ) ) || 731 ( rSalBmp.mpDDB && ( mpDDB != NULL ) ) ); 732 } 733 734 // ----------------------------------------------------------------------------- 735 736 bool X11SalBitmap::Create( const SalBitmap&, SalGraphics* ) 737 { 738 return sal_False; 739 } 740 741 // ----------------------------------------------------------------------------- 742 743 bool X11SalBitmap::Create( const SalBitmap&, sal_uInt16 ) 744 { 745 return sal_False; 746 } 747 748 // ----------------------------------------------------------------------------- 749 750 void X11SalBitmap::Destroy() 751 { 752 if( mpDIB ) 753 { 754 delete[] mpDIB->mpBits; 755 delete mpDIB, mpDIB = NULL; 756 } 757 758 if( mpDDB ) 759 delete mpDDB, mpDDB = NULL; 760 761 if( mpCache ) 762 mpCache->ImplRemove( this ); 763 } 764 765 // ----------------------------------------------------------------------------- 766 767 Size X11SalBitmap::GetSize() const 768 { 769 Size aSize; 770 771 if( mpDIB ) 772 aSize.Width() = mpDIB->mnWidth, aSize.Height() = mpDIB->mnHeight; 773 else if( mpDDB ) 774 aSize.Width() = mpDDB->ImplGetWidth(), aSize.Height() = mpDDB->ImplGetHeight(); 775 776 return aSize; 777 } 778 779 // ----------------------------------------------------------------------------- 780 781 sal_uInt16 X11SalBitmap::GetBitCount() const 782 { 783 sal_uInt16 nBitCount; 784 785 if( mpDIB ) 786 nBitCount = mpDIB->mnBitCount; 787 else if( mpDDB ) 788 nBitCount = mpDDB->ImplGetDepth(); 789 else 790 nBitCount = 0; 791 792 return nBitCount; 793 } 794 795 // ----------------------------------------------------------------------------- 796 797 BitmapBuffer* X11SalBitmap::AcquireBuffer( bool ) 798 { 799 if( !mpDIB && mpDDB ) 800 { 801 mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(), 802 mpDDB->ImplGetScreen(), 803 mpDDB->ImplGetDepth(), 804 0, 0, mpDDB->ImplGetWidth(), mpDDB->ImplGetHeight() ); 805 } 806 807 return mpDIB; 808 } 809 810 // ----------------------------------------------------------------------------- 811 812 void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, bool bReadOnly ) 813 { 814 if( !bReadOnly ) 815 { 816 if( mpDDB ) 817 delete mpDDB, mpDDB = NULL; 818 819 if( mpCache ) 820 mpCache->ImplRemove( this ); 821 } 822 } 823 824 // ----------------------------------------------------------------------------- 825 826 bool X11SalBitmap::GetSystemData( BitmapSystemData& rData ) 827 { 828 if( mpDDB ) 829 { 830 // Rename/retype pDummy to your likings (though X11 Pixmap is 831 // prolly not a good idea, since it's accessed from 832 // non-platform aware code in vcl/bitmap.hxx) 833 rData.aPixmap = (void*)mpDDB->ImplGetPixmap(); 834 rData.mnWidth = mpDDB->ImplGetWidth (); 835 rData.mnHeight = mpDDB->ImplGetHeight (); 836 return true; 837 } 838 839 return false; 840 } 841 842 // -------------- 843 // - ImplSalDDB - 844 // -------------- 845 846 ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable, int nScreen, const SalTwoRect& rTwoRect ) : 847 maPixmap ( 0 ), 848 maTwoRect ( rTwoRect ), 849 mnDepth ( pImage->depth ), 850 mnScreen ( nScreen ) 851 { 852 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 853 Display* pXDisp = pSalDisp->GetDisplay(); 854 855 if( (maPixmap = XCreatePixmap( pXDisp, aDrawable, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() )) ) 856 { 857 XGCValues aValues; 858 GC aGC; 859 int nValues = GCFunction; 860 861 aValues.function = GXcopy; 862 863 if( 1 == mnDepth ) 864 { 865 nValues |= ( GCForeground | GCBackground ); 866 aValues.foreground = 1, aValues.background = 0; 867 } 868 869 aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues ); 870 XPutImage( pXDisp, maPixmap, aGC, pImage, 0, 0, 0, 0, maTwoRect.mnDestWidth, maTwoRect.mnDestHeight ); 871 XFreeGC( pXDisp, aGC ); 872 } 873 } 874 875 // ----------------------------------------------------------------------------------------- 876 // create from XImage 877 878 ImplSalDDB::ImplSalDDB (Display* pDisplay, XLIB_Window hWindow, int nScreen, XImage* pImage) : 879 mnScreen( nScreen ) 880 { 881 maPixmap = XCreatePixmap (pDisplay, hWindow, pImage->width, pImage->height, pImage->depth); 882 if (maPixmap != 0) 883 { 884 XGCValues aValues; 885 GC aGC; 886 int nValues = GCFunction; 887 888 aValues.function = GXcopy; 889 890 if (pImage->depth == 1) 891 { 892 nValues |= ( GCForeground | GCBackground ); 893 aValues.foreground = 1; 894 aValues.background = 0; 895 } 896 897 aGC = XCreateGC (pDisplay, maPixmap, nValues, &aValues); 898 XPutImage (pDisplay, maPixmap, aGC, pImage, 0, 0, 0, 0, pImage->width, pImage->height); 899 XFreeGC (pDisplay, aGC); 900 901 maTwoRect.mnSrcX = 0; 902 maTwoRect.mnSrcY = 0; 903 maTwoRect.mnDestX = 0; 904 maTwoRect.mnDestY = 0; 905 maTwoRect.mnSrcWidth = pImage->width; 906 maTwoRect.mnDestWidth = pImage->width; 907 maTwoRect.mnSrcHeight = pImage->height; 908 maTwoRect.mnDestHeight = pImage->height; 909 910 mnDepth = pImage->depth; 911 } 912 } 913 914 // ----------------------------------------------------------------------------- 915 916 ImplSalDDB::ImplSalDDB( Drawable aDrawable, int nScreen, long nDrawableDepth, long nX, long nY, long nWidth, long nHeight ) : 917 mnDepth( nDrawableDepth ), 918 mnScreen( nScreen ) 919 { 920 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 921 Display* pXDisp = pSalDisp->GetDisplay(); 922 923 if( (maPixmap = XCreatePixmap( pXDisp, aDrawable, nWidth, nHeight, nDrawableDepth )) ) 924 { 925 XGCValues aValues; 926 GC aGC; 927 int nValues = GCFunction; 928 929 aValues.function = GXcopy; 930 931 if( 1 == mnDepth ) 932 { 933 nValues |= ( GCForeground | GCBackground ); 934 aValues.foreground = 1, aValues.background = 0; 935 } 936 937 aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues ); 938 ImplDraw( aDrawable, nDrawableDepth, maPixmap, mnDepth, 939 nX, nY, nWidth, nHeight, 0, 0, aGC ); 940 XFreeGC( pXDisp, aGC ); 941 942 maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0; 943 maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = nWidth; 944 maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = nHeight; 945 } 946 } 947 948 // ----------------------------------------------------------------------------- 949 950 ImplSalDDB::~ImplSalDDB() 951 { 952 if( maPixmap && ImplGetSVData() ) 953 XFreePixmap( GetX11SalData()->GetDisplay()->GetDisplay(), maPixmap ); 954 } 955 956 // ----------------------------------------------------------------------------- 957 958 bool ImplSalDDB::ImplMatches( int nScreen, long nDepth, const SalTwoRect& rTwoRect ) const 959 { 960 bool bRet = sal_False; 961 962 if( ( maPixmap != 0 ) && ( ( mnDepth == nDepth ) || ( 1 == mnDepth ) ) && nScreen == mnScreen) 963 { 964 if( rTwoRect.mnSrcX == maTwoRect.mnSrcX && rTwoRect.mnSrcY == maTwoRect.mnSrcY && 965 rTwoRect.mnSrcWidth == maTwoRect.mnSrcWidth && rTwoRect.mnSrcHeight == maTwoRect.mnSrcHeight && 966 rTwoRect.mnDestWidth == maTwoRect.mnDestWidth && rTwoRect.mnDestHeight == maTwoRect.mnDestHeight ) 967 { 968 // absolutely indentically 969 bRet = sal_True; 970 } 971 else if( rTwoRect.mnSrcWidth == rTwoRect.mnDestWidth && rTwoRect.mnSrcHeight == rTwoRect.mnDestHeight && 972 maTwoRect.mnSrcWidth == maTwoRect.mnDestWidth && maTwoRect.mnSrcHeight == maTwoRect.mnDestHeight && 973 rTwoRect.mnSrcX >= maTwoRect.mnSrcX && rTwoRect.mnSrcY >= maTwoRect.mnSrcY && 974 ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) <= ( maTwoRect.mnSrcX + maTwoRect.mnSrcWidth ) && 975 ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) <= ( maTwoRect.mnSrcY + maTwoRect.mnSrcHeight ) ) 976 { 977 bRet = sal_True; 978 } 979 } 980 981 return bRet; 982 } 983 984 // ----------------------------------------------------------------------------- 985 986 void ImplSalDDB::ImplDraw( Drawable aDrawable, long nDrawableDepth, const SalTwoRect& rTwoRect, const GC& rGC ) const 987 { 988 ImplDraw( maPixmap, mnDepth, aDrawable, nDrawableDepth, 989 rTwoRect.mnSrcX - maTwoRect.mnSrcX, rTwoRect.mnSrcY - maTwoRect.mnSrcY, 990 rTwoRect.mnDestWidth, rTwoRect.mnDestHeight, 991 rTwoRect.mnDestX, rTwoRect.mnDestY, rGC ); 992 } 993 994 // ----------------------------------------------------------------------------- 995 996 void ImplSalDDB::ImplDraw( Drawable aSrcDrawable, long nSrcDrawableDepth, 997 Drawable aDstDrawable, long, 998 long nSrcX, long nSrcY, 999 long nDestWidth, long nDestHeight, 1000 long nDestX, long nDestY, const GC& rGC ) 1001 { 1002 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 1003 Display* pXDisp = pSalDisp->GetDisplay(); 1004 1005 if( 1 == nSrcDrawableDepth ) 1006 { 1007 XCopyPlane( pXDisp, aSrcDrawable, aDstDrawable, rGC, 1008 nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY, 1 ); 1009 } 1010 else 1011 { 1012 XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC, 1013 nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY ); 1014 } 1015 } 1016 1017 // ---------------------- 1018 // - ImplSalBitmapCache - 1019 // ---------------------- 1020 1021 struct ImplBmpObj 1022 { 1023 X11SalBitmap* mpBmp; 1024 sal_uLong mnMemSize; 1025 sal_uLong mnFlags; 1026 1027 ImplBmpObj( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags ) : 1028 mpBmp( pBmp ), mnMemSize( nMemSize ), mnFlags( nFlags ) {} 1029 }; 1030 1031 // ----------------------------------------------------------------------------- 1032 1033 ImplSalBitmapCache::ImplSalBitmapCache() : 1034 mnTotalSize( 0UL ) 1035 { 1036 } 1037 1038 // ----------------------------------------------------------------------------- 1039 1040 ImplSalBitmapCache::~ImplSalBitmapCache() 1041 { 1042 ImplClear(); 1043 } 1044 1045 // ----------------------------------------------------------------------------- 1046 1047 void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags ) 1048 { 1049 ImplBmpObj* pObj; 1050 bool bFound = sal_False; 1051 1052 for( pObj = (ImplBmpObj*) maBmpList.Last(); pObj && !bFound; pObj = (ImplBmpObj*) maBmpList.Prev() ) 1053 if( pObj->mpBmp == pBmp ) 1054 bFound = sal_True; 1055 1056 mnTotalSize += nMemSize; 1057 1058 if( bFound ) 1059 { 1060 mnTotalSize -= pObj->mnMemSize; 1061 pObj->mnMemSize = nMemSize, pObj->mnFlags = nFlags; 1062 } 1063 else 1064 maBmpList.Insert( new ImplBmpObj( pBmp, nMemSize, nFlags ), LIST_APPEND ); 1065 } 1066 1067 // ----------------------------------------------------------------------------- 1068 1069 void ImplSalBitmapCache::ImplRemove( X11SalBitmap* pBmp ) 1070 { 1071 for( ImplBmpObj* pObj = (ImplBmpObj*) maBmpList.Last(); pObj; pObj = (ImplBmpObj*) maBmpList.Prev() ) 1072 { 1073 if( pObj->mpBmp == pBmp ) 1074 { 1075 maBmpList.Remove( pObj ); 1076 pObj->mpBmp->ImplRemovedFromCache(); 1077 mnTotalSize -= pObj->mnMemSize; 1078 delete pObj; 1079 break; 1080 } 1081 } 1082 } 1083 1084 // ----------------------------------------------------------------------------- 1085 1086 void ImplSalBitmapCache::ImplClear() 1087 { 1088 for( ImplBmpObj* pObj = (ImplBmpObj*) maBmpList.First(); pObj; pObj = (ImplBmpObj*) maBmpList.Next() ) 1089 { 1090 pObj->mpBmp->ImplRemovedFromCache(); 1091 delete pObj; 1092 } 1093 1094 maBmpList.Clear(); 1095 mnTotalSize = 0; 1096 } 1097