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