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 <unistd.h> 28 #include <cstdio> 29 #include <cstring> 30 31 #include <bmp.hxx> 32 33 #include <X11_selection.hxx> 34 35 using namespace x11; 36 using namespace com::sun::star::uno; 37 using namespace com::sun::star::script; 38 using namespace com::sun::star::awt; 39 using namespace rtl; 40 41 /* 42 * helper functions 43 */ 44 45 inline void writeLE( sal_uInt16 nNumber, sal_uInt8* pBuffer ) 46 { 47 pBuffer[ 0 ] = (nNumber & 0xff); 48 pBuffer[ 1 ] = ((nNumber>>8)&0xff); 49 } 50 51 inline void writeLE( sal_uInt32 nNumber, sal_uInt8* pBuffer ) 52 { 53 pBuffer[ 0 ] = (nNumber & 0xff); 54 pBuffer[ 1 ] = ((nNumber>>8)&0xff); 55 pBuffer[ 2 ] = ((nNumber>>16)&0xff); 56 pBuffer[ 3 ] = ((nNumber>>24)&0xff); 57 } 58 59 inline sal_uInt16 readLE16( const sal_uInt8* pBuffer ) 60 { 61 return (((sal_uInt16)pBuffer[1]) << 8 ) | pBuffer[0]; 62 } 63 64 inline sal_uInt16 readLE32( const sal_uInt8* pBuffer ) 65 { 66 return 67 (((sal_uInt32)pBuffer[3]) << 24 ) | 68 (((sal_uInt32)pBuffer[2]) << 16 ) | 69 (((sal_uInt32)pBuffer[1]) << 8 ) | 70 pBuffer[0]; 71 } 72 73 74 /* 75 * BmpTransporter 76 */ 77 78 BmpTransporter::BmpTransporter( const Sequence<sal_Int8>& rBmp ) : 79 m_aBM( rBmp ) 80 { 81 const sal_uInt8* pData = (const sal_uInt8*)rBmp.getConstArray(); 82 83 if( pData[0] == 'B' || pData[1] == 'M' ) 84 { 85 pData = pData+14; 86 m_aSize.Width = readLE32( pData+4 ); 87 m_aSize.Height = readLE32( pData+8 ); 88 } 89 else 90 m_aSize.Width = m_aSize.Height = 0; 91 } 92 93 BmpTransporter::~BmpTransporter() 94 { 95 } 96 97 com::sun::star::awt::Size SAL_CALL BmpTransporter::getSize() throw() 98 { 99 return m_aSize; 100 } 101 102 Sequence< sal_Int8 > SAL_CALL BmpTransporter::getDIB() throw() 103 { 104 return m_aBM; 105 } 106 107 Sequence< sal_Int8 > SAL_CALL BmpTransporter::getMaskDIB() throw() 108 { 109 return Sequence< sal_Int8 >(); 110 } 111 112 /* 113 * scanline helpers 114 */ 115 116 inline void X11_writeScanlinePixel( unsigned long nColor, sal_uInt8* pScanline, int depth, int x ) 117 { 118 switch( depth ) 119 { 120 case 1: 121 pScanline[ x/8 ] &= ~(1 << (x&7)); 122 pScanline[ x/8 ] |= ((nColor & 1) << (x&7)); 123 break; 124 case 4: 125 pScanline[ x/2 ] &= ((x&1) ? 0x0f : 0xf0); 126 pScanline[ x/2 ] |= ((x&1) ? (nColor & 0x0f) : ((nColor & 0x0f) << 4)); 127 break; 128 default: 129 case 8: 130 pScanline[ x ] = (nColor & 0xff); 131 break; 132 } 133 } 134 135 static sal_uInt8* X11_getPaletteBmpFromImage( 136 Display* pDisplay, 137 XImage* pImage, 138 Colormap aColormap, 139 sal_Int32& rOutSize 140 ) 141 { 142 sal_uInt32 nColors = 0; 143 144 rOutSize = 0; 145 146 sal_uInt8* pBuffer = 0; 147 sal_uInt32 nHeaderSize, nScanlineSize; 148 sal_uInt16 nBitCount; 149 // determine header and scanline size 150 switch( pImage->depth ) 151 { 152 case 1: 153 nHeaderSize = 64; 154 nScanlineSize = (pImage->width+31)/32; 155 nBitCount = 1; 156 break; 157 case 4: 158 nHeaderSize = 72; 159 nScanlineSize = (pImage->width+1)/2; 160 nBitCount = 4; 161 break; 162 default: 163 case 8: 164 nHeaderSize = 1084; 165 nScanlineSize = pImage->width; 166 nBitCount = 8; 167 break; 168 } 169 // adjust scan lines to begin on %4 boundaries 170 if( nScanlineSize & 3 ) 171 { 172 nScanlineSize &= 0xfffffffc; 173 nScanlineSize += 4; 174 } 175 176 // allocate buffer to hold header and scanlines, initialize to zero 177 rOutSize = nHeaderSize + nScanlineSize*pImage->height; 178 pBuffer = (sal_uInt8*)rtl_allocateZeroMemory( rOutSize ); 179 for( int y = 0; y < pImage->height; y++ ) 180 { 181 sal_uInt8* pScanline = pBuffer + nHeaderSize + (pImage->height-1-y)*nScanlineSize; 182 for( int x = 0; x < pImage->width; x++ ) 183 { 184 unsigned long nPixel = XGetPixel( pImage, x, y ); 185 if( nPixel >= nColors ) 186 nColors = nPixel+1; 187 X11_writeScanlinePixel( nPixel, pScanline, pImage->depth, x ); 188 } 189 } 190 191 // fill in header fields 192 pBuffer[ 0 ] = 'B'; 193 pBuffer[ 1 ] = 'M'; 194 195 writeLE( nHeaderSize, pBuffer+10 ); 196 writeLE( (sal_uInt32)40, pBuffer+14 ); 197 writeLE( (sal_uInt32)pImage->width, pBuffer+18 ); 198 writeLE( (sal_uInt32)pImage->height, pBuffer+22 ); 199 writeLE( (sal_uInt16)1, pBuffer+26 ); 200 writeLE( nBitCount, pBuffer+28 ); 201 writeLE( (sal_uInt32)(DisplayWidth(pDisplay,DefaultScreen(pDisplay))*1000/DisplayWidthMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+38); 202 writeLE( (sal_uInt32)(DisplayHeight(pDisplay,DefaultScreen(pDisplay))*1000/DisplayHeightMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+42); 203 writeLE( nColors, pBuffer+46 ); 204 writeLE( nColors, pBuffer+50 ); 205 206 XColor aColors[256]; 207 if( nColors > (1U << nBitCount) ) // paranoia 208 nColors = (1U << nBitCount); 209 for( unsigned long nPixel = 0; nPixel < nColors; nPixel++ ) 210 { 211 aColors[nPixel].flags = DoRed | DoGreen | DoBlue; 212 aColors[nPixel].pixel = nPixel; 213 } 214 XQueryColors( pDisplay, aColormap, aColors, nColors ); 215 for( sal_uInt32 i = 0; i < nColors; i++ ) 216 { 217 pBuffer[ 54 + i*4 ] = (sal_uInt8)(aColors[i].blue >> 8); 218 pBuffer[ 55 + i*4 ] = (sal_uInt8)(aColors[i].green >> 8); 219 pBuffer[ 56 + i*4 ] = (sal_uInt8)(aColors[i].red >> 8); 220 } 221 222 // done 223 224 return pBuffer; 225 } 226 227 inline unsigned long doRightShift( unsigned long nValue, int nShift ) 228 { 229 return (nShift > 0) ? (nValue >> nShift) : (nValue << (-nShift)); 230 } 231 232 inline unsigned long doLeftShift( unsigned long nValue, int nShift ) 233 { 234 return (nShift > 0) ? (nValue << nShift) : (nValue >> (-nShift)); 235 } 236 237 static void getShift( unsigned long nMask, int& rShift, int& rSigBits, int& rShift2 ) 238 { 239 unsigned long nUseMask = nMask; 240 rShift = 0; 241 while( nMask & 0xffffff00 ) 242 { 243 rShift++; 244 nMask >>= 1; 245 } 246 if( rShift == 0 ) 247 while( ! (nMask & 0x00000080) ) 248 { 249 rShift--; 250 nMask <<= 1; 251 } 252 253 int nRotate = sizeof(unsigned long)*8 - rShift; 254 rSigBits = 0; 255 nMask = doRightShift( nUseMask, rShift) ; 256 while( nRotate-- ) 257 { 258 if( nMask & 1 ) 259 rSigBits++; 260 nMask >>= 1; 261 } 262 263 rShift2 = 0; 264 if( rSigBits < 8 ) 265 rShift2 = 8-rSigBits; 266 } 267 268 static sal_uInt8* X11_getTCBmpFromImage( 269 Display* pDisplay, 270 XImage* pImage, 271 sal_Int32& rOutSize, 272 int nScreenNo 273 ) 274 { 275 // get masks from visual info (guesswork) 276 XVisualInfo aVInfo; 277 if( ! XMatchVisualInfo( pDisplay, nScreenNo, pImage->depth, TrueColor, &aVInfo ) ) 278 return NULL; 279 280 rOutSize = 0; 281 282 sal_uInt8* pBuffer = 0; 283 sal_uInt32 nHeaderSize = 60; 284 sal_uInt32 nScanlineSize = pImage->width*3; 285 286 // adjust scan lines to begin on %4 boundaries 287 if( nScanlineSize & 3 ) 288 { 289 nScanlineSize &= 0xfffffffc; 290 nScanlineSize += 4; 291 } 292 int nRedShift, nRedSig, nRedShift2 = 0; 293 getShift( aVInfo.red_mask, nRedShift, nRedSig, nRedShift2 ); 294 int nGreenShift, nGreenSig, nGreenShift2 = 0; 295 getShift( aVInfo.green_mask, nGreenShift, nGreenSig, nGreenShift2 ); 296 int nBlueShift, nBlueSig, nBlueShift2 = 0; 297 getShift( aVInfo.blue_mask, nBlueShift, nBlueSig, nBlueShift2 ); 298 299 // allocate buffer to hold header and scanlines, initialize to zero 300 rOutSize = nHeaderSize + nScanlineSize*pImage->height; 301 pBuffer = (sal_uInt8*)rtl_allocateZeroMemory( rOutSize ); 302 for( int y = 0; y < pImage->height; y++ ) 303 { 304 sal_uInt8* pScanline = pBuffer + nHeaderSize + (pImage->height-1-y)*nScanlineSize; 305 for( int x = 0; x < pImage->width; x++ ) 306 { 307 unsigned long nPixel = XGetPixel( pImage, x, y ); 308 309 sal_uInt8 nValue = (sal_uInt8)doRightShift( nPixel&aVInfo.blue_mask, nBlueShift); 310 if( nBlueShift2 ) 311 nValue |= (nValue >> nBlueShift2 ); 312 *pScanline++ = nValue; 313 314 nValue = (sal_uInt8)doRightShift( nPixel&aVInfo.green_mask, nGreenShift); 315 if( nGreenShift2 ) 316 nValue |= (nValue >> nGreenShift2 ); 317 *pScanline++ = nValue; 318 319 nValue = (sal_uInt8)doRightShift( nPixel&aVInfo.red_mask, nRedShift); 320 if( nRedShift2 ) 321 nValue |= (nValue >> nRedShift2 ); 322 *pScanline++ = nValue; 323 } 324 } 325 326 // fill in header fields 327 pBuffer[ 0 ] = 'B'; 328 pBuffer[ 1 ] = 'M'; 329 330 writeLE( nHeaderSize, pBuffer+10 ); 331 writeLE( (sal_uInt32)40, pBuffer+14 ); 332 writeLE( (sal_uInt32)pImage->width, pBuffer+18 ); 333 writeLE( (sal_uInt32)pImage->height, pBuffer+22 ); 334 writeLE( (sal_uInt16)1, pBuffer+26 ); 335 writeLE( (sal_uInt16)24, pBuffer+28 ); 336 writeLE( (sal_uInt32)(DisplayWidth(pDisplay,DefaultScreen(pDisplay))*1000/DisplayWidthMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+38); 337 writeLE( (sal_uInt32)(DisplayHeight(pDisplay,DefaultScreen(pDisplay))*1000/DisplayHeightMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+42); 338 339 // done 340 341 return pBuffer; 342 } 343 344 sal_uInt8* x11::X11_getBmpFromPixmap( 345 Display* pDisplay, 346 Drawable aDrawable, 347 Colormap aColormap, 348 sal_Int32& rOutSize 349 ) 350 { 351 // get geometry of drawable 352 XLIB_Window aRoot; 353 int x,y; 354 unsigned int w, h, bw, d; 355 XGetGeometry( pDisplay, aDrawable, &aRoot, &x, &y, &w, &h, &bw, &d ); 356 357 // find which screen we are on 358 int nScreenNo = ScreenCount( pDisplay ); 359 while( nScreenNo-- ) 360 { 361 if( RootWindow( pDisplay, nScreenNo ) == aRoot ) 362 break; 363 } 364 if( nScreenNo < 0 ) 365 return NULL; 366 367 if( aColormap == None ) 368 aColormap = DefaultColormap( pDisplay, nScreenNo ); 369 370 // get the image 371 XImage* pImage = XGetImage( pDisplay, aDrawable, 0, 0, w, h, AllPlanes, ZPixmap ); 372 if( ! pImage ) 373 return NULL; 374 375 sal_uInt8* pBmp = d <= 8 ? 376 X11_getPaletteBmpFromImage( pDisplay, pImage, aColormap, rOutSize ) : 377 X11_getTCBmpFromImage( pDisplay, pImage, rOutSize, nScreenNo ); 378 XDestroyImage( pImage ); 379 380 return pBmp; 381 } 382 383 void x11::X11_freeBmp( sal_uInt8* pBmp ) 384 { 385 rtl_freeMemory( pBmp ); 386 } 387 388 /* 389 * PixmapHolder 390 */ 391 392 PixmapHolder::PixmapHolder( Display* pDisplay ) : 393 m_pDisplay( pDisplay ), 394 m_aColormap( None ), 395 m_aPixmap( None ), 396 m_aBitmap( None ) 397 { 398 /* try to get a 24 bit true color visual, if that fails, 399 * revert to default visual 400 */ 401 if( ! XMatchVisualInfo( m_pDisplay, DefaultScreen( m_pDisplay ), 24, TrueColor, &m_aInfo ) ) 402 { 403 #if OSL_DEBUG_LEVEL > 1 404 fprintf( stderr, "PixmapHolder reverting to default visual\n" ); 405 #endif 406 Visual* pVisual = DefaultVisual( m_pDisplay, DefaultScreen( m_pDisplay ) ); 407 m_aInfo.screen = DefaultScreen( m_pDisplay ); 408 m_aInfo.visual = pVisual; 409 m_aInfo.visualid = pVisual->visualid; 410 m_aInfo.c_class = pVisual->c_class; 411 m_aInfo.red_mask = pVisual->red_mask; 412 m_aInfo.green_mask = pVisual->green_mask; 413 m_aInfo.blue_mask = pVisual->blue_mask; 414 m_aInfo.depth = DefaultDepth( m_pDisplay, m_aInfo.screen ); 415 } 416 m_aColormap = DefaultColormap( m_pDisplay, m_aInfo.screen ); 417 #if OSL_DEBUG_LEVEL > 1 418 static const char* pClasses[] = 419 { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor" }; 420 fprintf( stderr, "PixmapHolder visual: id = 0x%lx, class = %s (%d), depth=%d; color map = 0x%lx\n", 421 m_aInfo.visualid, 422 (m_aInfo.c_class >= 0 && unsigned(m_aInfo.c_class) < sizeof(pClasses)/sizeof(pClasses[0])) ? pClasses[m_aInfo.c_class] : "<unknown>", 423 m_aInfo.c_class, 424 m_aInfo.depth, 425 m_aColormap ); 426 #endif 427 if( m_aInfo.c_class == TrueColor ) 428 { 429 int nRedSig, nGreenSig, nBlueSig; 430 m_nRedShift = m_nRedShift2 = 0; 431 getShift( m_aInfo.red_mask, m_nRedShift, nRedSig, m_nRedShift2 ); 432 m_nGreenShift = m_nGreenShift2 = 0; 433 getShift( m_aInfo.green_mask, m_nGreenShift, nGreenSig, m_nGreenShift2 ); 434 m_nBlueShift = m_nBlueShift2 = 0; 435 getShift( m_aInfo.blue_mask, m_nBlueShift, nBlueSig, m_nBlueShift2 ); 436 437 m_nBlueShift2Mask = m_nBlueShift2 ? ~((unsigned long)((1<<m_nBlueShift2)-1)) : ~0L; 438 m_nGreenShift2Mask = m_nGreenShift2 ? ~((unsigned long)((1<<m_nGreenShift2)-1)) : ~0L; 439 m_nRedShift2Mask = m_nRedShift2 ? ~((unsigned long)((1<<m_nRedShift2)-1)) : ~0L; 440 } 441 } 442 443 PixmapHolder::~PixmapHolder() 444 { 445 if( m_aPixmap != None ) 446 XFreePixmap( m_pDisplay, m_aPixmap ); 447 if( m_aBitmap != None ) 448 XFreePixmap( m_pDisplay, m_aBitmap ); 449 } 450 451 unsigned long PixmapHolder::getTCPixel( sal_uInt8 r, sal_uInt8 g, sal_uInt8 b ) const 452 { 453 unsigned long nPixel = 0; 454 unsigned long nValue = (unsigned long)b; 455 nValue &= m_nBlueShift2Mask; 456 nPixel |= doLeftShift( nValue, m_nBlueShift ); 457 458 nValue = (unsigned long)g; 459 nValue &= m_nGreenShift2Mask; 460 nPixel |= doLeftShift( nValue, m_nGreenShift ); 461 462 nValue = (unsigned long)r; 463 nValue &= m_nRedShift2Mask; 464 nPixel |= doLeftShift( nValue, m_nRedShift ); 465 466 return nPixel; 467 } 468 469 void PixmapHolder::setBitmapDataPalette( const sal_uInt8* pData, XImage* pImage ) 470 { 471 // setup palette 472 XColor aPalette[256]; 473 474 sal_uInt32 nColors = readLE32( pData+32 ); 475 sal_uInt32 nWidth = readLE32( pData+4 ); 476 sal_uInt32 nHeight = readLE32( pData+8 ); 477 sal_uInt16 nDepth = readLE16( pData+14 ); 478 479 for( sal_uInt16 i = 0 ; i < nColors; i++ ) 480 { 481 if( m_aInfo.c_class != TrueColor ) 482 { 483 aPalette[i].red = ((unsigned short)pData[42 + i*4]) << 8 | ((unsigned short)pData[42 + i*4]); 484 aPalette[i].green = ((unsigned short)pData[41 + i*4]) << 8 | ((unsigned short)pData[41 + i*4]); 485 aPalette[i].blue = ((unsigned short)pData[40 + i*4]) << 8 | ((unsigned short)pData[40 + i*4]); 486 XAllocColor( m_pDisplay, m_aColormap, aPalette+i ); 487 } 488 else 489 aPalette[i].pixel = getTCPixel( pData[42+i*4], pData[41+i*4], pData[40+i*4] ); 490 } 491 const sal_uInt8* pBMData = pData + readLE32( pData ) + 4*nColors; 492 493 sal_uInt32 nScanlineSize = 0; 494 switch( nDepth ) 495 { 496 case 1: 497 nScanlineSize = (nWidth+31)/32; 498 break; 499 case 4: 500 nScanlineSize = (nWidth+1)/2; 501 break; 502 case 8: 503 nScanlineSize = nWidth; 504 break; 505 } 506 // adjust scan lines to begin on %4 boundaries 507 if( nScanlineSize & 3 ) 508 { 509 nScanlineSize &= 0xfffffffc; 510 nScanlineSize += 4; 511 } 512 513 // allocate buffer to hold header and scanlines, initialize to zero 514 for( unsigned int y = 0; y < nHeight; y++ ) 515 { 516 const sal_uInt8* pScanline = pBMData + (nHeight-1-y)*nScanlineSize; 517 for( unsigned int x = 0; x < nWidth; x++ ) 518 { 519 int nCol = 0; 520 switch( nDepth ) 521 { 522 case 1: nCol = (pScanline[ x/8 ] & (0x80 >> (x&7))) != 0 ? 0 : 1; break; 523 case 4: 524 if( x & 1 ) 525 nCol = (int)(pScanline[ x/2 ] >> 4); 526 else 527 nCol = (int)(pScanline[ x/2 ] & 0x0f); 528 break; 529 case 8: nCol = (int)pScanline[x]; 530 } 531 XPutPixel( pImage, x, y, aPalette[nCol].pixel ); 532 } 533 } 534 } 535 536 void PixmapHolder::setBitmapDataTCDither( const sal_uInt8* pData, XImage* pImage ) 537 { 538 XColor aPalette[216]; 539 540 int nNonAllocs = 0; 541 542 for( int r = 0; r < 6; r++ ) 543 { 544 for( int g = 0; g < 6; g++ ) 545 { 546 for( int b = 0; b < 6; b++ ) 547 { 548 int i = r*36+g*6+b; 549 aPalette[i].red = r == 5 ? 0xffff : r*10922; 550 aPalette[i].green = g == 5 ? 0xffff : g*10922; 551 aPalette[i].blue = b == 5 ? 0xffff : b*10922; 552 aPalette[i].pixel = 0; 553 if( ! XAllocColor( m_pDisplay, m_aColormap, aPalette+i ) ) 554 nNonAllocs++; 555 } 556 } 557 } 558 559 if( nNonAllocs ) 560 { 561 XColor aRealPalette[256]; 562 int nColors = 1 << m_aInfo.depth; 563 int i; 564 for( i = 0; i < nColors; i++ ) 565 aRealPalette[i].pixel = (unsigned long)i; 566 XQueryColors( m_pDisplay, m_aColormap, aRealPalette, nColors ); 567 for( i = 0; i < nColors; i++ ) 568 { 569 sal_uInt8 nIndex = 570 36*(sal_uInt8)(aRealPalette[i].red/10923) + 571 6*(sal_uInt8)(aRealPalette[i].green/10923) + 572 (sal_uInt8)(aRealPalette[i].blue/10923); 573 if( aPalette[nIndex].pixel == 0 ) 574 aPalette[nIndex] = aRealPalette[i]; 575 } 576 } 577 578 sal_uInt32 nWidth = readLE32( pData+4 ); 579 sal_uInt32 nHeight = readLE32( pData+8 ); 580 581 const sal_uInt8* pBMData = pData + readLE32( pData ); 582 sal_uInt32 nScanlineSize = nWidth*3; 583 // adjust scan lines to begin on %4 boundaries 584 if( nScanlineSize & 3 ) 585 { 586 nScanlineSize &= 0xfffffffc; 587 nScanlineSize += 4; 588 } 589 590 for( int y = 0; y < (int)nHeight; y++ ) 591 { 592 const sal_uInt8* pScanline = pBMData + (nHeight-1-(sal_uInt32)y)*nScanlineSize; 593 for( int x = 0; x < (int)nWidth; x++ ) 594 { 595 sal_uInt8 b = pScanline[3*x]; 596 sal_uInt8 g = pScanline[3*x+1]; 597 sal_uInt8 r = pScanline[3*x+2]; 598 sal_uInt8 i = 36*(r/43) + 6*(g/43) + (b/43); 599 600 XPutPixel( pImage, x, y, aPalette[ i ].pixel ); 601 } 602 } 603 } 604 605 void PixmapHolder::setBitmapDataTC( const sal_uInt8* pData, XImage* pImage ) 606 { 607 sal_uInt32 nWidth = readLE32( pData+4 ); 608 sal_uInt32 nHeight = readLE32( pData+8 ); 609 610 const sal_uInt8* pBMData = pData + readLE32( pData ); 611 sal_uInt32 nScanlineSize = nWidth*3; 612 // adjust scan lines to begin on %4 boundaries 613 if( nScanlineSize & 3 ) 614 { 615 nScanlineSize &= 0xfffffffc; 616 nScanlineSize += 4; 617 } 618 619 for( int y = 0; y < (int)nHeight; y++ ) 620 { 621 const sal_uInt8* pScanline = pBMData + (nHeight-1-(sal_uInt32)y)*nScanlineSize; 622 for( int x = 0; x < (int)nWidth; x++ ) 623 { 624 unsigned long nPixel = getTCPixel( pScanline[3*x+2], pScanline[3*x+1], pScanline[3*x] ); 625 XPutPixel( pImage, x, y, nPixel ); 626 } 627 } 628 } 629 630 bool PixmapHolder::needsConversion( const sal_uInt8* pData ) 631 { 632 if( pData[0] != 'B' || pData[1] != 'M' ) 633 return true; 634 635 pData = pData+14; 636 sal_uInt32 nDepth = readLE32( pData+14 ); 637 if( nDepth == 24 ) 638 { 639 if( m_aInfo.c_class != TrueColor ) 640 return true; 641 } 642 else if( nDepth != (sal_uInt32)m_aInfo.depth ) 643 { 644 if( m_aInfo.c_class != TrueColor ) 645 return true; 646 } 647 648 return false; 649 } 650 651 Pixmap PixmapHolder::setBitmapData( const sal_uInt8* pData ) 652 { 653 if( pData[0] != 'B' || pData[1] != 'M' ) 654 return None; 655 656 pData = pData+14; 657 658 // reject compressed data 659 if( readLE32( pData + 16 ) != 0 ) 660 return None; 661 662 sal_uInt32 nWidth = readLE32( pData+4 ); 663 sal_uInt32 nHeight = readLE32( pData+8 ); 664 665 if( m_aPixmap != None ) 666 XFreePixmap( m_pDisplay, m_aPixmap ), m_aPixmap = None; 667 if( m_aBitmap != None ) 668 XFreePixmap( m_pDisplay, m_aBitmap ), m_aBitmap = None; 669 670 m_aPixmap = XCreatePixmap( m_pDisplay, 671 RootWindow( m_pDisplay, m_aInfo.screen ), 672 nWidth, nHeight, m_aInfo.depth ); 673 674 if( m_aPixmap != None ) 675 { 676 XImage aImage; 677 aImage.width = (int)nWidth; 678 aImage.height = (int)nHeight; 679 aImage.xoffset = 0; 680 aImage.format = ZPixmap; 681 aImage.data = NULL; 682 aImage.byte_order = ImageByteOrder( m_pDisplay ); 683 aImage.bitmap_unit = BitmapUnit( m_pDisplay ); 684 aImage.bitmap_bit_order = BitmapBitOrder( m_pDisplay ); 685 aImage.bitmap_pad = BitmapPad( m_pDisplay ); 686 aImage.depth = m_aInfo.depth; 687 aImage.red_mask = m_aInfo.red_mask; 688 aImage.green_mask = m_aInfo.green_mask; 689 aImage.blue_mask = m_aInfo.blue_mask; 690 aImage.bytes_per_line = 0; // filled in by XInitImage 691 if( m_aInfo.depth <= 8 ) 692 aImage.bits_per_pixel = m_aInfo.depth; 693 else 694 aImage.bits_per_pixel = 8*((m_aInfo.depth+7)/8); 695 aImage.obdata = NULL; 696 697 XInitImage( &aImage ); 698 aImage.data = (char*)rtl_allocateMemory( nHeight*aImage.bytes_per_line ); 699 700 if( readLE32( pData+14 ) == 24 ) 701 { 702 if( m_aInfo.c_class == TrueColor ) 703 setBitmapDataTC( pData, &aImage ); 704 else 705 setBitmapDataTCDither( pData, &aImage ); 706 } 707 else 708 setBitmapDataPalette( pData, &aImage ); 709 710 // put the image 711 XPutImage( m_pDisplay, 712 m_aPixmap, 713 DefaultGC( m_pDisplay, m_aInfo.screen ), 714 &aImage, 715 0, 0, 716 0, 0, 717 nWidth, nHeight ); 718 719 // clean up 720 rtl_freeMemory( aImage.data ); 721 722 // prepare bitmap (mask) 723 m_aBitmap = XCreatePixmap( m_pDisplay, 724 RootWindow( m_pDisplay, m_aInfo.screen ), 725 nWidth, nHeight, 1 ); 726 XGCValues aVal; 727 aVal.function = GXcopy; 728 aVal.foreground = 0xffffffff; 729 GC aGC = XCreateGC( m_pDisplay, m_aBitmap, GCFunction | GCForeground, &aVal ); 730 XFillRectangle( m_pDisplay, m_aBitmap, aGC, 0, 0, nWidth, nHeight ); 731 XFreeGC( m_pDisplay, aGC ); 732 } 733 734 return m_aPixmap; 735 } 736