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