LCOV - code coverage report
Current view: top level - libreoffice/vcl/unx/generic/dtrans - bmp.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 377 0.0 %
Date: 2012-12-27 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10