SmartPDF - lightweight pdf viewer app for rosapps
[reactos.git] / rosapps / smartpdf / fitz / apps / unix / ximage.c
1 /*
2 * Blit ARGB images to X with X(Shm)Images
3 */
4
5 #include <fitz.h>
6
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9 #include <sys/ipc.h>
10 #include <sys/shm.h>
11 #include <X11/extensions/XShm.h>
12
13 extern int ffs(int);
14
15 typedef void (*ximage_convert_func_t)
16 (
17 const unsigned char *src,
18 int srcstride,
19 unsigned char *dst,
20 int dststride,
21 int w,
22 int h
23 );
24
25 #define POOLSIZE 4
26 #define WIDTH 256
27 #define HEIGHT 256
28
29 enum {
30 ARGB8888,
31 BGRA8888,
32 RGBA8888,
33 ABGR8888,
34 RGB888,
35 BGR888,
36 RGB565,
37 RGB565_BR,
38 RGB555,
39 RGB555_BR,
40 BGR233,
41 UNKNOWN
42 };
43
44 static char *modename[] = {
45 "ARGB8888",
46 "BGRA8888",
47 "RGBA8888",
48 "ABGR8888",
49 "RGB888",
50 "BGR888",
51 "RGB565",
52 "RGB565_BR",
53 "RGB555",
54 "RGB555_BR",
55 "BGR233",
56 "UNKNOWN"
57 };
58
59 extern ximage_convert_func_t ximage_convert_funcs[];
60
61 static struct
62 {
63 Display *display;
64 int screen;
65 XVisualInfo visual;
66 Colormap colormap;
67
68 int bitsperpixel;
69 int mode;
70
71 XColor rgbcube[256];
72
73 ximage_convert_func_t convert_func;
74
75 int useshm;
76 XImage *pool[POOLSIZE];
77 /* MUST exist during the lifetime of the shared ximage according to the
78 xc/doc/hardcopy/Xext/mit-shm.PS.gz */
79 XShmSegmentInfo shminfo[POOLSIZE];
80 int lastused;
81 } info;
82
83 static XImage *
84 createximage(Display *dpy, Visual *vis, XShmSegmentInfo *xsi, int depth, int w, int h)
85 {
86 XImage *img;
87 Status status;
88
89 if (!XShmQueryExtension(dpy)) goto fallback;
90
91 img = XShmCreateImage(dpy, vis, depth, ZPixmap, nil, xsi, w, h);
92 if (!img)
93 {
94 fprintf(stderr, "warn: could not XShmCreateImage\n");
95 goto fallback;
96 }
97
98 xsi->shmid = shmget(IPC_PRIVATE,
99 img->bytes_per_line * img->height,
100 IPC_CREAT | 0777);
101 if (xsi->shmid < 0)
102 {
103 XDestroyImage(img);
104 fprintf(stderr, "warn: could not shmget\n");
105 goto fallback;
106 }
107
108 img->data = xsi->shmaddr = shmat(xsi->shmid, 0, 0);
109 if (img->data == (char*)-1)
110 {
111 XDestroyImage(img);
112 fprintf(stderr, "warn: could not shmat\n");
113 goto fallback;
114 }
115
116 xsi->readOnly = False;
117 status = XShmAttach(dpy, xsi);
118 if (!status)
119 {
120 shmdt(xsi->shmaddr);
121 XDestroyImage(img);
122 fprintf(stderr, "warn: could not XShmAttach\n");
123 goto fallback;
124 }
125
126 XSync(dpy, False);
127
128 shmctl(xsi->shmid, IPC_RMID, 0);
129
130 return img;
131
132 fallback:
133 info.useshm = 0;
134
135 img = XCreateImage(dpy, vis, depth, ZPixmap, 0, 0, w, h, 32, 0);
136 if (!img)
137 {
138 fprintf(stderr, "fail: could not XCreateImage");
139 abort();
140 }
141
142 img->data = malloc(h * img->bytes_per_line);
143 if (!img->data)
144 {
145 fprintf(stderr, "fail: could not malloc");
146 abort();
147 }
148
149 return img;
150 }
151
152 static void
153 make_colormap(void)
154 {
155 if (info.visual.class == PseudoColor && info.visual.depth == 8)
156 {
157 int i, r, g, b;
158 i = 0;
159 for (b = 0; b < 4; b++) {
160 for (g = 0; g < 8; g++) {
161 for (r = 0; r < 8; r++) {
162 info.rgbcube[i].pixel = i;
163 info.rgbcube[i].red = (r * 36) << 8;
164 info.rgbcube[i].green = (g * 36) << 8;
165 info.rgbcube[i].blue = (b * 85) << 8;
166 info.rgbcube[i].flags =
167 DoRed | DoGreen | DoBlue;
168 i++;
169 }
170 }
171 }
172 info.colormap = XCreateColormap(info.display,
173 RootWindow(info.display, info.screen),
174 info.visual.visual,
175 AllocAll);
176 XStoreColors(info.display, info.colormap, info.rgbcube, 256);
177 return;
178 }
179 else if (info.visual.class == TrueColor)
180 {
181 info.colormap = 0;
182 return;
183 }
184 fprintf(stderr, "Cannot handle visual class %d with depth: %d\n",
185 info.visual.class, info.visual.depth);
186 return;
187 }
188
189 static void
190 select_mode(void)
191 {
192
193 int byteorder;
194 int byterev;
195 unsigned long rm, gm, bm;
196 unsigned long rs, gs, bs;
197
198 byteorder = ImageByteOrder(info.display);
199 #if BYTE_ORDER == BIG_ENDIAN
200 byterev = byteorder != MSBFirst;
201 #else
202 byterev = byteorder != LSBFirst;
203 #endif
204
205 rm = info.visual.red_mask;
206 gm = info.visual.green_mask;
207 bm = info.visual.blue_mask;
208
209 rs = ffs(rm) - 1;
210 gs = ffs(gm) - 1;
211 bs = ffs(bm) - 1;
212
213 printf("ximage: mode %d/%d %08lx %08lx %08lx (%ld,%ld,%ld) %s%s\n",
214 info.visual.depth,
215 info.bitsperpixel,
216 rm, gm, bm, rs, gs, bs,
217 byteorder == MSBFirst ? "msb" : "lsb",
218 byterev ? " <swap>":"");
219
220 info.mode = UNKNOWN;
221 if (info.bitsperpixel == 8) {
222 /* Either PseudoColor with BGR233 colormap, or TrueColor */
223 info.mode = BGR233;
224 }
225 else if (info.bitsperpixel == 16) {
226 if (rm == 0xF800 && gm == 0x07E0 && bm == 0x001F)
227 info.mode = !byterev ? RGB565 : RGB565_BR;
228 if (rm == 0x7C00 && gm == 0x03E0 && bm == 0x001F)
229 info.mode = !byterev ? RGB555 : RGB555_BR;
230 }
231 else if (info.bitsperpixel == 24) {
232 if (rs == 0 && gs == 8 && bs == 16)
233 info.mode = byteorder == MSBFirst ? RGB888 : BGR888;
234 if (rs == 16 && gs == 8 && bs == 0)
235 info.mode = byteorder == MSBFirst ? BGR888 : RGB888;
236 }
237 else if (info.bitsperpixel == 32) {
238 if (rs == 0 && gs == 8 && bs == 16)
239 info.mode = byteorder == MSBFirst ? ABGR8888 : RGBA8888;
240 if (rs == 8 && gs == 16 && bs == 24)
241 info.mode = byteorder == MSBFirst ? BGRA8888 : ARGB8888;
242 if (rs == 16 && gs == 8 && bs == 0)
243 info.mode = byteorder == MSBFirst ? ARGB8888 : BGRA8888;
244 if (rs == 24 && gs == 16 && bs == 8)
245 info.mode = byteorder == MSBFirst ? RGBA8888 : ABGR8888;
246 }
247
248 printf("ximage: ARGB8888 to %s\n", modename[info.mode]);
249
250 /* select conversion function */
251 info.convert_func = ximage_convert_funcs[info.mode];
252 }
253
254 static int
255 create_pool(void)
256 {
257 int i;
258
259 info.lastused = 0;
260
261 for (i = 0; i < POOLSIZE; i++) {
262 info.pool[i] = nil;
263 }
264
265 for (i = 0; i < POOLSIZE; i++) {
266 info.pool[i] = createximage(info.display,
267 info.visual.visual, &info.shminfo[i], info.visual.depth,
268 WIDTH, HEIGHT);
269 if (info.pool[i] == nil) {
270 return 0;
271 }
272 }
273
274 return 1;
275 }
276
277 static XImage *
278 next_pool_image(void)
279 {
280 if (info.lastused + 1 >= POOLSIZE) {
281 if (info.useshm)
282 XSync(info.display, False);
283 else
284 XFlush(info.display);
285 info.lastused = 0;
286 }
287 return info.pool[info.lastused ++];
288 }
289
290 int
291 ximage_init(Display *display, int screen, Visual *visual)
292 {
293 XVisualInfo template;
294 XVisualInfo *visuals;
295 int nvisuals;
296 XPixmapFormatValues *formats;
297 int nformats;
298 int ok;
299 int i;
300
301 info.display = display;
302 info.screen = screen;
303 info.colormap = 0;
304
305 /* Get XVisualInfo for this visual */
306 template.visualid = XVisualIDFromVisual(visual);
307 visuals = XGetVisualInfo(display, VisualIDMask, &template, &nvisuals);
308 if (nvisuals != 1) {
309 fprintf(stderr, "Visual not found!\n");
310 XFree(visuals);
311 return 0;
312 }
313 memcpy(&info.visual, visuals, sizeof (XVisualInfo));
314 XFree(visuals);
315
316 /* Get appropriate PixmapFormat for this visual */
317 formats = XListPixmapFormats(info.display, &nformats);
318 for (i = 0; i < nformats; i++) {
319 if (formats[i].depth == info.visual.depth) {
320 info.bitsperpixel = formats[i].bits_per_pixel;
321 break;
322 }
323 }
324 XFree(formats);
325 if (i == nformats) {
326 fprintf(stderr, "PixmapFormat not found!\n");
327 return 0;
328 }
329
330 /* extract mode */
331 select_mode();
332
333 /* prepare colormap */
334 make_colormap();
335
336 /* prepare pool of XImages */
337 info.useshm = 1;
338 ok = create_pool();
339 if (!ok)
340 return 0;
341
342 printf("ximage: %sPutImage\n", info.useshm ? "XShm" : "X");
343
344 return 1;
345 }
346
347 int
348 ximage_get_depth(void)
349 {
350 return info.visual.depth;
351 }
352
353 Visual *
354 ximage_get_visual(void)
355 {
356 return info.visual.visual;
357 }
358
359 Colormap
360 ximage_get_colormap(void)
361 {
362 return info.colormap;
363 }
364
365 void
366 ximage_blit(Drawable d, GC gc,
367 int dstx, int dsty,
368 unsigned char *srcdata,
369 int srcx, int srcy,
370 int srcw, int srch,
371 int srcstride)
372 {
373 XImage *image;
374 int ax, ay;
375 int w, h;
376 unsigned char *srcptr;
377
378 for (ay = 0; ay < srch; ay += HEIGHT)
379 {
380 h = MIN(srch - ay, HEIGHT);
381 for (ax = 0; ax < srcw; ax += WIDTH)
382 {
383 w = MIN(srcw - ax, WIDTH);
384
385 image = next_pool_image();
386
387 srcptr = srcdata +
388 (ay + srcy) * srcstride +
389 (ax + srcx) * 4;
390
391 info.convert_func(srcptr, srcstride,
392 image->data,
393 image->bytes_per_line, w, h);
394
395 if (info.useshm)
396 {
397 XShmPutImage(info.display, d, gc, image,
398 0, 0, dstx + ax, dsty + ay,
399 w, h, False);
400 }
401 else
402 {
403 XPutImage(info.display, d, gc, image,
404 0, 0,
405 dstx + ax,
406 dsty + ay,
407 w, h);
408 }
409 }
410 }
411 }
412
413 /*
414 * Primitive conversion functions
415 */
416
417 #ifndef restrict
418 #ifndef _C99
419 #ifdef __GNUC__
420 #define restrict __restrict__
421 #else
422 #define restrict
423 #endif
424 #endif
425 #endif
426
427 #define PARAMS \
428 const unsigned char * restrict src, \
429 int srcstride, \
430 unsigned char * restrict dst, \
431 int dststride, \
432 int w, \
433 int h
434
435 /*
436 * Convert byte:ARGB8888 to various formats
437 */
438
439 static void
440 ximage_convert_argb8888(PARAMS)
441 {
442 int x, y;
443 unsigned * restrict s = (unsigned * restrict )src;
444 unsigned * restrict d = (unsigned * restrict )dst;
445 for (y = 0; y < h; y++) {
446 for (x = 0; x < w; x++) {
447 d[x] = s[x];
448 }
449 d += dststride>>2;
450 s += srcstride>>2;
451 }
452 }
453
454 static void
455 ximage_convert_bgra8888(PARAMS)
456 {
457 int x, y;
458 unsigned *s = (unsigned *)src;
459 unsigned *d = (unsigned *)dst;
460 unsigned val;
461 for (y = 0; y < h; y++) {
462 for (x = 0; x < w; x++) {
463 val = s[x];
464 d[x] =
465 (val >> 24) |
466 ((val >> 8) & 0xff00) |
467 (val << 24) |
468 ((val << 8) & 0xff0000);
469 /*
470 d[x] =
471 (((val >> 24) & 0xff) << 0) |
472 (((val >> 16) & 0xff) << 8) |
473 (((val >> 8) & 0xff) << 16) |
474 (((val >> 0) & 0xff) << 24);
475 */
476 }
477 d += dststride>>2;
478 s += srcstride>>2;
479 }
480 }
481
482 /* following have yet to recieve some MMX love ;-) */
483
484 static void
485 ximage_convert_abgr8888(PARAMS)
486 {
487 int x, y;
488 unsigned *s = (unsigned *)src;
489 unsigned *d = (unsigned *)dst;
490 unsigned val;
491
492 for (y = 0; y < h; y++) {
493 for (x = 0; x < w; x++) {
494 val = s[x];
495 #if 1 /* FZ_MSB */
496 d[x] = (val & 0xff00ff00) |
497 (((val << 16) | (val >> 16)) & 0x00ff00ff);
498 #else /* FZ_LSB */
499 d[x] = (val << 24) | ((val >> 8) & 0xff);
500 #endif
501 }
502 d += dststride>>2;
503 s += srcstride>>2;
504 }
505 }
506
507 static void
508 ximage_convert_rgba8888(PARAMS)
509 {
510 int x, y;
511 for (y = 0; y < h; y++) {
512 for (x = 0; x < w; x++) {
513 dst[x * 4 + 0] = src[x * 4 + 1];
514 dst[x * 4 + 1] = src[x * 4 + 2];
515 dst[x * 4 + 2] = src[x * 4 + 3];
516 dst[x * 4 + 3] = src[x * 4 + 0];
517 }
518 dst += dststride;
519 src += srcstride;
520 }
521 }
522
523 static void
524 ximage_convert_bgr888(PARAMS)
525 {
526 int x, y;
527 for (y = 0; y < h; y++) {
528 for (x = 0; x < w; x++) {
529 dst[3*x + 0] = src[4*x + 3];
530 dst[3*x + 1] = src[4*x + 2];
531 dst[3*x + 2] = src[4*x + 1];
532 }
533 src += srcstride;
534 dst += dststride;
535 }
536 }
537
538 static void
539 ximage_convert_rgb888(PARAMS)
540 {
541 int x, y;
542 for (y = 0; y < h; y++) {
543 for (x = 0; x < w; x++) {
544 dst[3*x + 0] = src[4*x + 1];
545 dst[3*x + 1] = src[4*x + 2];
546 dst[3*x + 2] = src[4*x + 3];
547 }
548 src += srcstride;
549 dst += dststride;
550 }
551 }
552
553 static void
554 ximage_convert_rgb565(PARAMS)
555 {
556 unsigned char r, g, b;
557 int x, y;
558 for (y = 0; y < h; y++) {
559 for (x = 0; x < w; x++) {
560 r = src[4*x + 1];
561 g = src[4*x + 2];
562 b = src[4*x + 3];
563 ((unsigned short *)dst)[x] =
564 ((r & 0xF8) << 8) |
565 ((g & 0xFC) << 3) |
566 (b >> 3);
567 }
568 src += srcstride;
569 dst += dststride;
570 }
571 }
572
573 static void
574 ximage_convert_rgb565_br(PARAMS)
575 {
576 unsigned char r, g, b;
577 int x, y;
578 for (y = 0; y < h; y++) {
579 for (x = 0; x < w; x++) {
580 r = src[4*x + 1];
581 g = src[4*x + 2];
582 b = src[4*x + 3];
583 /* final word is:
584 g4 g3 g2 b7 b6 b5 b4 b3 r7 r6 r5 r4 r3 g7 g6 g5
585 */
586 ((unsigned short *)dst)[x] =
587 (r & 0xF8) |
588 ((g & 0xE0) >> 5) |
589 ((g & 0x1C) << 11) |
590 ((b & 0xF8) << 5);
591 }
592 src += srcstride;
593 dst += dststride;
594 }
595 }
596
597 static void
598 ximage_convert_rgb555(PARAMS)
599 {
600 unsigned char r, g, b;
601 int x, y;
602 for (y = 0; y < h; y++) {
603 for (x = 0; x < w; x++) {
604 r = src[4*x + 1];
605 g = src[4*x + 2];
606 b = src[4*x + 3];
607 ((unsigned short *)dst)[x] =
608 ((r & 0xF8) << 7) |
609 ((g & 0xF8) << 2) |
610 (b >> 3);
611 }
612 src += srcstride;
613 dst += dststride;
614 }
615 }
616
617 static void
618 ximage_convert_rgb555_br(PARAMS)
619 {
620 unsigned char r, g, b;
621 int x, y;
622 for (y = 0; y < h; y++) {
623 for (x = 0; x < w; x++) {
624 r = src[4*x + 1];
625 g = src[4*x + 2];
626 b = src[4*x + 3];
627 /* final word is:
628 g5 g4 g3 b7 b6 b5 b4 b3 0 r7 r6 r5 r4 r3 g7 g6
629 */
630 ((unsigned short *)dst)[x] =
631 ((r & 0xF8) >> 1) |
632 ((g & 0xC0) >> 6) |
633 ((g & 0x38) << 10) |
634 ((b & 0xF8) << 5);
635 }
636 src += srcstride;
637 dst += dststride;
638 }
639 }
640
641 static void
642 ximage_convert_bgr233(PARAMS)
643 {
644 unsigned char r, g, b;
645 int x,y;
646 for(y = 0; y < h; y++) {
647 for(x = 0; x < w; x++) {
648 r = src[4*x + 1];
649 g = src[4*x + 2];
650 b = src[4*x + 3];
651 /* format: b7 b6 g7 g6 g5 r7 r6 r5 */
652 dst[x] = (b&0xC0) | ((g>>2)&0x38) | ((r>>5)&0x7);
653 }
654 src += srcstride;
655 dst += dststride;
656 }
657 }
658
659 ximage_convert_func_t ximage_convert_funcs[] = {
660 ximage_convert_argb8888,
661 ximage_convert_bgra8888,
662 ximage_convert_rgba8888,
663 ximage_convert_abgr8888,
664 ximage_convert_rgb888,
665 ximage_convert_bgr888,
666 ximage_convert_rgb565,
667 ximage_convert_rgb565_br,
668 ximage_convert_rgb555,
669 ximage_convert_rgb555_br,
670 ximage_convert_bgr233,
671 };
672