From 7b358424ebad9349421acd533c2fa1cbf6cf3e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 28 Dec 2016 16:52:56 +0100 Subject: Initial import of xtrkcad version 1:4.0.2-2 --- app/wlib/mswlib/mswbitmap.c | 508 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 508 insertions(+) create mode 100644 app/wlib/mswlib/mswbitmap.c (limited to 'app/wlib/mswlib/mswbitmap.c') diff --git a/app/wlib/mswlib/mswbitmap.c b/app/wlib/mswlib/mswbitmap.c new file mode 100644 index 0000000..7371834 --- /dev/null +++ b/app/wlib/mswlib/mswbitmap.c @@ -0,0 +1,508 @@ +/** \file mswbitmap.c + * Bitmap handling functions + * + * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/mswlib/mswbitmap.c,v 1.1 2009-09-20 14:55:54 m_fischer Exp $ + */ +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2009 Martin Fischer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "mswint.h" +#include "i18n.h" + +#if _MSC_VER > 1300 + #define stricmp _stricmp + #define strnicmp _strnicmp + #define strdup _strdup +#endif + +struct wBitmap_t { + WOBJ_COMMON + }; + +HPALETTE hOldPal; + +HBITMAP mswCreateBitMap( + COLORREF fgCol1, + COLORREF fgCol2, + COLORREF bgCol, + wPos_t w, + wPos_t h, + const char * bits ) +{ + HDC hDc; + HDC hButtDc; + HBRUSH oldBrush, newBrush; + RECT rect; + HBITMAP hBitMap; + HBITMAP hOldBitMap; + const char * byts_p; + int byt, i, j; + + hDc = GetDC( mswHWnd ); + hButtDc = CreateCompatibleDC( hDc ); + hBitMap = CreateCompatibleBitmap( hDc, w, h ); + ReleaseDC( mswHWnd, hDc ); + hOldBitMap = SelectObject( hButtDc, hBitMap ); + if (mswPalette) { + hOldPal = SelectPalette( hButtDc, mswPalette, 0 ); + } + + /*PatBlt( hButtDc, 0, 0, w, h, WHITENESS );*/ + newBrush = CreateSolidBrush( bgCol ); + oldBrush = SelectObject( hButtDc, newBrush ); + rect.top = 0; + rect.left = 0; + rect.bottom = h; + rect.right = w; + FillRect( hButtDc, &rect, newBrush ); + DeleteObject( SelectObject( hButtDc, oldBrush ) ); + + byts_p = bits; + for ( j = 0; j < h; j++ ) { + byt = (0xFF & *byts_p++) | 0x100; + for ( i = 0; i < w; i++ ) { + if (byt == 1) + byt = (0xFF & *byts_p++) | 0x100; + if ( byt & 0x1 ) { + SetPixel( hButtDc, i, j, fgCol1 ); + SetPixel( hButtDc, i+1, j+1, fgCol2 ); + } + byt >>= 1; + } + } + + SelectObject( hButtDc, hOldBitMap ); + DeleteDC( hButtDc ); + return hBitMap; +} + +dynArr_t bitmap_da; +#define controlMap(N) DYNARR_N(controlMap_t,controlMap_da,N) +#define bitmap(N) DYNARR_N(HBITMAP,bitmap_da,N) + +void mswRegisterBitMap( + HBITMAP hBm ) +{ + DYNARR_APPEND( HBITMAP, bitmap_da, 10 ); + bitmap(bitmap_da.cnt-1) = hBm; +} + +void deleteBitmaps( void ) +{ + int inx; + for ( inx=0; inxcolorcnt - 1) * sizeof( RGBQUAD )); + if( !bmiInfo ) { + fprintf( stderr, "could not allocate memory for bmiInfo\n" ); + abort(); + } + + /* initialize bitmap header from XPM information */ + bmiInfo->bmiHeader.biSize = sizeof( bmiInfo->bmiHeader ); + bmiInfo->bmiHeader.biWidth = bm->w; + bmiInfo->bmiHeader.biHeight = bm->h; + bmiInfo->bmiHeader.biPlanes = 1; + if( bm->type == mswIcon_bitmap ) + bmiInfo->bmiHeader.biBitCount = 1; + else + bmiInfo->bmiHeader.biBitCount = 8; /* up to 256 colors */ + bmiInfo->bmiHeader.biCompression = BI_RGB; /* no compression */ + bmiInfo->bmiHeader.biSizeImage = 0; + bmiInfo->bmiHeader.biXPelsPerMeter = 0; + bmiInfo->bmiHeader.biYPelsPerMeter = 0; + bmiInfo->bmiHeader.biClrUsed = bm->colorcnt; /* number of colors used */ + bmiInfo->bmiHeader.biClrImportant = bm->colorcnt; + + /* + * create a transparency mask and paint to screen + */ + if( bm->type == mswIcon_bitmap ) { + memset( &bmiInfo->bmiColors[ 0 ], 0xFF, sizeof( RGBQUAD )); + memset( &bmiInfo->bmiColors[ 1 ], 0, sizeof( RGBQUAD )); + } else { + memset( bmiInfo->bmiColors, 0, bm->colorcnt * sizeof( RGBQUAD )); + memset( &bmiInfo->bmiColors[ bm->transparent ], 0xFF, sizeof( RGBQUAD )); + } + StretchDIBits(hDc, offw, offh, + bmiInfo->bmiHeader.biWidth, + bmiInfo->bmiHeader.biHeight, + 0, 0, + bmiInfo->bmiHeader.biWidth, + bmiInfo->bmiHeader.biHeight, + bm->pixels, bmiInfo, + DIB_RGB_COLORS, SRCAND); + + /* now paint the bitmap with transparent set to black */ + if( bm->type == mswIcon_bitmap ) { + if( disabled ) { + col = color2; + } else { + col = color1; + } + memset( &bmiInfo->bmiColors[ 0 ], 0, sizeof( RGBQUAD )); + bmiInfo->bmiColors[ 1 ].rgbRed = GetRValue( col ); + bmiInfo->bmiColors[ 1 ].rgbGreen = GetGValue( col ); + bmiInfo->bmiColors[ 1 ].rgbBlue = GetBValue( col ); + } else { + if( disabled ) { + /* create a gray scale palette */ + for( i = 0; i < bm->colorcnt; i ++ ) { + byt = ( 30 * bm->colormap[ i ].rgbRed + + 59 * bm->colormap[ i ].rgbGreen + + 11 * bm->colormap[ i ].rgbBlue )/100; + + /* if totally black, use a dark gray */ + if( byt == 0 ) + byt = 0x66; + + bmiInfo->bmiColors[ i ].rgbRed = byt; + bmiInfo->bmiColors[ i ].rgbGreen = byt; + bmiInfo->bmiColors[ i ].rgbBlue = byt; + } + } else { + /* copy the palette */ + memcpy( (void *)bmiInfo->bmiColors, (void *)bm->colormap, bm->colorcnt * sizeof( RGBQUAD )); + } + memset( &bmiInfo->bmiColors[ bm->transparent ], 0, sizeof( RGBQUAD )); + } + + /* show the bitmap */ + StretchDIBits(hDc, offw, offh, + bmiInfo->bmiHeader.biWidth, + bmiInfo->bmiHeader.biHeight, + 0, 0, + bmiInfo->bmiHeader.biWidth, + bmiInfo->bmiHeader.biHeight, + bm->pixels, bmiInfo, + DIB_RGB_COLORS, SRCPAINT); + + /* forget the data */ + free( bmiInfo ); +} + +/** + * Create a two color bitmap. This creates a two color icon. Pixels set to 1 are painted + * in the specified color, pixels set to 0 are transparent + * in order to convert the format, a lot of bit fiddling is necessary. The order of + * scanlines needs to be reversed and the bit order (high order - low order) is reversed + * as well. + * \param w IN width in pixels + * \param h IN height in pixels + * \param bits IN pixel data + * \param color IN color for foreground + * \return pointer to icon + */ + +wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color ) +{ + int lineLength; + int i, j; + unsigned char *dest; + static unsigned char revbits[] = { 0, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F }; + unsigned long col = wDrawGetRGB( color ); + + wIcon_p ip; + ip = (wIcon_p)malloc( sizeof *ip ); + if( !ip ) { + fprintf( stderr, "Couldn't allocate memory for bitmap header.\n" ); + abort(); + } + + memset( ip, 0, sizeof *ip ); + ip->type = mswIcon_bitmap; + ip->w = w; + ip->h = h; + ip->colorcnt = 2; + + /* set up our two color palette */ + ip->colormap = malloc( 2 * sizeof( RGBQUAD )); + + ip->colormap[ 1 ].rgbBlue = col & 0xFF; + ip->colormap[ 1 ].rgbRed = (col>>16) & 0xFF; + ip->colormap[ 1 ].rgbGreen = (col>>8) & 0xFF; + ip->colormap[ 1 ].rgbReserved = 0; + + color = GetSysColor( COLOR_BTNFACE ); + ip->colormap[ 0 ].rgbBlue = GetBValue( color ); + ip->colormap[ 0 ].rgbRed = GetRValue( color ); + ip->colormap[ 0 ].rgbGreen = GetGValue( color ); + ip->colormap[ 0 ].rgbReserved = 0; + + lineLength = (((( ip->w + 7 ) / 8 ) + 3 ) >> 2 ) << 2; + ip->pixels = malloc( lineLength * ip->h ); + if( !ip->pixels ) { + fprintf( stderr, "Couldn't allocate memory for pixel data.\n" ); + abort(); + } + + /* + * copy the bits from source to the buffer, at this time the order of + * scanlines is reversed by starting with the last source line. + */ + for( i = 0; i < ip->h; i++ ) { + dest = ip->pixels + i * lineLength; + memcpy( dest, bits + ( ip->h - i - 1 ) * (( ip->w + 7) / 8), ( ip->w + 7 ) / 8 ); + + /* + * and now, the bit order is changed, this is done via a lookup table + */ + for( j = 0; j < lineLength; j++ ) + { + unsigned byte = dest[ j ]; + unsigned low = byte & 0x0F; + unsigned high = (byte & 0xF0) >> 4; + dest[ j ] = revbits[ low ]<<4 | revbits[ high ]; + } + } + + return ip; +} + +/** + * Create a pixmap. This functions interprets a XPM icon contained in a + * char array. Supported format are one or two byte per pixel and #rrggbb + * or #rrrrggggbbbb color specification. Color 'None' is interpreted as + * transparency, other symbolic names are not supported. + * + * \param pm IN XPM variable + * \return pointer to icon, call free() if not needed anymore. + */ + +wIcon_p wIconCreatePixMap( char *pm[]) +{ + wIcon_p ip; + int col, r, g, b, len; + int width, height; + char buff[3]; + char * cp, * cq, * ptr; + int i, j, k; + int lineLength; + unsigned *keys; + unsigned numchars; + unsigned pixel; + + ip = (wIcon_p)malloc( sizeof *ip ); + if( !ip ) { + fprintf( stderr, "Couldn't allocate memory for bitmap header.\n" ); + abort(); + } + + memset( ip, 0, sizeof *ip ); + ip->type = mswIcon_pixmap; + + /* extract values */ + cp = pm[0]; + width = (int)strtol(cp, &cq, 10 ); /* width of image */ + height = (int)strtol(cq, &cq, 10 ); /* height of image */ + col = (int)strtol(cq, &cq, 10 ); /* number of colors used */ + numchars = (int)strtol(cq, &cq, 10 ); /* get number of chars per pixel */ + + ip->colormap = malloc( col * sizeof( RGBQUAD )); + ip->w = width; + ip->h = height; + ip->colorcnt = col; /* number of colors used */ + + keys = malloc( sizeof( unsigned ) * col ); + + for ( col=0; col<(int)ip->colorcnt; col++ ) { + ptr = strdup( pm[col+1] ); /* create duplicate for input string*/ + + if( numchars == 1 ) { + keys[ col ] = (unsigned)ptr[0]; + } + else if( numchars == 2 ) { + keys[ col ] = (unsigned) ( ptr[ 0 ] + ptr[ 1 ] * 256 ); + } + + cp = strtok( ptr + numchars, "\t " ); /* cp points to color type */ + assert( *cp == 'c' ); /* should always be color */ + + cp = strtok( NULL, "\t " ); /* go to next token, the color definition itself */ + + if( *cp == '#' ) { /* is this a hex RGB specification? */ + len = strlen( cp+1 ) / 3; + assert( len == 4 || len == 2 ); /* expecting three 2 char or 4 char values */ + buff[2] = 0; /* if yes, extract the values */ + memcpy( buff, cp + 1, 2 ); + r = (int)strtol(buff, &cq, 16); + memcpy( buff, cp + 1 + len, 2 ); + g = (int)strtol(buff, &cq, 16); + memcpy( buff, cp + 1 + 2 * len, 2 ); + b = (int)strtol(buff, &cq, 16); + + ip->colormap[ col ].rgbBlue = b; + ip->colormap[ col ].rgbGreen = g; + ip->colormap[ col ].rgbRed = r; + ip->colormap[ col ].rgbReserved = 0; + + } else { + if( !stricmp( cp, "none" )) { /* special case transparency*/ + ip->transparent = col; + } + else + assert( *cp == '#' ); /* if no, abort for the moment */ + } + free( ptr ); + } + + /* get memory for the pixel data */ + /* dword align begin of line */ + lineLength = ((ip->w + 3 ) >> 2 ) << 2; + ip->pixels = malloc( lineLength * ip->h ); + if( !ip->pixels ) { + fprintf( stderr, "Couldn't allocate memory for pixel data.\n" ); + abort(); + } + + /* + convert the XPM pixel data to indexes into color table + at the same time the order of rows is reversed + Win32 should be able to do that but I couldn't find out + how, so this is coded by hand. + */ + + /* for all rows */ + for( i = 0; i < ip->h; i++ ) { + + cq = ip->pixels + lineLength * i; + /* get the next row */ + cp = pm[ ip->h - i + ip->colorcnt ]; + /* for all pixels in row */ + for( j = 0; j < ip->w; j++ ) { + /* get the pixel info */ + if( numchars == 1 ) + pixel = ( unsigned )*cp; + else + pixel = (unsigned) (*cp + *(cp+1)*256); + cp += numchars; + + /* look up pixel info in color table */ + k = 0; + while( pixel != keys[ k ] ) + k++; + + /* save the index into color table */ + *(cq + j) = k; + } + } + free( keys ); + + return ip; +} + +void wIconSetColor( wIcon_p ip, wDrawColor color ) +{ + unsigned long col = wDrawGetRGB( color ); + + if( ip->type == mswIcon_bitmap ) { + ip->colormap[ 1 ].rgbBlue = col & 0xFF; + ip->colormap[ 1 ].rgbRed = (col>>16) & 0xFF; + ip->colormap[ 1 ].rgbGreen = (col>>8) & 0xFF; + } +} + +/** + * Draw icon to screen. + * + * \param d IN drawing area + * \param bm IN bitmap to draw + * \param x IN x position + * \param y IN y position + */ + +void +wIconDraw( wDraw_p d, wIcon_p bm, wPos_t x, wPos_t y ) +{ + mswDrawIcon( d->hDc, (int)x, (int)y, bm, FALSE, 0, 0 ); +} + +/** + * Create a static control for displaying a bitmap. + * + * \param parent IN parent window + * \param x, y IN position in parent window + * \param option IN ignored for now + * \param iconP IN icon to use + * \return the control + */ + +wControl_p +wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long option, wIcon_p iconP ) +{ + wBitmap_p control; + int index; + DWORD style = SS_OWNERDRAW | WS_VISIBLE | WS_CHILD; + + control = mswAlloc( parent, B_BITMAP, NULL, sizeof( struct wBitmap_t ), NULL, &index ); + mswComputePos( (wControl_p)control, x, y ); + control->option = option; + + control->hWnd = CreateWindow( "STATIC", NULL, + style, control->x, control->y, + iconP->w, iconP->h, + ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL ); + + if (control->hWnd == NULL) { + mswFail("CreateWindow(BITMAP)"); + return (wControl_p)control; + } + control->h = iconP->h; + control->w = iconP->w; + control->data = iconP; + + return (wControl_p)control; +} \ No newline at end of file -- cgit v1.2.3