LCOV - code coverage report
Current view: top level - vcl/unx/generic/dtrans - bmp.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 387 0.0 %
Date: 2014-11-03 Functions: 0 23 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             :     ::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             :     , m_aBitmap(None)
     354             :     , m_nRedShift(0)
     355             :     , m_nRedShift2(0)
     356             :     , m_nGreenShift(0)
     357             :     , m_nGreenShift2(0)
     358             :     , m_nBlueShift(0)
     359             :     , m_nBlueShift2(0)
     360             :     , m_nBlueShift2Mask(0)
     361             :     , m_nRedShift2Mask(0)
     362           0 :     , m_nGreenShift2Mask(0)
     363             : {
     364             :     /*  try to get a 24 bit true color visual, if that fails,
     365             :      *  revert to default visual
     366             :      */
     367           0 :     if( ! XMatchVisualInfo( m_pDisplay, DefaultScreen( m_pDisplay ), 24, TrueColor, &m_aInfo ) )
     368             :     {
     369             : #if OSL_DEBUG_LEVEL > 1
     370             :         fprintf( stderr, "PixmapHolder reverting to default visual\n" );
     371             : #endif
     372           0 :         Visual* pVisual     = DefaultVisual( m_pDisplay, DefaultScreen( m_pDisplay ) );
     373           0 :         m_aInfo.screen      = DefaultScreen( m_pDisplay );
     374           0 :         m_aInfo.visual      = pVisual;
     375           0 :         m_aInfo.visualid    = pVisual->visualid;
     376           0 :         m_aInfo.c_class     = pVisual->c_class;
     377           0 :         m_aInfo.red_mask    = pVisual->red_mask;
     378           0 :         m_aInfo.green_mask  = pVisual->green_mask;
     379           0 :         m_aInfo.blue_mask   = pVisual->blue_mask;
     380           0 :         m_aInfo.depth       = DefaultDepth( m_pDisplay, m_aInfo.screen );
     381             :     }
     382           0 :     m_aColormap         = DefaultColormap( m_pDisplay, m_aInfo.screen );
     383             : #if OSL_DEBUG_LEVEL > 1
     384             :     static const char* pClasses[] =
     385             :         { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor" };
     386             :     fprintf( stderr, "PixmapHolder visual: id = 0x%lx, class = %s (%d), depth=%d; color map = 0x%lx\n",
     387             :              m_aInfo.visualid,
     388             :              (m_aInfo.c_class >= 0 && unsigned(m_aInfo.c_class) < SAL_N_ELEMENTS(pClasses)) ? pClasses[m_aInfo.c_class] : "<unknown>",
     389             :              m_aInfo.c_class,
     390             :              m_aInfo.depth,
     391             :              m_aColormap  );
     392             : #endif
     393           0 :     if( m_aInfo.c_class == TrueColor )
     394             :     {
     395             :         int nRedSig, nGreenSig, nBlueSig;
     396           0 :         getShift( m_aInfo.red_mask, m_nRedShift, nRedSig, m_nRedShift2 );
     397           0 :         getShift( m_aInfo.green_mask, m_nGreenShift, nGreenSig, m_nGreenShift2 );
     398           0 :         getShift( m_aInfo.blue_mask, m_nBlueShift, nBlueSig, m_nBlueShift2 );
     399             : 
     400           0 :         m_nBlueShift2Mask = m_nBlueShift2 ? ~((unsigned long)((1<<m_nBlueShift2)-1)) : ~0L;
     401           0 :         m_nGreenShift2Mask = m_nGreenShift2 ? ~((unsigned long)((1<<m_nGreenShift2)-1)) : ~0L;
     402           0 :         m_nRedShift2Mask = m_nRedShift2 ? ~((unsigned long)((1<<m_nRedShift2)-1)) : ~0L;
     403             :     }
     404           0 : }
     405             : 
     406           0 : PixmapHolder::~PixmapHolder()
     407             : {
     408           0 :     if( m_aPixmap != None )
     409           0 :         XFreePixmap( m_pDisplay, m_aPixmap );
     410           0 :     if( m_aBitmap != None )
     411           0 :         XFreePixmap( m_pDisplay, m_aBitmap );
     412           0 : }
     413             : 
     414           0 : unsigned long PixmapHolder::getTCPixel( sal_uInt8 r, sal_uInt8 g, sal_uInt8 b ) const
     415             : {
     416           0 :     unsigned long nPixel = 0;
     417           0 :     unsigned long nValue = (unsigned long)b;
     418           0 :     nValue &= m_nBlueShift2Mask;
     419           0 :     nPixel |= doLeftShift( nValue, m_nBlueShift );
     420             : 
     421           0 :     nValue = (unsigned long)g;
     422           0 :     nValue &= m_nGreenShift2Mask;
     423           0 :     nPixel |= doLeftShift( nValue, m_nGreenShift );
     424             : 
     425           0 :     nValue = (unsigned long)r;
     426           0 :     nValue &= m_nRedShift2Mask;
     427           0 :     nPixel |= doLeftShift( nValue, m_nRedShift );
     428             : 
     429           0 :     return nPixel;
     430             : }
     431             : 
     432           0 : void PixmapHolder::setBitmapDataPalette( const sal_uInt8* pData, XImage* pImage )
     433             : {
     434             :     // setup palette
     435             :     XColor aPalette[256];
     436             : 
     437           0 :     sal_uInt32 nColors = readLE32( pData+32 );
     438           0 :     sal_uInt32 nWidth   = readLE32( pData+4 );
     439           0 :     sal_uInt32 nHeight  = readLE32( pData+8 );
     440           0 :     sal_uInt16 nDepth = readLE16( pData+14 );
     441             : 
     442           0 :     for( sal_uInt16 i = 0 ; i < nColors; i++ )
     443             :     {
     444           0 :         if( m_aInfo.c_class != TrueColor )
     445             :         {
     446           0 :             aPalette[i].red     = ((unsigned short)pData[42 + i*4]) << 8 | ((unsigned short)pData[42 + i*4]);
     447           0 :             aPalette[i].green   = ((unsigned short)pData[41 + i*4]) << 8 | ((unsigned short)pData[41 + i*4]);
     448           0 :             aPalette[i].blue    = ((unsigned short)pData[40 + i*4]) << 8 | ((unsigned short)pData[40 + i*4]);
     449           0 :             XAllocColor( m_pDisplay, m_aColormap, aPalette+i );
     450             :         }
     451             :         else
     452           0 :             aPalette[i].pixel = getTCPixel( pData[42+i*4], pData[41+i*4], pData[40+i*4] );
     453             :     }
     454           0 :     const sal_uInt8* pBMData = pData + readLE32( pData ) + 4*nColors;
     455             : 
     456           0 :     sal_uInt32 nScanlineSize = 0;
     457           0 :     switch( nDepth )
     458             :     {
     459             :         case 1:
     460           0 :             nScanlineSize = (nWidth+31)/32;
     461           0 :             break;
     462             :         case 4:
     463           0 :             nScanlineSize = (nWidth+1)/2;
     464           0 :             break;
     465             :         case 8:
     466           0 :             nScanlineSize = nWidth;
     467           0 :             break;
     468             :     }
     469             :     // adjust scan lines to begin on %4 boundaries
     470           0 :     if( nScanlineSize & 3 )
     471             :     {
     472           0 :         nScanlineSize &= 0xfffffffc;
     473           0 :         nScanlineSize += 4;
     474             :     }
     475             : 
     476             :     // allocate buffer to hold header and scanlines, initialize to zero
     477           0 :     for( unsigned int y = 0; y < nHeight; y++ )
     478             :     {
     479           0 :         const sal_uInt8* pScanline = pBMData + (nHeight-1-y)*nScanlineSize;
     480           0 :         for( unsigned int x = 0; x < nWidth; x++ )
     481             :         {
     482           0 :             int nCol = 0;
     483           0 :             switch( nDepth )
     484             :             {
     485           0 :                 case 1: nCol = (pScanline[ x/8 ] & (0x80 >> (x&7))) != 0 ? 0 : 1; break;
     486             :                 case 4:
     487           0 :                     if( x & 1 )
     488           0 :                         nCol = (int)(pScanline[ x/2 ] >> 4);
     489             :                     else
     490           0 :                         nCol = (int)(pScanline[ x/2 ] & 0x0f);
     491           0 :                     break;
     492           0 :                 case 8: nCol = (int)pScanline[x];
     493             :             }
     494           0 :             XPutPixel( pImage, x, y, aPalette[nCol].pixel );
     495             :         }
     496             :     }
     497           0 : }
     498             : 
     499           0 : void PixmapHolder::setBitmapDataTCDither( const sal_uInt8* pData, XImage* pImage )
     500             : {
     501             :     XColor aPalette[216];
     502             : 
     503           0 :     int nNonAllocs = 0;
     504             : 
     505           0 :     for( int r = 0; r < 6; r++ )
     506             :     {
     507           0 :         for( int g = 0; g < 6; g++ )
     508             :         {
     509           0 :             for( int b = 0; b < 6; b++ )
     510             :             {
     511           0 :                 int i = r*36+g*6+b;
     512           0 :                 aPalette[i].red     = r == 5 ? 0xffff : r*10922;
     513           0 :                 aPalette[i].green   = g == 5 ? 0xffff : g*10922;
     514           0 :                 aPalette[i].blue    = b == 5 ? 0xffff : b*10922;
     515           0 :                 aPalette[i].pixel   = 0;
     516           0 :                 if( ! XAllocColor( m_pDisplay, m_aColormap, aPalette+i ) )
     517           0 :                     nNonAllocs++;
     518             :             }
     519             :         }
     520             :     }
     521             : 
     522           0 :     if( nNonAllocs )
     523             :     {
     524             :         XColor aRealPalette[256];
     525           0 :         int nColors = 1 << m_aInfo.depth;
     526             :         int i;
     527           0 :         for( i = 0; i < nColors; i++ )
     528           0 :             aRealPalette[i].pixel = (unsigned long)i;
     529           0 :         XQueryColors( m_pDisplay, m_aColormap, aRealPalette, nColors );
     530           0 :         for( i = 0; i < nColors; i++ )
     531             :         {
     532             :             sal_uInt8 nIndex =
     533             :                 36*(sal_uInt8)(aRealPalette[i].red/10923) +
     534             :                 6*(sal_uInt8)(aRealPalette[i].green/10923) +
     535           0 :                 (sal_uInt8)(aRealPalette[i].blue/10923);
     536           0 :             if( aPalette[nIndex].pixel == 0 )
     537           0 :                 aPalette[nIndex] = aRealPalette[i];
     538             :         }
     539             :     }
     540             : 
     541           0 :     sal_uInt32 nWidth   = readLE32( pData+4 );
     542           0 :     sal_uInt32 nHeight  = readLE32( pData+8 );
     543             : 
     544           0 :     const sal_uInt8* pBMData = pData + readLE32( pData );
     545           0 :     sal_uInt32 nScanlineSize = nWidth*3;
     546             :     // adjust scan lines to begin on %4 boundaries
     547           0 :     if( nScanlineSize & 3 )
     548             :     {
     549           0 :         nScanlineSize &= 0xfffffffc;
     550           0 :         nScanlineSize += 4;
     551             :     }
     552             : 
     553           0 :     for( int y = 0; y < (int)nHeight; y++ )
     554             :     {
     555           0 :         const sal_uInt8* pScanline = pBMData + (nHeight-1-(sal_uInt32)y)*nScanlineSize;
     556           0 :         for( int x = 0; x < (int)nWidth; x++ )
     557             :         {
     558           0 :             sal_uInt8 b = pScanline[3*x];
     559           0 :             sal_uInt8 g = pScanline[3*x+1];
     560           0 :             sal_uInt8 r = pScanline[3*x+2];
     561           0 :             sal_uInt8 i = 36*(r/43) + 6*(g/43) + (b/43);
     562             : 
     563           0 :             XPutPixel( pImage, x, y, aPalette[ i ].pixel );
     564             :         }
     565             :     }
     566           0 : }
     567             : 
     568           0 : void PixmapHolder::setBitmapDataTC( const sal_uInt8* pData, XImage* pImage )
     569             : {
     570           0 :     sal_uInt32 nWidth   = readLE32( pData+4 );
     571           0 :     sal_uInt32 nHeight  = readLE32( pData+8 );
     572             : 
     573           0 :     if (!nWidth || !nHeight)
     574           0 :         return;
     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 :             unsigned long nPixel = getTCPixel( pScanline[3*x+2], pScanline[3*x+1], pScanline[3*x] );
     591           0 :             XPutPixel( pImage, x, y, nPixel );
     592             :         }
     593             :     }
     594             : }
     595             : 
     596           0 : bool PixmapHolder::needsConversion( const sal_uInt8* pData )
     597             : {
     598           0 :     if( pData[0] != 'B' || pData[1] != 'M' )
     599           0 :         return true;
     600             : 
     601           0 :     pData = pData+14;
     602           0 :     sal_uInt32 nDepth = readLE32( pData+14 );
     603           0 :     if(  nDepth == 24 )
     604             :     {
     605           0 :         if( m_aInfo.c_class != TrueColor )
     606           0 :             return true;
     607             :     }
     608           0 :     else if( nDepth != (sal_uInt32)m_aInfo.depth )
     609             :     {
     610           0 :         if( m_aInfo.c_class != TrueColor )
     611           0 :             return true;
     612             :     }
     613             : 
     614           0 :     return false;
     615             : }
     616             : 
     617           0 : Pixmap PixmapHolder::setBitmapData( const sal_uInt8* pData )
     618             : {
     619           0 :     if( pData[0] != 'B' || pData[1] != 'M' )
     620           0 :         return None;
     621             : 
     622           0 :     pData = pData+14;
     623             : 
     624             :     // reject compressed data
     625           0 :     if( readLE32( pData + 16 ) != 0 )
     626           0 :         return None;
     627             : 
     628           0 :     sal_uInt32 nWidth   = readLE32( pData+4 );
     629           0 :     sal_uInt32 nHeight  = readLE32( pData+8 );
     630             : 
     631           0 :     if( m_aPixmap != None )
     632           0 :         XFreePixmap( m_pDisplay, m_aPixmap ), m_aPixmap = None;
     633           0 :     if( m_aBitmap != None )
     634           0 :         XFreePixmap( m_pDisplay, m_aBitmap ), m_aBitmap = None;
     635             : 
     636             :     m_aPixmap = limitXCreatePixmap( m_pDisplay,
     637           0 :                                RootWindow( m_pDisplay, m_aInfo.screen ),
     638           0 :                                nWidth, nHeight, m_aInfo.depth );
     639             : 
     640           0 :     if( m_aPixmap != None )
     641             :     {
     642             :         XImage aImage;
     643           0 :         aImage.width            = (int)nWidth;
     644           0 :         aImage.height           = (int)nHeight;
     645           0 :         aImage.xoffset          = 0;
     646           0 :         aImage.format           = ZPixmap;
     647           0 :         aImage.data             = NULL;
     648           0 :         aImage.byte_order       = ImageByteOrder( m_pDisplay );
     649           0 :         aImage.bitmap_unit      = BitmapUnit( m_pDisplay );
     650           0 :         aImage.bitmap_bit_order = BitmapBitOrder( m_pDisplay );
     651           0 :         aImage.bitmap_pad       = BitmapPad( m_pDisplay );
     652           0 :         aImage.depth            = m_aInfo.depth;
     653           0 :         aImage.red_mask         = m_aInfo.red_mask;
     654           0 :         aImage.green_mask       = m_aInfo.green_mask;
     655           0 :         aImage.blue_mask        = m_aInfo.blue_mask;
     656           0 :         aImage.bytes_per_line   = 0; // filled in by XInitImage
     657           0 :         if( m_aInfo.depth <= 8 )
     658           0 :             aImage.bits_per_pixel = m_aInfo.depth;
     659             :         else
     660           0 :             aImage.bits_per_pixel = 8*((m_aInfo.depth+7)/8);
     661           0 :         aImage.obdata           = NULL;
     662             : 
     663           0 :         XInitImage( &aImage );
     664           0 :         aImage.data = (char*)rtl_allocateMemory( nHeight*aImage.bytes_per_line );
     665             : 
     666           0 :         if( readLE32( pData+14 ) == 24 )
     667             :         {
     668           0 :             if( m_aInfo.c_class == TrueColor )
     669           0 :                 setBitmapDataTC( pData, &aImage );
     670             :             else
     671           0 :                 setBitmapDataTCDither( pData, &aImage );
     672             :         }
     673             :         else
     674           0 :             setBitmapDataPalette( pData, &aImage );
     675             : 
     676             :         // put the image
     677             :         XPutImage( m_pDisplay,
     678             :                    m_aPixmap,
     679           0 :                    DefaultGC( m_pDisplay, m_aInfo.screen ),
     680             :                    &aImage,
     681             :                    0, 0,
     682             :                    0, 0,
     683           0 :                    nWidth, nHeight );
     684             : 
     685             :         // clean up
     686           0 :         rtl_freeMemory( aImage.data );
     687             : 
     688             :         // prepare bitmap (mask)
     689             :         m_aBitmap = limitXCreatePixmap( m_pDisplay,
     690           0 :                                    RootWindow( m_pDisplay, m_aInfo.screen ),
     691           0 :                                    nWidth, nHeight, 1 );
     692             :         XGCValues aVal;
     693           0 :         aVal.function = GXcopy;
     694           0 :         aVal.foreground = 0xffffffff;
     695           0 :         GC aGC = XCreateGC( m_pDisplay, m_aBitmap, GCFunction | GCForeground, &aVal );
     696           0 :         XFillRectangle( m_pDisplay, m_aBitmap, aGC, 0, 0, nWidth, nHeight );
     697           0 :         XFreeGC( m_pDisplay, aGC );
     698             :     }
     699             : 
     700           0 :     return m_aPixmap;
     701             : }
     702             : 
     703           0 : css::uno::Sequence<sal_Int8> x11::convertBitmapDepth(
     704             :     css::uno::Sequence<sal_Int8> const & data, int depth)
     705             : {
     706           0 :     if (depth < 4) {
     707           0 :         depth = 1;
     708           0 :     } else if (depth < 8) {
     709           0 :         depth = 4;
     710           0 :     } else if (depth > 8 && depth < 24) {
     711           0 :         depth = 24;
     712             :     }
     713           0 :     SolarMutexGuard g;
     714             :     SvMemoryStream in(
     715           0 :         const_cast<sal_Int8 *>(data.getConstArray()), data.getLength(),
     716           0 :         STREAM_READ);
     717           0 :     Bitmap bm;
     718           0 :     ReadDIB(bm, in, true);
     719           0 :     if (bm.GetBitCount() == 24 && depth <= 8) {
     720           0 :         bm.Dither(BMP_DITHER_FLOYD);
     721             :     }
     722           0 :     if (bm.GetBitCount() != depth) {
     723           0 :         switch (depth) {
     724             :         case 1:
     725           0 :             bm.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
     726           0 :             break;
     727             :         case 4:
     728           0 :             bm.ReduceColors(BMP_CONVERSION_4BIT_COLORS);
     729           0 :             break;
     730             :         case 8:
     731           0 :             bm.ReduceColors(BMP_CONVERSION_8BIT_COLORS);
     732           0 :             break;
     733             :         case 24:
     734           0 :             bm.Convert(BMP_CONVERSION_24BIT);
     735           0 :             break;
     736             :         }
     737             :     }
     738           0 :     SvMemoryStream out;
     739           0 :     WriteDIB(bm, out, false, true);
     740             :     return css::uno::Sequence<sal_Int8>(
     741           0 :         static_cast<sal_Int8 const *>(out.GetData()), out.GetEndOfData());
     742           0 : }
     743             : 
     744             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10