xref: /plan9/sys/src/ape/lib/draw/colors.c (revision 40ef9009116dd37656783aaadc8782c1d8bfb056)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5 
6 char *argv0;
7 
8 static void
_sysfatalimpl(char * fmt,va_list arg)9 _sysfatalimpl(char *fmt, va_list arg)
10 {
11 	char buf[1024];
12 
13 	vseprint(buf, buf+sizeof(buf), fmt, arg);
14 	if(argv0)
15 		fprint(2, "%s: %s\n", argv0, buf);
16 	else
17 		fprint(2, "%s\n", buf);
18 	exits(buf);
19 }
20 
21 void (*_sysfatal)(char *fmt, va_list arg) = _sysfatalimpl;
22 
23 void
sysfatal(char * fmt,...)24 sysfatal(char *fmt, ...)
25 {
26 	va_list arg;
27 
28 	va_start(arg, fmt);
29 	(*_sysfatal)(fmt, arg);
30 	va_end(arg);
31 }
32 
33 int nbit, npix;
34 Image *pixel;
35 Rectangle crect[256];
36 
37 Image *color[256];
38 
39 void
eresized(int new)40 eresized(int new)
41 {
42 	int x, y, i, n, nx, ny;
43 	Rectangle r, b;
44 
45 	if(new && getwindow(display, Refnone) < 0){
46 		fprint(2, "colors: can't reattach to window: %r\n");
47 		exits("resized");
48 	}
49 	if(screen->depth > 8){
50 		n = 256;
51 		nx = 16;
52 	}else{
53 		n = 1<<screen->depth;
54 		nx = 1<<(screen->depth/2);
55 	}
56 
57 	ny = n/nx;
58 	draw(screen, screen->r, display->white, nil, ZP);
59 	r = insetrect(screen->r, 5);
60 	r.min.y+=20;
61 	b.max.y=r.min.y;
62 	for(i=n-1, y=0; y!=ny; y++){
63 		b.min.y=b.max.y;
64 		b.max.y=r.min.y+(r.max.y-r.min.y)*(y+1)/ny;
65 		b.max.x=r.min.x;
66 		for(x=0; x!=nx; x++, --i){
67 			b.min.x=b.max.x;
68 			b.max.x=r.min.x+(r.max.x-r.min.x)*(x+1)/nx;
69 			crect[i]=insetrect(b, 1);
70 			draw(screen, crect[i], color[i], nil, ZP);
71 		}
72 	}
73 	flushimage(display, 1);
74 }
75 
76 char *buttons[] =
77 {
78 	"exit",
79 	0
80 };
81 
82 ulong
grey(int i)83 grey(int i)
84 {
85 	if(i < 0)
86 		return grey(0);
87 	if(i > 255)
88 		return grey(255);
89 	return (i<<16)+(i<<8)+i;
90 }
91 
92 Menu menu =
93 {
94 	buttons
95 };
96 
97 int
98 dither[16] =  {
99 	0, 8, 2, 10,
100 	12, 4, 14, 6,
101 	3, 11, 1, 9,
102 	15, 7, 13, 5
103 };
104 
105 void
main(int argc,char * argv[])106 main(int argc, char *argv[])
107 {
108 	Point p;
109 	Mouse m;
110 	int i, j, k, l, n, ramp, prev;
111 	char buf[100];
112 	char *fmt;
113 	Image *dark;
114 	ulong rgb;
115 
116 	ramp = 0;
117 
118 	fmt = "index %3d r %3lud g %3lud b %3lud 0x%.8luX        ";
119 /*
120 	ARGBEGIN{
121 	default:
122 		goto Usage;
123 	case 'x':
124 		fmt = "index %2luX r %3luX g %3luX b %3luX 0x%.8luX       ";
125 		break;
126 	case 'r':
127 		ramp = 1;
128 		break;
129 	}ARGEND
130 */
131 	argv0 = argv[0];
132 	if(argc != 1){
133 	Usage:
134 		fprint(2, "Usage: %s [-rx]\n", argv0);
135 		exits("usage");
136 	}
137 
138 	if(initdraw(nil, nil, "colors") < 0)
139 		sysfatal("initdraw failed: %r");
140 	einit(Emouse);
141 
142 	for(i=0; i<256; i++){
143 		if(ramp){
144 			if(screen->chan == CMAP8){
145 				/* dither the fine grey */
146 				j = i-(i%17);
147 				dark = allocimage(display, Rect(0,0,1,1), screen->chan, 1, (grey(j)<<8)+0xFF);
148 				color[i] = allocimage(display, Rect(0,0,4,4), screen->chan, 1, (grey(j+17)<<8)+0xFF);
149 				for(j=0; j<16; j++){
150 					k = j%4;
151 					l = j/4;
152 					if(dither[j] > (i%17))
153 						draw(color[i], Rect(k, l, k+1, l+1), dark, nil, ZP);
154 				}
155 				freeimage(dark);
156 			}else
157 				color[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, (grey(i)<<8)+0xFF);
158 		}else
159 			color[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, (cmap2rgb(i)<<8)+0xFF);
160 		if(color[i] == nil)
161 			sysfatal("can't allocate image: %r");
162 	}
163 	eresized(0);
164 	prev = -1;
165 	for(;;){
166 		m = emouse();
167 		switch(m.buttons){
168 		case 1:
169 			while(m.buttons){
170 				if(screen->depth > 8)
171 					n = 256;
172 				else
173 					n = 1<<screen->depth;
174 				for(i=0; i!=n; i++)
175 					if(i!=prev && ptinrect(m.xy, crect[i])){
176 						if(ramp)
177 							rgb = grey(i);
178 						else
179 							rgb = cmap2rgb(i);
180 						sprint(buf, fmt,
181 							i,
182 							(rgb>>16)&0xFF,
183 							(rgb>>8)&0xFF,
184 							rgb&0xFF,
185 							(rgb<<8) | 0xFF);
186 						p = addpt(screen->r.min, Pt(2,2));
187 						draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->white, nil, p);
188 						string(screen, p, display->black, ZP, font, buf);
189 						prev=i;
190 						break;
191 					}
192 				m = emouse();
193 			}
194 			break;
195 
196 		case 4:
197 			switch(emenuhit(3, &m, &menu)){
198 			case 0:
199 				exits(0);
200 			}
201 		}
202 	}
203 }
204