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

Generated by: LCOV version 1.10