1 #include "config.h"
2 
3 /* do not change anything below this, unless you know what you're doing */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <math.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include <xpm.h>
12 
13 #include "largeclub.bm"
14 #include "largespade.bm"
15 #include "largeheart.bm"
16 #include "largediamond.bm"
17 #include "largerank.bm"
18 
19 #define RANK_WIDTH 9
20 #define RANK_HEIGHT 14
21 
22 static unsigned char grey[90][90];
23 static int size[] = { 0, 41, 21, 15, 11 };
24 
bitmap_to_grey(char * bm,int w,int h,int scale,int scanline)25 static void bitmap_to_grey(char *bm, int w, int h, int scale, int scanline) {
26     int i, j;
27     char *b, *bb;
28     unsigned char *g, *gg;
29     int scancol, scancol0;
30 
31     memset(grey, 0, sizeof(grey));
32     b = bm;
33     if (scanline == -1) {
34 	scanline = 0;
35 	scancol0 = 0;
36 	g = grey[0];
37     } else {
38 	i = (scale * size[scale/2] - w) / 2;
39 	scancol0 = i % scale;
40 	g = grey[(82-h)/scale] + i / scale;
41     }
42 
43     /* make a picture of bitmap, offsetting it (scanline, scancol0) */
44     --scanline;
45     for (i = 0; i < h; ++i) {
46 	int c;
47 	/* start a new scanline */
48 	if (++scanline >= scale) {
49 	    scanline -= scale;
50 	    g += 90;
51 	}
52 	gg = g;		/* restart at this line */
53 	bb = b;
54 	scancol = scancol0 - 1;
55 	/* first, skip xoffset pixel */
56 	for (j = 0; j < w; ++j) {
57 	    if (++scancol >= scale) {
58 		++gg;
59 		scancol -= scale;
60 	    }
61 	    if (!(j % 8))
62 		c = *bb++;
63 	    /* c has bit in pos 0 */
64 	    if (c & 1)
65 		++*gg;
66 	    c >>= 1;
67 	}
68 	b += (w + 7) >> 3;
69     }
70 }
71 
72 struct longcolor {
73     long red, green, blue;
74 };
75 
76 static Display *dpy;
77 static unsigned int screen;
78 static Drawable w;
79 static GC gc;
80 static unsigned long black_ramp[NUM_BLACK_COLORS+1],
81     red_ramp[NUM_RED_COLORS+1];
82 
make_ramp(int numcolors,unsigned long * xcolors,struct longcolor bg,struct longcolor fg)83 static void make_ramp(int numcolors, unsigned long *xcolors,
84 	      struct longcolor bg, struct longcolor fg) {
85     XColor color;
86     Colormap cmap;
87     int i;
88 
89     cmap = XDefaultColormap(dpy, screen);
90     color.flags = DoRed|DoGreen|DoBlue;
91 
92     for (i = 0; i <= numcolors; ++i) {
93 	color.red   = ((numcolors-i) * bg.red   + i * fg.red)   / numcolors;
94 	color.green = ((numcolors-i) * bg.green + i * fg.green) / numcolors;
95 	color.blue  = ((numcolors-i) * bg.blue  + i * fg.blue)  / numcolors;
96 	/* printf("r/g/b = %04x/%04x/%04x yields ", color.red,
97 	     color.green, color.blue); */
98 	if (!XAllocColor(dpy, cmap, &color)) {
99 	    fprintf(stderr, "Error! Cannot allocate color cell!\n");
100 	    exit(1);
101 	}
102 	/* printf("%04x/%04x/%04x\n", color.red, color.green, color.blue); */
103 	xcolors[i] = color.pixel;
104     }
105 }
106 
connect(int view,int width,int height,char * name)107 static void connect(int view, int width, int height, char *name) {
108     Window root;
109     Pixmap p;
110 
111     if(!(dpy = XOpenDisplay(NULL))) {
112 	fprintf( stderr, "cannot open display\n");
113 	exit(EXIT_FAILURE);
114     }
115     screen = XDefaultScreen(dpy);
116     gc = XDefaultGC(dpy, screen);
117     root = RootWindow(dpy, screen);
118 
119     if (!view) {
120 	p = XCreatePixmap(dpy, root, width, height, DefaultDepth(dpy, screen));
121 	w = p;
122     } else {
123 	Window win;
124 	XGCValues gcv;
125 	unsigned long w_mask, gc_mask;
126 	XSizeHints xsh;
127 	XWMHints xwmh = {
128 	    (InputHint|StateHint),
129 	    True,
130 	    NormalState,
131 	    0,0,0,0,0,0 };
132 
133 	w_mask = CWColormap|CWBackPixel;
134 	xsh.flags = PPosition | PSize;
135 	xsh.width = width;
136 	xsh.height = height;
137 	xsh.x = 100;
138 	xsh.y = 200;
139 
140 	win = XCreateSimpleWindow(dpy, root, xsh.x,xsh.y,xsh.width,
141 				  xsh.height, 0,
142 				  WhitePixel(dpy, screen),
143 				  BlackPixel(dpy, screen));
144 	XSetStandardProperties(dpy, win, name, name, None, NULL, 0, &xsh);
145 	XSetWMHints(dpy, win, &xwmh);
146 	XSelectInput(dpy, win, ExposureMask|ButtonPressMask);
147 	XMapRaised(dpy, win);
148 	w = win;
149 	gcv.function = GXcopy;
150 	gcv.plane_mask = AllPlanes;
151 	gcv.line_width = 0;
152 	gcv.line_style = LineSolid;
153 	gcv.join_style = JoinMiter;
154 	gcv.fill_style = FillSolid;
155 	gc_mask = GCFunction|GCPlaneMask|GCLineWidth|GCLineStyle|GCJoinStyle|GCFillStyle;
156 	XChangeGC(dpy, gc, gc_mask, &gcv);
157     }
158 }
159 
wait_for_event(void)160 static void wait_for_event(void) {
161     XEvent event;
162     do {
163 	XNextEvent(dpy, &event);
164 	if (event.type == ButtonPress)
165 	    exit(0);
166     } while (event.type != Expose || event.xexpose.count != 0);
167 
168     /* skip coming events */
169     while(XCheckTypedEvent(dpy, Expose, &event))
170 	;
171 }
172 
173 
174 
175 
paintsuit(char * bits,int width,int height,int y,int scale,int suit)176 static void paintsuit(char *bits, int width, int height, int y,
177 		      int scale, int suit) {
178     int i, j, this;
179     this = size[scale];
180     bitmap_to_grey(bits, width, height, 2*scale, scale*this - 41);
181     for (i = 0; i < this; ++i)
182 	for (j = 0; j < this; ++j) {
183 	    if (suit < 2)
184 		XSetForeground(dpy, gc, black_ramp[(((int)grey[j][i]
185 		   * NUM_BLACK_COLORS / scale / scale) + 2) / 4]);
186 	    else
187 		XSetForeground(dpy, gc, red_ramp[(((int)grey[j][i]
188 		   * NUM_RED_COLORS / scale / scale) + 2) / 4]);
189 	    /* single pixels: (O'Reilly Xlib PM 3rd ed., p. 738) */
190 	    XFillRectangle(dpy, w, gc, suit*this+i,       y+j,        1, 1);
191 	    if (scale > 1)
192 	    XFillRectangle(dpy, w, gc, (suit+5)*this-i-1, y+this-1-j, 1, 1);
193 	}
194 }
195 
paint(int width,int height)196 static void paint(int width, int height) {
197     int scale, y;
198 
199     XSetForeground(dpy, gc, black_ramp[0]);
200     XFillRectangle(dpy, w, gc, 0, 0, width, height);
201 
202     y = 0;
203     for (scale = 1; scale <= 4; ++scale) {
204 	paintsuit(largeclub_bits, largeclub_width, largeclub_height,
205 		  y, scale, 0);
206 	paintsuit(largespade_bits, largespade_width, largespade_height,
207 		  y, scale, 1);
208 	paintsuit(largeheart_bits, largeheart_width, largeheart_height,
209 		  y, scale, 2);
210 	paintsuit(largediamond_bits, largediamond_width, largediamond_height,
211 		  y, scale, 3);
212 	y += size[scale];
213     }
214 }
215 
paintrank(int width,int height)216 static void paintrank(int width, int height) {
217     int i, j, scale;
218     XSetForeground(dpy, gc, black_ramp[0]);
219     XFillRectangle(dpy, w, gc, 0, 0, width, height);
220     scale = largerank_width / 9 / 3;
221     if ((scale & 1) ||
222 	scale * 9 * 3 != largerank_width ||
223 	scale * 14 * 5 != largerank_height)
224 	fprintf(stderr, "Please check your scale. I'm getting weird results\n");
225     scale /= 2;
226     bitmap_to_grey(largerank_bits, largerank_width, largerank_height, 2*scale, -1);
227     for (i = 0; i < 3*RANK_WIDTH; ++i)
228 	for (j = 0; j < 5*RANK_HEIGHT; ++j) {
229 	    XSetForeground(dpy, gc, black_ramp[(((int)grey[j][i] * NUM_BLACK_COLORS
230 		/ scale / scale) + 2) / 4]);
231 	    XFillRectangle(dpy, w, gc, i,                j,                 1, 1);
232 	    XFillRectangle(dpy, w, gc, 9*RANK_WIDTH-i-1, 5*RANK_HEIGHT-1-j, 1, 1);
233 	    XSetForeground(dpy, gc, red_ramp[(((int)grey[j][i] * NUM_RED_COLORS
234 	        / scale / scale) + 2) / 4]);
235 	    XFillRectangle(dpy, w, gc, 3*RANK_WIDTH+i,   j,                 1, 1);
236 	    XFillRectangle(dpy, w, gc,12*RANK_WIDTH-i-1, 5*RANK_HEIGHT-1-j, 1, 1);
237 	}
238 }
239 
writefile(const char * filename)240 static void writefile(const char *filename) {
241     static int is_written = 0;
242     if (!is_written) {
243 	is_written = 1;
244 	if (XpmWriteFileFromPixmap(dpy, filename, w, 0, NULL) != XpmSuccess)
245 	    fprintf(stderr, "error writing xpm file %s\n", filename);
246     }
247 }
248 
main(int argc,char * argv[])249 int main(int argc, char *argv[]) {
250     char *p;
251     static struct longcolor red = RED_COLOR, black = BLACK_COLOR,
252        bg = WHITE_COLOR;
253     int view = 0, do_rank = 0;
254     int width = 168, height = 88;
255 
256     p = strrchr(argv[0], '/');
257     p = p ? p+1 : argv[0];
258     if (!strcmp(p, "rank")) {
259 	do_rank = 1;
260 	width = 12 * RANK_WIDTH;
261 	height = 5 * RANK_HEIGHT;
262     }
263     if (argc == 2 && !strcmp(argv[1], "-v"))
264 	view = 1;
265     else if (argc != 1) {
266 	fprintf(stderr, "usage: %s [-v]\n", p);
267 	exit(1);
268     }
269 
270     connect(view, width, height, p);
271     make_ramp(NUM_BLACK_COLORS, black_ramp, bg, black);
272     make_ramp(NUM_RED_COLORS, red_ramp, bg, red);
273     do {
274 	if (view)
275 	    wait_for_event();
276 	if (do_rank) {
277 	    paintrank(width, height);
278 	    writefile("Ranks.xpm");
279 	} else {
280 	    paint(width, height);
281 	    writefile("Suits.xpm");
282 	}
283     } while (view);
284     return 0;
285 }
286