From d98c30d989f09904fb3f27f9e39d966609bf89a5 Mon Sep 17 00:00:00 2001 From: jwalz Date: Wed, 20 Mar 2002 03:50:49 +0000 Subject: [PATCH] 's new files. --- win/gem/gr_rect.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++ win/gem/gr_rect.h | 14 ++++ win/gem/xpm2img.c | 164 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 359 insertions(+) create mode 100644 win/gem/gr_rect.c create mode 100644 win/gem/gr_rect.h create mode 100644 win/gem/xpm2img.c diff --git a/win/gem/gr_rect.c b/win/gem/gr_rect.c new file mode 100644 index 000000000..0dbe49a1b --- /dev/null +++ b/win/gem/gr_rect.c @@ -0,0 +1,181 @@ +/* SCCS Id: @(#)gr_rect.c 3.4 2001/12/10 */ +/* Copyright (c) Christian Bressler, 2001 */ +/* NetHack may be freely redistributed. See license for details. */ +/* This is an almost exact copy of qt_clust.cpp */ +/* gr_rect.c */ +#include +#include +#include +#include "gr_rect.h" +dirty_rect *new_dirty_rect(int size){ + dirty_rect *new=NULL; + if(size>0){ + new=(dirty_rect *)calloc(1L,sizeof(dirty_rect)); + if(new){ + new->rects=(GRECT *)calloc((long)size,sizeof(GRECT)); + if(new->rects==NULL){ + free(new); + return(NULL); + } + new->max=size; + } + } + return(new); +} +void delete_dirty_rect(dirty_rect *this){ + if(this==NULL) + return; + if(this->rects) + free(this->rects); + /* In case the Pointer is reused wrongly */ + this->rects=NULL; + this->max=0; + this->used=0; + free(this); +} +static int gc_inside(GRECT *frame,GRECT *test); +static int gc_touch(GRECT *frame,GRECT *test); +static void gc_combine(GRECT *frame,GRECT *test); +static long gc_area(GRECT *area); +int add_dirty_rect(dirty_rect *dr,GRECT *area){ + int cursor; + long lowestcost=9999999L; + int cheapest=-1; + int cheapestmerge1=-1; + int cheapestmerge2=-1; + int merge1; + int merge2; + for (cursor=0; cursorused; cursor++) { + if (gc_inside(&dr->rects[cursor],area)) { + /* Wholly contained already. */ + return(TRUE); + } + } + for (cursor=0; cursorused; cursor++) { + if (gc_touch(&dr->rects[cursor],area)) { + GRECT larger=dr->rects[cursor]; + long cost; + gc_combine(&larger,area); + cost=gc_area(&larger)-gc_area(&dr->rects[cursor]); + if (cost < lowestcost) { + int bad=FALSE,c; + for (c=0; cused && !bad; c++) { + bad=gc_touch(&dr->rects[c],&larger) && c!=cursor; + } + if (!bad) { + cheapest=cursor; + lowestcost=cost; + } + } + } + } + if (cheapest>=0) { + gc_combine(&dr->rects[cheapest],area); + return(TRUE); + } + if (dr->used < dr->max) { + dr->rects[dr->used++]=*area; + return(TRUE); + } + // Do cheapest of: + // add to closest cluster + // do cheapest cluster merge, add to new cluster + lowestcost=9999999L; + cheapest=-1; + for (cursor=0; cursorused; cursor++) { + GRECT larger=dr->rects[cursor]; + long cost; + gc_combine(&larger,area); + cost=gc_area(&larger)-gc_area(&dr->rects[cursor]); + if (cost < lowestcost) { + int bad=FALSE, c; + for (c=0; cused && !bad; c++) { + bad=gc_touch(&dr->rects[c],&larger) && c!=cursor; + } + if (!bad) { + cheapest=cursor; + lowestcost=cost; + } + } + } + // XXX could make an heuristic guess as to whether we + // XXX need to bother looking for a cheap merge. + for (merge1=0; merge1used; merge1++) { + for (merge2=0; merge2used; merge2++) { + if (merge1!=merge2) { + GRECT larger=dr->rects[merge1]; + long cost; + gc_combine(&larger,&dr->rects[merge2]); + cost=gc_area(&larger)-gc_area(&dr->rects[merge1])-gc_area(&dr->rects[merge2]); + if (cost < lowestcost) { + int bad=FALSE, c; + for (c=0; cused && !bad; c++) { + bad=gc_touch(&dr->rects[c],&larger) && c!=cursor; + } + if (!bad) { + cheapestmerge1=merge1; + cheapestmerge2=merge2; + lowestcost=cost; + } + } + } + } + } + if (cheapestmerge1>=0) { + gc_combine(&dr->rects[cheapestmerge1],&dr->rects[cheapestmerge2]); + dr->rects[cheapestmerge2]=dr->rects[dr->used-1]; + dr->rects[dr->used-1]=*area; + } else { + gc_combine(&dr->rects[cheapest],area); + } + // NB: clusters do not intersect (or intersection will + // overwrite). This is a result of the above algorithm, + // given the assumption that (x,y) are ordered topleft + // to bottomright. + return(TRUE); +} +int get_dirty_rect(dirty_rect* dr,GRECT *area){ + if(dr==NULL || area==NULL || dr->rects==NULL || dr->used<=0 || dr->max<=0) + return(FALSE); + *area=dr->rects[--dr->used]; + return(TRUE); +} +int clear_dirty_rect(dirty_rect *dr){ + if(dr) + dr->used=0; + return(TRUE); +} +int resize_dirty_rect(dirty_rect *dr,int new_size){ + return(FALSE); +} +static int gc_inside(GRECT *frame,GRECT *test){ + if(frame && test && frame->g_x<=test->g_x && frame->g_y<=test->g_y && + frame->g_x+frame->g_w>=test->g_x+test->g_w && + frame->g_y+frame->g_h>=test->g_y+test->g_h + ) + return(TRUE); + return(FALSE); +} +static int gc_touch(GRECT *frame,GRECT *test){ + GRECT tmp={test->g_x-1,test->g_y-1,test->g_w+2,test->g_h+2}; + return(rc_intersect(frame,&tmp)); +} +static void gc_combine(GRECT *frame,GRECT *test){ + if(!frame || !test) + return; + if(frame->g_x>test->g_x){ + frame->g_w+=frame->g_x-test->g_x; + frame->g_x=test->g_x; + } + if(frame->g_y>test->g_y){ + frame->g_h+=frame->g_y-test->g_y; + frame->g_y=test->g_y; + } + if(frame->g_x+frame->g_wg_x+test->g_w) + frame->g_w=test->g_x+test->g_w-frame->g_x; + if(frame->g_y+frame->g_hg_y+test->g_h) + frame->g_h=test->g_y+test->g_h-frame->g_y; +} +static long gc_area(GRECT *area){ + return((long)area->g_h*(long)area->g_w); +} diff --git a/win/gem/gr_rect.h b/win/gem/gr_rect.h new file mode 100644 index 000000000..0e4a0bdc8 --- /dev/null +++ b/win/gem/gr_rect.h @@ -0,0 +1,14 @@ +/* gr_rect.h */ +#include +/********** structs **********/ +typedef struct { + GRECT *rects; + int max,used; +} dirty_rect; +/********* functions ************/ +dirty_rect *new_dirty_rect(int size); +void delete_dirty_rect(dirty_rect *this); +int add_dirty_rect(dirty_rect *dr,GRECT *area); +int get_dirty_rect(dirty_rect* dr,GRECT *area); +int clear_dirty_rect(dirty_rect *dr); +int resize_dirty_rect(dirty_rect *dr,int new_size); diff --git a/win/gem/xpm2img.c b/win/gem/xpm2img.c new file mode 100644 index 000000000..605d5db09 --- /dev/null +++ b/win/gem/xpm2img.c @@ -0,0 +1,164 @@ +/* SCCS Id: @(#)xpm2img.c 3.4 2002/03/17 */ +/* Copyright (c) Christian Bressler 2002 */ +/* NetHack may be freely redistributed. See license for details. */ +/* This is mainly a reworked tile2bmp.c + xpm2iff.c -- Marvin */ +#include +#include +#include +#include "bitmfile.h" +#define TRUE 1 +#define FALSE 0 +void get_color(unsigned int colind, struct RGB *rgb); +void get_pixel(int x, int y, unsigned int *colind); +char *xpmgetline(); +unsigned int **Bild_daten; +/* translation table from xpm characters to RGB and colormap slots */ +struct Ttable { + char flag; + struct RGB col; + int slot; /* output colortable index */ +}ttable[256]; +struct RGB *ColorMap; +int num_colors = 0; +int width=0, height=0; +int initflag; +FILE *fp; +int +main(argc, argv) +int argc; +char *argv[]; +{ + int i; + int row, col, planeno; + int farben, planes; + if (argc != 3) { + fprintf(stderr, "usage: tile2img infile.xpm outfile.img\n"); + exit(EXIT_FAILURE); + } + initflag = 0; + fp = fopen(argv[2],"wb"); + if (!fp) { + printf("Error creating IMG-file %s, aborting.\n",argv[2]); + exit(EXIT_FAILURE); + } + fclose(fp); + if(fopen_xpm_file(argv[1],"r")!=TRUE){ + printf("Error reading xpm-file %s, aborting.\n",argv[1]); + exit(EXIT_FAILURE); + } + Bild_daten=(unsigned int **)malloc((long)height*sizeof(unsigned int *)); + for(i=0;i256){ + fprintf(stderr,"ERROR: zuviele Farben\n"); + exit(EXIT_FAILURE); + }else if(num_colors>16){ + farben=256; + planes=8; + }else if(num_colors>2){ + farben=16; + planes=4; + }else{ + farben=2; + planes=1; + } + bitmap_to_file(XIMG, width, height, 372, 372, planes, farben, argv[2], get_color, get_pixel ); + exit(EXIT_SUCCESS); + /*NOTREACHED*/ + return 0; +} +void get_color(unsigned int colind, struct RGB *rgb){ + rgb->r=(1000L*(long)ColorMap[colind].r)/0xFF; + rgb->g=(1000L*(long)ColorMap[colind].g)/0xFF; + rgb->b=(1000L*(long)ColorMap[colind].b)/0xFF; +} +void get_pixel(int x, int y, unsigned int *colind){ + *colind=Bild_daten[y][x]; +} +FILE *xpmfh = 0; +char initbuf[200]; +char *xpmbuf = initbuf; +/* version 1. Reads the raw xpm file, NOT the compiled version. This is + * not a particularly good idea but I don't have time to do the right thing + * at this point, even if I was absolutely sure what that was. */ +fopen_xpm_file(const char *fn, const char *mode){ + int temp; + char *xb; + if(strcmp(mode, "r"))return FALSE; /* no choice now */ + if(xpmfh)return FALSE; /* one file at a time */ + xpmfh = fopen(fn, mode); + if(!xpmfh)return FALSE; /* I'm hard to please */ + /* read the header */ + xb = xpmgetline(); + if(xb == 0)return FALSE; + if(4 != sscanf(xb,"%d %d %d %d", + &width, &height,&num_colors, &temp)) + return FALSE; /* bad header */ + /* replace the original buffer with one big enough for + * the real data + */ +/* XXX */ + xpmbuf = malloc(width * 2); + if(!xpmbuf){ + fprintf(stderr,"ERROR: Can't allocate line buffer\n"); + exit(1); + } + if(temp != 1)return FALSE; /* limitation of this code */ + { + /* read the colormap and translation table */ + int ccount = -1; + ColorMap = (struct RGB *)malloc((long)num_colors*sizeof(struct RGB)); + while(ccount++ < (num_colors-1)){ + char index; + int r, g, b; + xb = xpmgetline(); + if(xb==0)return FALSE; + if(4 != sscanf(xb,"%c c #%2x%2x%2x",&index,&r,&g,&b)){ + fprintf(stderr,"Bad color entry: %s\n",xb); + return FALSE; + } + ttable[index].flag = 1; /* this color is valid */ + ttable[index].col.r = r; + ttable[index].col.g = g; + ttable[index].col.b = b; + ttable[index].slot = ccount; + ColorMap[ccount].r=r; + ColorMap[ccount].g=g; + ColorMap[ccount].b=b; + } + } + return TRUE; +} +/* This deserves better. Don't read it too closely - you'll get ill. */ +#define bufsz 2048 +char buf[bufsz]; +char * +xpmgetline(){ + char *bp; + do { + if(fgets(buf, bufsz, xpmfh) == 0)return 0; + } while(buf[0] != '"'); + /* strip off the trailing <",> if any */ + for(bp = buf;*bp;bp++); + bp--; + while(isspace(*bp))bp--; + if(*bp==',')bp--; + if(*bp=='"')bp--; + bp++; + *bp = '\0'; + return &buf[1]; +}