/** \file gtkxpm.c * XPM creation functions */ /* XTrackCad - Model Railroad CAD * Copyright (C) 2015 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 #ifdef HAVE_MALLOC_H #include #endif #include #include #include "gtkint.h" #include "uthash.h" struct xpmColTable { int color; /* color value (rgb) */ char name[ 5 ]; /* corresponding character representation */ UT_hash_handle hh; /* makes this structure hashable */ }; static struct xpmColTable *colTable = NULL; // must be 64 chars long static char colVal[] = ".*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; //struct wDraw_t { //WOBJ_COMMON //void * context; //wDrawActionCallBack_p action; //wDrawRedrawCallBack_p redraw; //double dpi; //GdkGC * gc; //wDrawWidth lineWidth; //wDrawOpts opts; //wPos_t maxW; //wPos_t maxH; //unsigned long lastColor; //wBool_t lastColorInverted; //const char * helpStr; //wPos_t lastX; //wPos_t lastY; //wBool_t delayUpdate; //}; /** * Export as XPM bitmap file. During creation of the color table, a 4 byte color * encoding is assumed and a table created accordingly. Once the whole picture has been scanned * the correct number ist known. When writing to disk only the needed number of bytes per entry * is written. * This routine was heavily inspired by on implementation for TK written by Jan Nijtmans. * * \param d IN the drawing area ? * \param fileName IN fully qualified filename for the bitmap file. * \return TRUE on success, FALSE on error */ wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName ) { GdkImage * image; gint x, y; guint32 pixel; FILE * f; int cc = 0; struct xpmColTable *ct, *tmp; int numChars; image = gdk_image_get( (GdkWindow*)d->pixmap, 0, 0, d->w, d->h ); if (!image) { wNoticeEx( NT_ERROR, "WriteBitMap: image_get failed", "Ok", NULL ); return FALSE; } f = fopen( fileName, "w" ); if (!f) { perror( fileName ); return FALSE; } fprintf( f, "/* XPM */\n" ); fprintf( f, "static char * xtrkcad_bitmap[] = {\n" ); fprintf( f, "/* width height num_colors chars_per_pixel */\n" ); // count colors used and create the color table in the same pass for( y = 0; y < d->h;y ++ ) { for (x = 0; x < d->w; x++ ) { pixel = gdk_image_get_pixel( image, x, y ); //check whether color is new HASH_FIND(hh, colTable, &pixel, sizeof( guint32 ), ct); if( !ct ) { // not found previously, so add a new color table entry int i; int c; ct = malloc( sizeof( struct xpmColTable ) ); ct->name[ 4 ] = '\0'; for( i = 3, c = cc; i >= 0; i--, c>>=6 ) { (ct->name)[ i ] = colVal[ c & 0x3F ]; } ct->color = pixel; HASH_ADD(hh, colTable, color, sizeof( guint32 ), ct); cc++; } } } // calculate how many characters are needed for the color table numChars = 1; if( cc > 0x3ffff ) { numChars = 4; } else { if( cc > 0xfff ) { numChars = 3; } else { if( cc > 0x3f ) { numChars = 2; } } } // print color table fprintf( f, "\"%d %d %d %d\"\n", d->w, d->h, cc, numChars ); fprintf( f, "/* colors */\n" ); for( ct = colTable; ct != NULL; ct = ct->hh.next ) fprintf( f, "\"%s c #%6.6x\",\n", (ct->name) + (4 - numChars ), ct->color ); // print the pixels fprintf( f, "/* pixels */\n" ); for ( y=0; yh; y++ ) { fprintf( f, "\"" ); for ( x=0; xw; x++ ) { pixel = gdk_image_get_pixel( image, x, y ); HASH_FIND( hh, colTable, &pixel, sizeof(guint32), ct ); fputs( (ct->name) + (4 - numChars ), f ); } fprintf( f, "\"%s\n", (yh-1)?",":"" ); } // delete the hash and free the content HASH_ITER(hh, colTable, ct, tmp) { HASH_DEL(colTable,ct); free(ct); } gdk_image_destroy( image ); fprintf( f, "};\n" ); fclose( f ); return TRUE; }