summaryrefslogtreecommitdiff
path: root/app/wlib/gtklib/gtkxpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/gtklib/gtkxpm.c')
-rw-r--r--app/wlib/gtklib/gtkxpm.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/app/wlib/gtklib/gtkxpm.c b/app/wlib/gtklib/gtkxpm.c
new file mode 100644
index 0000000..022c973
--- /dev/null
+++ b/app/wlib/gtklib/gtkxpm.c
@@ -0,0 +1,177 @@
+/** \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 <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+
+#include <gtk/gtk.h>
+#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;
+
+ GdkPixmap * pixmap;
+ GdkPixmap * pixmapBackup;
+
+ 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; y<d->h; y++ ) {
+ fprintf( f, "\"" );
+ for ( x=0; x<d->w; 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", (y<d->h-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;
+}