chiark / gitweb /
Imported Debian patch 1.0.0-5
[e16] / src / piximg.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies of the Software, its documentation and marketing & publicity
13  * materials, and acknowledgment shall be given in the documentation, materials
14  * and software packages that this Software was used.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include "E.h"
24 #include "piximg.h"
25 #include "xwin.h"
26 #include <sys/ipc.h>
27 #include <sys/shm.h>
28 #include <X11/Xutil.h>
29 #include <X11/extensions/XShm.h>
30
31 void
32 EFillPixmap(Window win, Pixmap pmap, int x, int y, int w, int h)
33 {
34    XGCValues           gcv;
35    GC                  gc;
36
37    gcv.subwindow_mode = IncludeInferiors;
38    gc = EXCreateGC(win, GCSubwindowMode, &gcv);
39    XCopyArea(disp, win, pmap, gc, x, y, w, h, x, y);
40    EXFreeGC(gc);
41 }
42
43 void
44 EPastePixmap(Window win, Pixmap pmap, int x, int y, int w, int h)
45 {
46    XGCValues           gcv;
47    GC                  gc;
48
49    gcv.subwindow_mode = IncludeInferiors;
50    gc = EXCreateGC(win, GCSubwindowMode, &gcv);
51    XCopyArea(disp, pmap, win, gc, x, y, w, h, x, y);
52    EXFreeGC(gc);
53 }
54
55 PixImg             *
56 ECreatePixImg(Window win, int w, int h)
57 {
58    XGCValues           gcv;
59    PixImg             *pi;
60
61    pi = EMALLOC(PixImg, 1);
62    if (!pi)
63       return NULL;
64
65    pi->shminfo = EMALLOC(XShmSegmentInfo, 1);
66    if (pi->shminfo)
67      {
68         pi->xim = XShmCreateImage(disp, WinGetVisual(VROOT),
69                                   WinGetDepth(VROOT), ZPixmap, NULL,
70                                   pi->shminfo, w, h);
71         if (pi->xim)
72           {
73              pi->shminfo->shmid =
74                 shmget(IPC_PRIVATE, pi->xim->bytes_per_line * pi->xim->height,
75                        IPC_CREAT | 0666);
76              if (pi->shminfo->shmid >= 0)
77                {
78                   pi->shminfo->shmaddr = pi->xim->data =
79                      (char *)shmat(pi->shminfo->shmid, 0, 0);
80                   if (pi->shminfo->shmaddr != (void *)-1)
81                     {
82                        pi->shminfo->readOnly = False;
83                        Dpy.last_error_code = 0;
84                        XShmAttach(disp, pi->shminfo);
85                        ESync(0);
86                        if (Dpy.last_error_code == 0)
87                          {
88                             pi->pmap =
89                                XShmCreatePixmap(disp, win, pi->shminfo->shmaddr,
90                                                 pi->shminfo, w, h,
91                                                 WinGetDepth(VROOT));
92                             if (pi->pmap)
93                               {
94                                  gcv.subwindow_mode = IncludeInferiors;
95                                  pi->gc =
96                                     EXCreateGC(win, GCSubwindowMode, &gcv);
97                                  if (pi->gc)
98                                     return pi;
99
100                                  EFreePixmap(pi->pmap);
101                               }
102                             XShmDetach(disp, pi->shminfo);
103                          }
104                        shmdt(pi->shminfo->shmaddr);
105                     }
106                   shmctl(pi->shminfo->shmid, IPC_RMID, 0);
107                }
108              XDestroyImage(pi->xim);
109           }
110         Efree(pi->shminfo);
111      }
112    Efree(pi);
113    return NULL;
114 }
115
116 void
117 EDestroyPixImg(PixImg * pi)
118 {
119    if (!pi)
120       return;
121    ESync(0);
122    XShmDetach(disp, pi->shminfo);
123    shmdt(pi->shminfo->shmaddr);
124    shmctl(pi->shminfo->shmid, IPC_RMID, 0);
125    XDestroyImage(pi->xim);
126    Efree(pi->shminfo);
127    EFreePixmap(pi->pmap);
128    EXFreeGC(pi->gc);
129    Efree(pi);
130 }
131
132 void
133 EBlendRemoveShape(Win win, Pixmap pmap, int x, int y)
134 {
135    static GC           gc = 0;
136    Window              root = WinGetXwin(VROOT);
137    int                 w, h;
138
139    if (!win)
140      {
141         if (gc)
142            EXFreeGC(gc);
143         gc = 0;
144         return;
145      }
146
147    if (win->num_rect <= 0)
148       return;
149
150    w = WinGetW(win);
151    h = WinGetH(win);
152
153    if (!gc)
154      {
155         XGCValues           gcv;
156         GC                  gcm;
157         Pixmap              mask;
158         XRectangle         *rl;
159         int                 i;
160
161         gcv.subwindow_mode = IncludeInferiors;
162         gc = EXCreateGC(root, GCSubwindowMode, &gcv);
163
164         mask = XCreatePixmap(disp, root, w, h, 1);
165         gcm = EXCreateGC(mask, 0, NULL);
166         XSetForeground(disp, gcm, 1);
167         XFillRectangle(disp, mask, gcm, 0, 0, w, h);
168         XSetForeground(disp, gcm, 0);
169         rl = win->rects;
170         for (i = 0; i < win->num_rect; i++)
171            XFillRectangle(disp, mask, gcm, rl[i].x, rl[i].y, rl[i].width,
172                           rl[i].height);
173         XSetClipMask(disp, gc, mask);
174         EXFreeGC(gcm);
175         XFreePixmap(disp, mask);
176      }
177
178    XSetClipOrigin(disp, gc, x, y);
179    XCopyArea(disp, pmap, root, gc, x, y, w, h, x, y);
180 }
181
182 void
183 EBlendPixImg(Win win, PixImg * s1, PixImg * s2, PixImg * dst, int x, int y,
184              int w, int h)
185 {
186    static GC           gc = 0;
187    Window              root = WinGetXwin(VROOT);
188    int                 i, j, ox, oy;
189
190    if (!win)
191      {
192         if (gc)
193            EXFreeGC(gc);
194         gc = 0;
195         return;
196      }
197
198    if (!gc)
199      {
200         XGCValues           gcv;
201
202         gcv.subwindow_mode = IncludeInferiors;
203         gc = EXCreateGC(root, GCSubwindowMode, &gcv);
204         if (win->rects)
205            XSetClipRectangles(disp, gc, x, y, win->rects, win->num_rect,
206                               win->ord);
207      }
208    else
209       XSetClipOrigin(disp, gc, x, y);
210
211    ox = 0;
212    oy = 0;
213    if ((x >= WinGetW(VROOT)) || (y >= WinGetH(VROOT)))
214       return;
215    if (x + w > WinGetW(VROOT))
216       w -= ((x + w) - WinGetW(VROOT));
217    if (x < 0)
218      {
219         ox = -x;
220         w -= ox;
221         x = 0;
222      }
223    if (y + h > WinGetH(VROOT))
224       h -= ((y + h) - WinGetH(VROOT));
225    if (y < 0)
226      {
227         oy = -y;
228         h -= oy;
229         y = 0;
230      }
231    if ((w <= 0) || (h <= 0))
232       return;
233
234    ESync(0);
235
236    switch (dst->xim->bits_per_pixel)
237      {
238      case 32:
239         for (j = 0; j < h; j++)
240           {
241              unsigned int       *ptr1, *ptr2, *ptr3;
242
243              ptr1 =
244                 (unsigned int *)(s1->xim->data +
245                                  (x * ((s1->xim->bits_per_pixel) >> 3)) +
246                                  ((j + y) * s1->xim->bytes_per_line));
247              ptr2 =
248                 (unsigned int *)(s2->xim->data +
249                                  (ox * ((s2->xim->bits_per_pixel) >> 3)) +
250                                  ((j + oy) * s2->xim->bytes_per_line));
251              ptr3 =
252                 (unsigned int *)(dst->xim->data +
253                                  (ox * ((dst->xim->bits_per_pixel) >> 3)) +
254                                  ((j + oy) * dst->xim->bytes_per_line));
255              for (i = 0; i < w; i++)
256                {
257                   unsigned int        p1, p2;
258
259                   p1 = *ptr1++;
260                   p2 = *ptr2++;
261                   *ptr3++ = ((p1 >> 1) & 0x7f7f7f7f) +
262                      ((p2 >> 1) & 0x7f7f7f7f) + (p1 & p2 & 0x01010101);
263                }
264           }
265         break;
266      case 24:
267         for (j = 0; j < h; j++)
268           {
269              for (i = 0; i < w; i++)
270                {
271                   unsigned int        p1, p2;
272
273                   p1 = XGetPixel(s1->xim, (i + x), (j + y));
274                   p2 = XGetPixel(s2->xim, (i + ox), (j + oy));
275                   XPutPixel(dst->xim, (i + ox), (j + oy),
276                             (((p1 >> 1) & 0x7f7f7f7f) +
277                              ((p2 >> 1) & 0x7f7f7f7f) +
278                              (p1 & p2 & 0x01010101)));
279                }
280           }
281         break;
282      case 16:
283         if (WinGetDepth(VROOT) != 15)
284           {
285              for (j = 0; j < h; j++)
286                {
287                   unsigned int       *ptr1, *ptr2, *ptr3;
288
289                   ptr1 =
290                      (unsigned int *)(s1->xim->data +
291                                       (x * ((s1->xim->bits_per_pixel) >> 3)) +
292                                       ((j + y) * s1->xim->bytes_per_line));
293                   ptr2 =
294                      (unsigned int *)(s2->xim->data +
295                                       (ox * ((s2->xim->bits_per_pixel) >> 3)) +
296                                       ((j + oy) * s2->xim->bytes_per_line));
297                   ptr3 =
298                      (unsigned int *)(dst->xim->data +
299                                       (ox * ((dst->xim->bits_per_pixel) >> 3)) +
300                                       ((j + oy) * dst->xim->bytes_per_line));
301                   if (!(w & 0x1))
302                     {
303                        for (i = 0; i < w; i += 2)
304                          {
305                             unsigned int        p1, p2;
306
307                             p1 = *ptr1++;
308                             p2 = *ptr2++;
309                             *ptr3++ =
310                                ((p1 >> 1) &
311                                 ((0x78 << 8) | (0x7c << 3) | (0x78 >> 3) |
312                                  (0x78 << 24) | (0x7c << 19) | (0x78 << 13)))
313                                +
314                                ((p2 >> 1) &
315                                 ((0x78 << 8) | (0x7c << 3) | (0x78 >> 3) |
316                                  (0x78 << 24) | (0x7c << 19) | (0x78 << 13)))
317                                +
318                                (p1 & p2 &
319                                 ((0x1 << 11) | (0x1 << 5) | (0x1) |
320                                  (0x1 << 27) | (0x1 << 21) | (0x1 << 16)));
321                          }
322                     }
323                   else
324                     {
325                        for (i = 0; i < (w - 1); i += 2)
326                          {
327                             unsigned int        p1, p2;
328
329                             p1 = *ptr1++;
330                             p2 = *ptr2++;
331                             *ptr3++ =
332                                ((p1 >> 1) &
333                                 ((0x78 << 8) | (0x7c << 3) | (0x78 >> 3) |
334                                  (0x78 << 24) | (0x7c << 19) | (0x78 << 13)))
335                                +
336                                ((p2 >> 1) &
337                                 ((0x78 << 8) | (0x7c << 3) | (0x78 >> 3) |
338                                  (0x78 << 24) | (0x7c << 19) | (0x78 << 13)))
339                                +
340                                (p1 & p2 &
341                                 ((0x1 << 11) | (0x1 << 5) | (0x1) |
342                                  (0x1 << 27) | (0x1 << 21) | (0x1 << 16)));
343                          }
344                        {
345                           unsigned short     *pptr1, *pptr2, *pptr3;
346                           unsigned short      pp1, pp2;
347
348                           pptr1 = (unsigned short *)ptr1;
349                           pptr2 = (unsigned short *)ptr2;
350                           pptr3 = (unsigned short *)ptr3;
351                           pp1 = *pptr1;
352                           pp2 = *pptr2;
353                           *pptr3 =
354                              ((pp1 >> 1) &
355                               ((0x78 << 8) | (0x7c << 3) | (0x78 >> 3)))
356                              +
357                              ((pp2 >> 1) &
358                               ((0x78 << 8) | (0x7c << 3) | (0x78 >> 3)))
359                              + (pp1 & pp2 & ((0x1 << 11) | (0x1 << 5) | (0x1)));
360                        }
361                     }
362                }
363           }
364         else
365           {
366              for (j = 0; j < h; j++)
367                {
368                   unsigned int       *ptr1, *ptr2, *ptr3;
369
370                   ptr1 =
371                      (unsigned int *)(s1->xim->data +
372                                       (x * (s1->xim->bits_per_pixel >> 3)) +
373                                       ((j + y) * s1->xim->bytes_per_line));
374                   ptr2 =
375                      (unsigned int *)(s2->xim->data +
376                                       (ox * ((s2->xim->bits_per_pixel) >> 3)) +
377                                       ((j + oy) * s2->xim->bytes_per_line));
378                   ptr3 =
379                      (unsigned int *)(dst->xim->data +
380                                       (ox * ((dst->xim->bits_per_pixel) >> 3)) +
381                                       ((j + oy) * dst->xim->bytes_per_line));
382                   if (!(w & 0x1))
383                     {
384                        for (i = 0; i < w; i += 2)
385                          {
386                             unsigned int        p1, p2;
387
388                             p1 = *ptr1++;
389                             p2 = *ptr2++;
390                             *ptr3++ =
391                                ((p1 >> 1) &
392                                 ((0x78 << 7) | (0x78 << 2) | (0x78 >> 3) |
393                                  (0x78 << 23) | (0x78 << 18) | (0x78 << 13)))
394                                +
395                                ((p2 >> 1) &
396                                 ((0x78 << 7) | (0x78 << 2) | (0x78 >> 3) |
397                                  (0x78 << 23) | (0x78 << 18) | (0x78 << 13)))
398                                +
399                                (p1 & p2 &
400                                 ((0x1 << 10) | (0x1 << 5) | (0x1) |
401                                  (0x1 << 26) | (0x1 << 20) | (0x1 << 16)));
402                          }
403                     }
404                   else
405                     {
406                        for (i = 0; i < (w - 1); i += 2)
407                          {
408                             unsigned int        p1, p2;
409
410                             p1 = *ptr1++;
411                             p2 = *ptr2++;
412                             *ptr3++ =
413                                ((p1 >> 1) &
414                                 ((0x78 << 7) | (0x78 << 2) | (0x78 >> 3) |
415                                  (0x78 << 23) | (0x78 << 18) | (0x78 << 13)))
416                                +
417                                ((p2 >> 1) &
418                                 ((0x78 << 7) | (0x78 << 2) | (0x78 >> 3) |
419                                  (0x78 << 23) | (0x78 << 18) | (0x78 << 13)))
420                                +
421                                (p1 & p2 &
422                                 ((0x1 << 10) | (0x1 << 5) | (0x1) |
423                                  (0x1 << 26) | (0x1 << 20) | (0x1 << 16)));
424                          }
425                        {
426                           unsigned short     *pptr1, *pptr2, *pptr3;
427                           unsigned short      pp1, pp2;
428
429                           pptr1 = (unsigned short *)ptr1;
430                           pptr2 = (unsigned short *)ptr2;
431                           pptr3 = (unsigned short *)ptr3;
432                           pp1 = *pptr1;
433                           pp2 = *pptr2;
434                           *pptr3++ =
435                              ((pp1 >> 1) &
436                               ((0x78 << 7) | (0x78 << 2) | (0x78 >> 3)))
437                              +
438                              ((pp2 >> 1) &
439                               ((0x78 << 7) | (0x78 << 2) | (0x78 >> 3)))
440                              + (pp1 & pp2 & ((0x1 << 10) | (0x1 << 5) | (0x1)));
441                        }
442                     }
443                }
444           }
445         break;
446      default:
447         for (j = 0; j < h; j++)
448           {
449              unsigned char      *ptr1, *ptr2, *ptr3;
450
451              ptr1 =
452                 (unsigned char *)(s1->xim->data +
453                                   ((x) *
454                                    ((s1->xim->bits_per_pixel) >> 3)) +
455                                   ((j + y) * s1->xim->bytes_per_line));
456              ptr2 =
457                 (unsigned char *)(s2->xim->data +
458                                   ((ox) *
459                                    ((s2->xim->bits_per_pixel) >> 3)) +
460                                   ((j + oy) * s2->xim->bytes_per_line));
461              ptr3 =
462                 (unsigned char *)(dst->xim->data +
463                                   ((ox) *
464                                    ((dst->xim->bits_per_pixel) >> 3)) +
465                                   ((j + oy) * dst->xim->bytes_per_line));
466              if (!(w & 0x1))
467                {
468                   if (j & 0x1)
469                     {
470                        ptr2++;
471                        for (i = 0; i < w; i += 2)
472                          {
473                             unsigned char       p1;
474
475                             p1 = *ptr1;
476                             ptr1 += 2;
477                             *ptr3++ = p1;
478                             p1 = *ptr2;
479                             ptr2 += 2;
480                             *ptr3++ = p1;
481                          }
482                     }
483                   else
484                     {
485                        ptr1++;
486                        for (i = 0; i < w; i += 2)
487                          {
488                             unsigned char       p1;
489
490                             p1 = *ptr2;
491                             ptr2 += 2;
492                             *ptr3++ = p1;
493                             p1 = *ptr1;
494                             ptr1 += 2;
495                             *ptr3++ = p1;
496                          }
497                     }
498                }
499              else
500                {
501                   if (j & 0x1)
502                     {
503                        ptr2++;
504                        for (i = 0; i < (w - 1); i += 2)
505                          {
506                             unsigned char       p1;
507
508                             p1 = *ptr1;
509                             ptr1 += 2;
510                             *ptr3++ = p1;
511                             p1 = *ptr2;
512                             ptr2 += 2;
513                             *ptr3++ = p1;
514                          }
515                        *ptr3 = *ptr1;
516                     }
517                   else
518                     {
519                        ptr1++;
520                        for (i = 0; i < (w - 1); i += 2)
521                          {
522                             unsigned char       p1;
523
524                             p1 = *ptr2;
525                             ptr2 += 2;
526                             *ptr3++ = p1;
527                             p1 = *ptr1;
528                             ptr1 += 2;
529                             *ptr3++ = p1;
530                          }
531                        *ptr3 = *ptr2;
532                     }
533                }
534           }
535         break;
536      }
537 /* workaround since XCopyArea doesnt always work with shared pixmaps */
538    XShmPutImage(disp, root, gc, dst->xim, ox, oy, x, y, w, h, False);
539 /*      XCopyArea(disp, dst->pmap, root, gc, ox, oy, w, h, x, y); */
540 /* I dont believe it - you cannot do this to a shared pixmaps to the screen */
541 /* XCopyArea(disp, dst->pmap, root, dst->gc, x, y, w, h, x, y); */
542 }