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

Generated by: LCOV version 1.11