]> granicus.if.org Git - nethack/commitdiff
X11 wide tilemap support
authorcohrs <cohrs>
Sun, 17 Mar 2002 20:02:47 +0000 (20:02 +0000)
committercohrs <cohrs>
Sun, 17 Mar 2002 20:02:47 +0000 (20:02 +0000)
- support X11 tile files (with or without XPM) that are 40 tiles wide
- rearrange some X11 code to share more code between XPM & non-XPM options
- clean out some deprecated X11/winmap.c #ifdefs
- update Qt code minimally to handle such an XPM file

include/tile2x11.h
include/winX.h
sys/unix/Makefile.src
win/Qt/qt_win.cpp
win/X11/tile2x11.c
win/X11/winmap.c

index 34ac01e751b351b24b7198f9287c205c35842665..3f16285e2107873441090339c806d2e5aafc4cc4 100644 (file)
@@ -13,6 +13,10 @@ typedef struct {
     unsigned long tile_width;
     unsigned long tile_height;
     unsigned long ntiles;
+    unsigned long per_row;
 } x11_header;
 
+/* how wide each row in the tile file is, in tiles */
+#define TILES_PER_ROW (40)
+
 #endif /* TILE2X11_H */
index 38c9a7d4445cda077541234fb691c3ed75c51b3f..7ded0185646f0bfcf173e2ae809e80159796028b 100644 (file)
@@ -56,6 +56,8 @@ struct tile_map_info_t {
     unsigned short glyphs[ROWNO][COLNO];       /* Saved glyph numbers. */
     GC white_gc;
     GC black_gc;
+    unsigned long image_width;                 /* dimensions of tile image */
+    unsigned long image_height;
 };
 
 struct map_info_t {
index 821540f3a376ff2345af48d6bf4f214be64cc7ba..9eafac67711b770b5873334bdcfbef68cfd71c2c 100644 (file)
@@ -668,8 +668,8 @@ load_img.o: ../win/gem/load_img.c ../include/load_img.h
        $(CC) $(CFLAGS) -c ../win/gem/load_img.c
 tile.o: tile.c $(HACK_H)
 qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) ../include/func_tab.h \
-               ../include/dlb.h ../include/patchlevel.h ../include/qt_win.h \
-               ../include/qt_clust.h ../include/qt_kde0.h \
+               ../include/dlb.h ../include/patchlevel.h ../include/tile2x11.h \
+               ../include/qt_win.h ../include/qt_clust.h ../include/qt_kde0.h \
                ../include/qt_xpms.h qt_win.moc qt_kde0.moc qttableview.moc
        $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_win.cpp
 qt_clust.o: ../win/Qt/qt_clust.cpp ../include/qt_clust.h
index 105fb96e473ee0b6c86821bd22600ad9383e3dcd..6493180833a79ad68919fe7d17bda3cf9fec5b75 100644 (file)
@@ -56,6 +56,7 @@ extern "C" {
 #include "func_tab.h"
 #include "dlb.h"
 #include "patchlevel.h"
+#include "tile2x11.h"
 #undef Warning
 #undef red
 #undef green
@@ -4178,10 +4179,10 @@ NetHackQtGlyphs::NetHackQtGlyphs()
            tiles_per_row = 40;
        }
     } else {
-        tiles_per_row = 1;
-        if (img.height()%total_tiles_used) {
-            impossible("Tile file \"%s\" has %d lines, not multiple of glyph count (%d)",
-               tile_file, img.height(), total_tiles_used);
+        tiles_per_row = TILES_PER_ROW;
+        if (img.width()%tiles_per_row) {
+            impossible("Tile file \"%s\" has %d columns, not multiple of row count (%d)",
+               tile_file, img.height(), tiles_per_row);
         }
     }
     int rows = ((total_tiles_used+tiles_per_row-1) / tiles_per_row);
index 746001dc3623f46585db89665b782aa885060b81..a2542135debb1c0dcd9707261c32273301261581 100644 (file)
@@ -15,7 +15,7 @@
 
 
 x11_header     header;
-unsigned char  tile_bytes[TILE_X*TILE_Y*MAX_GLYPH];
+unsigned char  tile_bytes[TILE_X*TILE_Y*(MAX_GLYPH+TILES_PER_ROW)];
 unsigned char  *curr_tb = tile_bytes;
 unsigned char  x11_colormap[MAXCOLORMAPSIZE][3];
 
@@ -44,8 +44,9 @@ pix_to_colormap(pix)
 
 /* Convert the tiles in the file to our format of bytes. */
 static unsigned long
-convert_tiles(tb_ptr)
+convert_tiles(tb_ptr, total)
     unsigned char **tb_ptr;    /* pointer to a tile byte pointer */
+    unsigned long total;       /* total tiles so far */
 {
     unsigned char *tb = *tb_ptr;
     unsigned long count = 0;
@@ -54,12 +55,20 @@ convert_tiles(tb_ptr)
 
     while (read_text_tile(tile)) {
        count++;
-       for (y = 0; y < TILE_Y; y++)
+       total++;
+       for (y = 0; y < TILE_Y; y++) {
            for (x = 0; x < TILE_X; x++)
-               *tb++ = pix_to_colormap(tile[y][x]);
+               tb[x] = pix_to_colormap(tile[y][x]);
+           tb += TILE_X * header.per_row;
+       }
+
+       /* repoint at the upper-left corner of the next tile */
+       *tb_ptr += TILE_X;
+       if (header.per_row == 1 || (total % header.per_row) == 0)
+           *tb_ptr += TILE_X * (TILE_Y - 1) * header.per_row;
+       tb = *tb_ptr;
     }
 
-    *tb_ptr = tb;      /* update return val */
     return count;
 }
 
@@ -108,9 +117,9 @@ process_file(fname)
     if (!fopen_text_file(fname, RDTMODE)) {
        Fprintf(stderr, "can't open file \"%s\"\n", fname);
        exit(1);
-       }
+    }
     merge_text_colormap();
-    count = convert_tiles(&curr_tb);
+    count = convert_tiles(&curr_tb, header.ntiles);
     Fprintf(stderr, "%s: %lu tiles\n", fname, count);
     header.ntiles += count;
     fclose_text_file();
@@ -122,7 +131,7 @@ static int
 xpm_write(fp)
 FILE *fp;
 {
-    int i,j,n;
+    int i, j, n;
 
     if (header.ncolors > 64) {
        Fprintf(stderr, "Sorry, only configured for up to 64 colors\n");
@@ -130,34 +139,32 @@ FILE *fp;
        /* All you need to do is add more char per color - below */
     }
 
-    fprintf(fp, "/* XPM */\n");
-    fprintf(fp, "static char* nhtiles[] = {\n");
-    fprintf(fp, "\"%lu %lu %lu %d\",\n",
-               header.tile_width,
-               header.tile_height*header.ntiles,
+    Fprintf(fp, "/* XPM */\n");
+    Fprintf(fp, "static char* nhtiles[] = {\n");
+    Fprintf(fp, "\"%lu %lu %lu %d\",\n",
+               header.tile_width*header.per_row,
+               (header.tile_height*header.ntiles)/header.per_row,
                header.ncolors,
                1 /* char per color */);
     for (i = 0; i < header.ncolors; i++)
-       fprintf(fp, "\"%c  c #%02x%02x%02x\",\n",
+       Fprintf(fp, "\"%c  c #%02x%02x%02x\",\n",
                i+'0', /* just one char per color */
                x11_colormap[i][0],
                x11_colormap[i][1],
                x11_colormap[i][2]);
 
-    n=0;
-    for (i = 0; i < header.tile_height*header.ntiles; i++) {
-       fprintf(fp, "\"");
-       for (j = 0; j < header.tile_width; j++) {
+    n = 0;
+    for (i = 0; i < (header.tile_height*header.ntiles)/header.per_row; i++) {
+       Fprintf(fp, "\"");
+       for (j = 0; j < header.tile_width*header.per_row; j++) {
            /* just one char per color */
            fputc(tile_bytes[n++]+'0', fp);
        }
-       if (j==header.tile_width-1)
-           fprintf(fp, "\"\n");
-       else
-           fprintf(fp, "\",\n");
+
+       Fprintf(fp, "\",\n");
     }
 
-    return fprintf(fp, "};\n")>=0;
+    return fprintf(fp, "};\n") >= 0;
 }
 #endif /* USE_XPM */
 
@@ -169,11 +176,12 @@ main(argc, argv)
     FILE *fp;
     int i;
 
-    header.version     = 1;
+    header.version     = 2;            /* version 1 had no per_row field */
     header.ncolors     = 0;
     header.tile_width  = TILE_X;
     header.tile_height = TILE_Y;
     header.ntiles      = 0;            /* updated as we read in files */
+    header.per_row     = TILES_PER_ROW;
 
     if (argc == 1) {
        Fprintf(stderr, "usage: %s txt_file1 [txt_file2 ...]\n", argv[0]);
@@ -184,12 +192,20 @@ main(argc, argv)
     if (!fp) {
        Fprintf(stderr, "can't open output file\n");
        exit(1);
-       }
+    }
+
+    /* don't leave garbage at end of partial row */
+    (void) memset((genericptr_t)tile_bytes, 0, sizeof(tile_bytes));
 
     for (i = 1; i < argc; i++)
        process_file(argv[i]);
     Fprintf(stderr, "Total tiles: %ld\n", header.ntiles);
 
+    /* round size up to the end of the row */
+    if ((header.ntiles % header.per_row) != 0) {
+       header.ntiles += header.per_row - (header.ntiles % header.per_row);
+    }
+
 #ifdef USE_XPM
     if (xpm_write(fp) == 0) {
        Fprintf(stderr, "can't write XPM file\n");
@@ -199,7 +215,7 @@ main(argc, argv)
     if (fwrite((char *)&header, sizeof(x11_header), 1, fp) == 0) {
        Fprintf(stderr, "can't open output header\n");
        exit(1);
-       }
+    }
 
     if (fwrite((char *)x11_colormap, 1, header.ncolors*3, fp) == 0) {
        Fprintf(stderr, "can't write output colormap\n");
index af83f100ec8ed43bc31d4dbbc0b4014e980f7721..dda4685bec22465c0af96c14cadcb839523353a2 100644 (file)
@@ -206,11 +206,11 @@ post_process_tiles()
     Display *dpy = XtDisplay(toplevel);
     unsigned int width, height;
 
-    height = tile_height * tile_count;
-    width  = tile_width;
-
     if (tile_image == 0) return;       /* no tiles */
 
+    height = tile_image->height;
+    width  = tile_image->width;
+
     tile_pixmap = XCreatePixmap(dpy, XtWindow(toplevel),
                        width,
                        height,
@@ -239,7 +239,10 @@ static boolean
 init_tiles(wp)
     struct xwindow *wp;
 {
-#ifndef USE_XPM
+#ifdef USE_XPM
+    XpmAttributes attributes;
+    int errorcode;
+#else
     FILE *fp = (FILE *)0;
     x11_header header;
     unsigned char *cp, *colormap = (unsigned char *)0;
@@ -248,13 +251,14 @@ init_tiles(wp)
     XColor *colors = (XColor *)0;
     int i, x, y;
     int bitmap_pad;
-    unsigned int image_height, image_width;
     int ddepth;
 #endif
+    char buf[BUFSZ];
     Display *dpy = XtDisplay(toplevel);
     Screen *screen = DefaultScreenOfDisplay(dpy);
     struct map_info_t *map_info = (struct map_info_t *)0;
     struct tile_map_info_t *tile_info = (struct tile_map_info_t *)0;
+    unsigned int image_height = 0, image_width = 0;
     boolean result = TRUE;
     XGCValues values;
     XtGCMask mask;
@@ -269,54 +273,63 @@ init_tiles(wp)
                                sizeof(struct tile_map_info_t));
 
 #ifdef USE_XPM
-    {
-       char buf[BUFSZ];
-       XpmAttributes attributes;
-       int errorcode;
+    attributes.valuemask = XpmCloseness;
+    attributes.closeness = 25000;
 
-       attributes.valuemask = XpmCloseness;
-       attributes.closeness = 25000;
+    errorcode = XpmReadFileToImage(dpy, appResources.tile_file,
+                                  &tile_image, 0, &attributes);
 
-       errorcode=XpmReadFileToImage(dpy,appResources.tile_file,&tile_image,0,&attributes);
+    if (errorcode == XpmColorFailed) {
+       Sprintf(buf, "Insufficient colors available to load %s.",
+               appResources.tile_file);
+       X11_raw_print(buf);
+       X11_raw_print("Try closing other colorful applications and restart.");
+       X11_raw_print("Attempting to load with inferior colors.");
+       attributes.closeness = 50000;
+       errorcode = XpmReadFileToImage(dpy, appResources.tile_file,
+                                      &tile_image, 0, &attributes);
+    }
 
+    if (errorcode != XpmSuccess) {
        if (errorcode == XpmColorFailed) {
-           Sprintf(buf, "Insufficient colors available to load %s.",appResources.tile_file);
+           Sprintf(buf, "Insufficient colors available to load %s.",
+                   appResources.tile_file);
+           X11_raw_print(buf);
+       } else {
+           Sprintf(buf, "Failed to load %s: %s", appResources.tile_file,
+                   XpmGetErrorString(errorcode));
            X11_raw_print(buf);
-           X11_raw_print("Try closing other colorful applications and restart.");
-           X11_raw_print("Attempting to load with inferior colors.");
-           attributes.closeness = 50000;
-           errorcode=XpmReadFileToImage(dpy,appResources.tile_file,&tile_image,0,&attributes);
        }
+       result = FALSE;
+       X11_raw_print("Switching to text-based mode.");
+       goto tiledone;
+    }
 
-       if (errorcode!=XpmSuccess) {
-           if (errorcode == XpmColorFailed) {
-               Sprintf(buf, "Insufficient colors available to load %s.",appResources.tile_file);
-               X11_raw_print(buf);
-           } else {
-               Sprintf(buf, "Failed to load %s: %s",appResources.tile_file,
-                       XpmGetErrorString(errorcode));
-               X11_raw_print(buf);
-           }
-           result = FALSE;
-           X11_raw_print("Switching to text-based mode.");
-           goto tiledone;
-       }
+    /* assume a fixed number of tiles per row */
+    if (tile_image->width % TILES_PER_ROW != 0) {
+       Sprintf(buf,
+               "%s is not a multiple of %d (number of tiles/row) pixels wide",
+               appResources.tile_file, TILES_PER_ROW);
+       X11_raw_print(buf);
+       XDestroyImage(tile_image);
+       tile_image = 0;
+       result = FALSE;
+       goto tiledone;
+    }
 
-       if (tile_image->height%total_tiles_used != 0) {
-           Sprintf(buf,
-               "%s is not a multiple of %d (the number of tiles) pixels high",
-               appResources.tile_file, total_tiles_used);
-           X11_raw_print(buf);
-           XDestroyImage(tile_image);
-           tile_image = 0;
-           result = FALSE;
-           goto tiledone;
-       }
+    /* infer tile dimensions from image size, assume square tiles */
+    image_width = tile_image->width;
+    image_height = tile_image->height;
+    tile_width = image_width / TILES_PER_ROW;
+    tile_height = tile_width;
+    tile_count = (image_width * image_height) / (tile_width * tile_height);
 
-       /* infer tile dimensions from image size */
-       tile_count=total_tiles_used;
-       tile_width=tile_image->width;
-       tile_height=tile_image->height/tile_count;
+    if (tile_count < total_tiles_used) {
+       Sprintf(buf, "%s incomplete, expecting %d tiles, found %d",
+               appResources.tile_file, total_tiles_used, tile_count);
+       X11_raw_print(buf);
+       result = FALSE;
+       goto tiledone;
     }
 #else
     /* any less than 16 colours makes tiles useless */
@@ -340,12 +353,21 @@ init_tiles(wp)
        goto tiledone;
     }
 
+    if (header.version != 2) {
+       Sprintf(buf, "Wrong tile file version, expected 2, got %lu",
+               header.version);
+       X11_raw_print(buf);
+       result = FALSE;
+       goto tiledone;
+    }
+
 # ifdef VERBOSE
-    fprintf(stderr, "X11 tile file:\n    version %ld\n    ncolors %ld\n    tile width %ld\n    tile height %ld\n    ntiles %ld\n",
+    fprintf(stderr, "X11 tile file:\n    version %ld\n    ncolors %ld\n    tile width %ld\n    tile height %ld\n    per row %ld\n    ntiles %ld\n",
        header.version,
        header.ncolors,
        header.tile_width,
        header.tile_height,
+       header.per_row,
        header.ntiles);
 # endif
 
@@ -374,9 +396,8 @@ init_tiles(wp)
        if (!XAllocColor(dpy, DefaultColormapOfScreen(screen), &colors[i]) &&
            !nhApproxColor(screen, DefaultColormapOfScreen(screen),
                           (char *)0, &colors[i])) {
-           char buf[BUFSZ];
            Sprintf(buf, "%dth out of %ld color allocation failed",
-               i, header.ncolors);
+                   i, header.ncolors);
            X11_raw_print(buf);
            result = FALSE;
            goto tiledone;
@@ -388,8 +409,11 @@ init_tiles(wp)
      * This alloc() and the one below require 32-bit ints, since tile_bytes
      * is currently ~200k and alloc() takes an int
      */
-    tile_bytes = (unsigned char *) alloc((unsigned)header.ntiles*size);
     tile_count = header.ntiles;
+    if ((tile_count % header.per_row) != 0) {
+       tile_count += header.per_row - (tile_count % header.per_row);
+    }
+    tile_bytes = (unsigned char *) alloc((unsigned)tile_count*size);
     if (fread((char *) tile_bytes, size, tile_count, fp) != tile_count) {
        X11_raw_print("read of tile bytes failed");
        result = FALSE;
@@ -397,7 +421,6 @@ init_tiles(wp)
     }
 
     if (header.ntiles < total_tiles_used) {
-       char buf[BUFSZ];
        Sprintf(buf, "tile file incomplete, expecting %d tiles, found %lu",
                total_tiles_used, header.ntiles);
        X11_raw_print(buf);
@@ -414,8 +437,8 @@ init_tiles(wp)
        tile_height = header.tile_height;
     }
 
-    image_height = tile_height * tile_count;
-    image_width  = tile_width;
+    image_height = tile_height * tile_count / header.per_row;
+    image_width  = tile_width * header.per_row;
 
     /* calculate bitmap_pad */
     if (ddepth > 16)
@@ -444,19 +467,19 @@ init_tiles(wp)
 
     if (appResources.double_tile_size) {
        unsigned long *expanded_row =
-           (unsigned long *)alloc(sizeof(unsigned long)*(unsigned)tile_width);
+           (unsigned long *)alloc(sizeof(unsigned long)*(unsigned)image_width);
 
        tb = tile_bytes;
        for (y = 0; y < image_height; y++) {
-           for (x = 0; x < header.tile_width; x++)
+           for (x = 0; x < image_width/2; x++)
                expanded_row[2*x] =
                            expanded_row[(2*x)+1] = colors[*tb++].pixel;
 
-           for (x = 0; x < tile_width; x++)
+           for (x = 0; x < image_width; x++)
                XPutPixel(tile_image, x, y, expanded_row[x]);
 
            y++;        /* duplicate row */
-           for (x = 0; x < tile_width; x++)
+           for (x = 0; x < image_width; x++)
                XPutPixel(tile_image, x, y, expanded_row[x]);
        }
        free((genericptr_t)expanded_row);
@@ -489,12 +512,8 @@ init_tiles(wp)
      */
     mask = GCFunction | GCForeground | GCGraphicsExposures;
     values.graphics_exposures = False;
-#if 1
     values.foreground = WhitePixelOfScreen(screen) ^
        XGetPixel(tile_image, 0, tile_height*glyph2tile[cmap_to_glyph(S_corr)]);
-#else
-    values.foreground = ~((unsigned long) 0);
-#endif
     values.function = GXxor;
     tile_info->white_gc = XtGetGC(wp->w, mask, &values);
 
@@ -502,7 +521,7 @@ init_tiles(wp)
     values.function = GXCopy;
     values.graphics_exposures = False;
     tile_info->black_gc = XtGetGC(wp->w, mask, &values);
-#endif
+#endif /* USE_WHITE */
 
 tiledone:
 #ifndef USE_XPM
@@ -517,6 +536,8 @@ tiledone:
        map_info->square_width = tile_width;
        map_info->square_ascent = 0;
        map_info->square_lbearing = 0;
+       tile_info->image_width = image_width;
+       tile_info->image_height = image_height;
     } else {
        if (tile_info) free((genericptr_t)tile_info);
        tile_info = 0;
@@ -905,7 +926,7 @@ get_char_info(wp)
 
 #ifdef VERBOSE
     printf("Font information:\n");
-    printf("fid = %d, direction = %d\n", fs->fid, fs->direction);
+    printf("fid = %ld, direction = %d\n", fs->fid, fs->direction);
     printf("first = %d, last = %d\n",
                        fs->min_char_or_byte2, fs->max_char_or_byte2);
     printf("all chars exist? %s\n", fs->all_chars_exist?"yes":"no");
@@ -917,7 +938,7 @@ get_char_info(wp)
                fs->max_bounds.lbearing, fs->max_bounds.rbearing,
                fs->max_bounds.width, fs->max_bounds.ascent,
                fs->max_bounds.descent, fs->max_bounds.attributes);
-    printf("per_char = 0x%x\n", fs->per_char);
+    printf("per_char = 0x%lx\n", (unsigned long) fs->per_char);
     printf("Text: (max) width = %d, height = %d\n",
            map_info->square_width, map_info->square_height);
 #endif
@@ -1174,28 +1195,26 @@ map_update(wp, start_row, stop_row, start_col, stop_col, inverted)
     if (map_info->is_tile) {
        struct tile_map_info_t *tile_map = map_info->mtype.tile_map;
        int cur_col;
-       Display* dpy=XtDisplay(wp->w);
-       Screen* screen=DefaultScreenOfDisplay(dpy);
+       Display* dpy = XtDisplay(wp->w);
+       Screen* screen = DefaultScreenOfDisplay(dpy);
 
        for (row = start_row; row <= stop_row; row++) {
            for (cur_col = start_col; cur_col <= stop_col; cur_col++) {
                int glyph = tile_map->glyphs[row][cur_col];
                int tile = glyph2tile[glyph];
+               int src_x, src_y;
                int dest_x = cur_col * map_info->square_width;
                int dest_y = row * map_info->square_height;
 
+               src_x = (tile % TILES_PER_ROW) * tile_width;
+               src_y = (tile / TILES_PER_ROW) * tile_height;
                XCopyArea(dpy, tile_pixmap, XtWindow(wp->w),
-                       tile_map->black_gc,     /* no grapics_expose */
-                       0,
-                       tile * map_info->square_height,
-                       tile_width, tile_height,
-                       dest_x,dest_y);
+                         tile_map->black_gc,   /* no grapics_expose */
+                         src_x, src_y,
+                         tile_width, tile_height,
+                         dest_x, dest_y);
 
-               if (glyph_is_pet(glyph)
-#ifdef TEXTCOLOR
-                       && iflags.hilite_pet
-#endif
-                       ) {
+               if (glyph_is_pet(glyph) && iflags.hilite_pet) {
                    /* draw pet annotation (a heart) */
                    XSetForeground(dpy, tile_map->black_gc, pet_annotation.foreground);
                    XSetClipOrigin(dpy, tile_map->black_gc, dest_x, dest_y);