New upstream version 3.1.1
[xfishtank.git] / src / ixpm.c
1 /* -copyright-
2 #-# Copyright © 2021 Eric Bina, Dave Black, TJ Phan,
3 #-# Vincent Renardias, Willem Vermin
4 #-#
5 #-# Permission is hereby granted, free of charge, to any person
6 #-# obtaining a copy of this software and associated documentation
7 #-# files (the “Software”), to deal in the Software without
8 #-# restriction, including without limitation the rights to use,
9 #-# copy, modify, merge, publish, distribute, sublicense, and/or
10 #-# sell copies of the Software, and to permit persons to whom
11 #-# the Software is furnished to do so, subject to the following
12 #-# conditions:
13 #-#
14 #-# The above copyright notice and this permission notice shall
15 #-# be included in all copies or substantial portions of the Software.
16 #-#
17 #-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
18 #-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 #-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 #-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 #-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 #-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 #-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 #-# OTHER DEALINGS IN THE SOFTWARE.
25 #-#
26 */
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 #include "ixpm.h"
32 #include "debug.h"
33 #include "utils.h"
34 // from the xpm package:
35 static void xpmCreatePixmapFromImage(
36 Display *display,
37 Drawable d,
38 XImage *ximage,
39 Pixmap *pixmap_return)
40 {
41 GC gc;
42 XGCValues values;
43
44 *pixmap_return = XCreatePixmap(display, d, ximage->width,
45 ximage->height, ximage->depth);
46 /* set fg and bg in case we have an XYBitmap */
47 values.foreground = 1;
48 values.background = 0;
49 gc = XCreateGC(display, *pixmap_return,
50 GCForeground | GCBackground, &values);
51
52 XPutImage(display, *pixmap_return, gc, ximage, 0, 0, 0, 0,
53 ximage->width, ximage->height);
54
55 XFreeGC(display, gc);
56 }
57
58 void paintit(XImage *img, long int color)
59 {
60 int x,y;
61 for (y=0; y<img->height; y++)
62 for (x=0; x<img->width; x++)
63 {
64 XPutPixel(img, x,y,color);
65 }
66 }
67
68
69 // reverse characters in string, characters taken in chunks of l
70 // if you know what I mean
71 static void strrevert(char*s, size_t l)
72 {
73 assert(l>0);
74 size_t n = strlen(s)/l;
75 size_t i;
76 char *c = (char *)malloc(l*sizeof(*c));
77 char *a = s;
78 char *b = s+strlen(s)-l;
79 for (i=0; i<n/2; i++)
80 {
81 strncpy(c,a,l);
82 strncpy(a,b,l);
83 strncpy(b,c,l);
84 a+=l;
85 b-=l;
86 }
87 free(c);
88 }
89
90 //
91 // equal to XpmCreatePixmapFromData, with extra flags:
92 // flop: if 1, reverse the data horizontally
93 // Extra: 0xff000000 is added to the pixmap data
94 //
95 int iXpmCreatePixmapFromData(Display *display, Drawable d,
96 const char *data[], Pixmap *p, Pixmap *s, XpmAttributes *attr, int flop)
97 {
98 int rc, lines, i, ncolors, height, w;
99 char **idata;
100
101 sscanf(data[0],"%*s %d %d %d", &height, &ncolors, &w);
102 lines = height+ncolors+1;
103 assert(lines>0);
104 idata = (char **)malloc(lines*sizeof(*idata));
105 for (i=0; i<lines; i++)
106 idata[i] = strdup(data[i]);
107 if(flop)
108 // flop the image data
109 for (i=1+ncolors; i<lines; i++)
110 strrevert(idata[i],w);
111
112 XImage *ximage,*shapeimage;
113 rc = XpmCreateImageFromData(display,idata,&ximage,&shapeimage,attr);
114 if (rc != 0)
115 {
116 I("rc from XpmCreateImageFromData: ");
117 switch (rc)
118 {
119 case 1:
120 printf("XpmColorError\n");
121 for (i=0; i<lines; i++)
122 printf("\"%s\",\n",idata[i]);
123 break;
124 case -1:
125 printf("XpmOpenFailed\n");
126 break;
127 case -2:
128 printf("XpmFileInvalid\n");
129 break;
130 case -3:
131 printf("XpmNoMemory: maybe issue with width of data: w=%d\n",w);
132 break;
133 case -4:
134 printf("XpmColorFailed\n");
135 for (i=0; i<lines; i++)
136 printf("\"%s\",\n",idata[i]);
137 break;
138 default:
139 printf("%d\n",rc);
140 break;
141 }
142 printf("exiting\n");
143 fflush(NULL);
144 abort();
145 }
146 XAddPixel(ximage,0xff000000);
147 if(p)
148 xpmCreatePixmapFromImage(display, d, ximage, p);
149 if(s)
150 xpmCreatePixmapFromImage(display, d, shapeimage, s);
151 XDestroyImage(ximage);
152 XDestroyImage(shapeimage);
153 for(i=0; i<lines; i++) free(idata[i]);
154 free(idata);
155 return rc;
156 }
157
158 // given xpmdata **data, add the non-transparent pixels to Region r
159 Region regionfromxpm(const char **data, int flop)
160 {
161 int w,h,nc,n;
162 Region r = XCreateRegion();
163 // width, height, #colors, $chars to code color
164 sscanf(*data,"%d %d %d %d",&w,&h,&nc,&n);
165 // find color "None":
166 int i;
167 char *code = (char *)"";
168 int offset = nc + 1;
169 for(i=1; i<=nc; i++)
170 {
171 char s[100];
172 P("%s\n",data[i]);
173 sscanf(data[i]+n,"%*s %100s",s);
174 P("%s\n",s);
175 if(!strcasecmp(s,"None"))
176 {
177 code = strndup(data[i],n);
178 break;
179 }
180 }
181 XRectangle rect;
182 rect.width = 1;
183 rect.height = 1;
184 int y;
185 for (y=0; y<h; y++)
186 {
187 int x;
188 char*s = strdup(data[y+offset]);
189 if(flop)
190 strrevert(s,n);
191 for(x=0; x<w; x++)
192 {
193 if (strncmp(s+n*x,code,n))
194 {
195 rect.x = x;
196 rect.y = y;
197 XUnionRectWithRegion(&rect,r,r);
198 }
199 }
200 free(s);
201 }
202 free(code);
203 return r;
204 }
205
206 /*
207 * converts xpm data to bitmap
208 * xpm: input xpm data
209 * bitsreturn: output bitmap, allocated by this function
210 * wreturn: width of bitmap
211 * hreturn: height of bitmap
212 * lreturn: length of bitmap
213 *
214 * Return value: 1: OK, 0: not OK.
215 * BUGS: this code has not been tested on a big endian system
216 */
217 int xpmtobits(char *xpm[],unsigned char **bitsreturn, int *wreturn, int *hreturn, int *lreturn)
218 {
219 int nc,cpp,w,h;
220
221 unsigned char *bits = (unsigned char*) malloc(sizeof(unsigned char)*1);
222 if (sscanf(xpm[0],"%d %d %d %d",&w,&h,&nc,&cpp)!=4)
223 return 0;
224 if(cpp <=0 || w<0 || h<0 || nc<0)
225 return 0;
226 *wreturn = w;
227 *hreturn = h;
228 int l = ((int)w + 7)/8; // # chars needed for this w
229 *lreturn = l*h;
230 // l*h+1: we do not want allocate 0 bytes
231 bits = (unsigned char*) realloc(bits,sizeof(unsigned char)*(l*h+1));
232 *bitsreturn = bits;
233 int i;
234 for(i=0; i<l*h; i++)
235 bits[i] = 0;
236
237 char *code = (char *)malloc(sizeof(char)*cpp);
238 for (i=0; i<cpp; i++)
239 code[i] = ' ';
240
241 int offset = nc + 1;
242 for(i=1; i<=nc; i++)
243 {
244 char s[100];
245 if (strlen(xpm[i]) > (size_t)cpp + 6)
246 {
247 sscanf(xpm[i]+cpp,"%*s %100s",s);
248 if(!strcasecmp(s,"none"))
249 {
250 free(code);
251 code = strndup(xpm[i],cpp);
252 break;
253 }
254 }
255 }
256 int y;
257 unsigned char c = 0;
258 int j = 0;
259 if (is_little_endian())
260 for (y=0; y<h; y++) // little endian
261 {
262 int x,k=0;
263 const char *s = xpm[y+offset];
264 int l = strlen(s);
265 for(x=0; x<w; x++)
266 {
267 c >>= 1;
268 if (cpp*x + cpp <= l)
269 {
270 if (strncmp(s+cpp*x,code,cpp))
271 c |= 0x80;
272 }
273 k++;
274 if (k == 8)
275 {
276 bits[j++] = c;
277 k = 0;
278 }
279 }
280 if (k)
281 bits[j++] = c>>(8-k);
282 }
283 else
284 for (y=0; y<h; y++) // big endian NOT tested
285 {
286 int x,k=0;
287 const char *s = xpm[y+offset];
288 int l = strlen(s);
289 for(x=0; x<w; x++)
290 {
291 c <<= 1;
292 if (cpp*x + cpp <= l)
293 {
294 if (strncmp(s+cpp*x,code,cpp))
295 c |= 0x01;
296 }
297 k++;
298 if (k == 8)
299 {
300 bits[j++] = c;
301 k = 0;
302 }
303 }
304 if (k)
305 bits[j++] = c<<(8-k);
306 }
307
308 free(code);
309 return 1;
310 }
311
312
313 // given color and xmpdata **data of a monocolored picture like:
314 //
315 //XPM_TYPE *snow06_xpm[] = {
316 ///* columns rows colors chars-per-pixel */
317 //"3 3 2 1 ",
318 //" c none",
319 //". c black",
320 ///* pixels */
321 //". .",
322 //" . ",
323 //". ."
324 //};
325 // change the second color to color and put the result in out.
326 // lines will become the number of lines in out, comes in handy
327 // when wanteing to free out.
328 void xpm_set_color(char **data, char ***out, int *lines, const char *color)
329 {
330 int n;
331 sscanf(data[0],"%*d %d",&n);
332 assert(n+3>0);
333 *out = (char**)malloc(sizeof(char *)*(n+3));
334 char **x = *out;
335 int j;
336 for (j=0; j<2; j++)
337 x[j] = strdup(data[j]);
338 x[2] = (char *)malloc(5+strlen(color));
339 x[2][0] = '\0';
340 strcat(x[2],". c ");
341 strcat(x[2],color);
342 P("c: [%s]\n",x[2]);
343
344 for (j=3; j<n+3; j++)
345 {
346 x[j] = strdup(data[j]);
347 P("%d %s\n",j,x[j]);
348 }
349 *lines = n+3;
350 }
351
352 void xpm_destroy(char **data)
353 {
354 int h,nc;
355 sscanf(data[0],"%*d %d %d",&h,&nc);
356 int i;
357 for (i=0; i<h+nc+1; i++)
358 free(data[i]);
359 free(data);
360 }
361
362 void xpm_print(char **xpm)
363 {
364 int w,h,nc;
365 sscanf(xpm[0],"%d %d %d",&w,&h,&nc);
366 int i,j;
367 printf("%s\n",xpm[0]);
368 for (i=1; i<1+nc; i++)
369 printf("%s\n",xpm[i]);
370 for (i=0; i<2*w+2; i++)
371 printf("_");
372 printf("\n");
373 for (i=0; i<h; i++)
374 {
375 printf("|");
376 for (j=0; j<w; j++)
377 printf("%2c",xpm[i+nc+1][j]);
378 printf("|");
379 printf("\n");
380 }
381 for (i=0; i<2*w+2; i++)
382 printf("-");
383 printf("\n");
384 }
385
This page took 0.032954 seconds and 4 git commands to generate.