13 #include "kpixmapio.h"
21 #include <tdeglobal.h>
22 #include <tdeconfig.h>
25 #include <sys/types.h>
34 #include <X11/Xutil.h>
36 #include <X11/extensions/XShm.h>
39 extern "C" int XShmQueryExtension(Display *display);
47 struct KPixmapIOPrivate
57 XShmSegmentInfo *shminfo;
68 typedef unsigned char uchar;
69 typedef unsigned int uint;
72 static int lowest_bit(uint val)
76 for (i=0; (!(val & test)) && i<32; i++, test<<=1);
77 return (i == 32) ? -1 : i;
83 KPixmapIO::KPixmapIO()
86 d =
new KPixmapIOPrivate;
95 if (XQueryExtension(tqt_xdisplay(),
"MIT-SHM", &ignore, &ignore, &ignore))
97 if (XShmQueryExtension(tqt_xdisplay()))
102 kdDebug(290) << k_lineinfo <<
"MIT-SHM not available!\n";
110 d->shminfo =
new XShmSegmentInfo;
111 d->ximage = XShmCreateImage(tqt_xdisplay(), (Visual *) TQPaintDevice::x11AppVisual(),
112 TQPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, 10, 10);
113 d->bpp = d->ximage->bits_per_pixel;
116 if (d->ximage->byte_order == LSBFirst)
118 int red_shift = lowest_bit(d->ximage->red_mask);
119 int green_shift = lowest_bit(d->ximage->green_mask);
120 int blue_shift = lowest_bit(d->ximage->blue_mask);
121 XDestroyImage(d->ximage); d->ximage = 0L;
128 if ((bpp == 32) && (red_shift == 16) && (green_shift == 8) &&
130 d->byteorder = bo32_ARGB;
131 else if ((bpp == 32) && (red_shift == 0) && (green_shift == 8) &&
133 d->byteorder = bo32_BGRA;
134 else if ((bpp == 33) && (red_shift == 16) && (green_shift == 8) &&
136 d->byteorder = bo32_BGRA;
137 else if ((bpp == 24) && (red_shift == 16) && (green_shift == 8) &&
139 d->byteorder = bo24_RGB;
140 else if ((bpp == 24) && (red_shift == 0) && (green_shift == 8) &&
142 d->byteorder = bo24_BGR;
143 else if ((bpp == 25) && (red_shift == 16) && (green_shift == 8) &&
145 d->byteorder = bo24_BGR;
146 else if ((bpp == 16) && (red_shift == 11) && (green_shift == 5) &&
148 d->byteorder = bo16_RGB_565;
149 else if ((bpp == 16) && (red_shift == 10) && (green_shift == 5) &&
151 d->byteorder = bo16_RGB_555;
152 else if ((bpp == 17) && (red_shift == 11) && (green_shift == 5) &&
154 d->byteorder = bo16_BGR_565;
155 else if ((bpp == 17) && (red_shift == 10) && (green_shift == 5) &&
157 d->byteorder = bo16_BGR_555;
158 else if ((bpp == 8) || (bpp == 9))
165 <<
", green = " << green_shift
166 <<
", blue = " << blue_shift <<
endl;
167 kdWarning(290) <<
"Please report to <jansen@kde.org>\n";
176 KPixmapIO::~KPixmapIO()
189 int size = img.width() * img.height();
190 if (m_bShm && (img.depth() > 1) && (d->bpp > 8) && (size > d->threshold))
192 TQPixmap dst(img.width(), img.height());
198 dst.convertFromImage(img);
208 int size = pm.width() * pm.height();
209 if (m_bShm && (d->bpp >= 8) && (size > d->threshold))
210 image =
getImage(&pm, 0, 0, pm.width(), pm.height());
212 image = pm.convertToImage();
220 putImage(dst, offset.x(), offset.y(), src);
226 int size = src->width() * src->height();
227 bool fallback =
true;
228 if (m_bShm && (src->depth() > 1) && (d->bpp > 8) && (size > d->threshold))
231 if( initXImage(src->width(), src->height()))
233 convertToXImage(*src);
234 XShmPutImage(tqt_xdisplay(), dst->handle(), tqt_xget_temp_gc(tqt_xscreen(),
false), d->ximage,
235 dx, dy, 0, 0, src->width(), src->height(),
false);
237 XSync(tqt_xdisplay(),
false);
246 pix.convertFromImage(*src);
247 bitBlt(dst, dx, dy, &pix, 0, 0, pix.width(), pix.height());
254 return getImage(src, rect.x(), rect.y(), rect.width(), rect.height());
261 int size = src->width() * src->height();
262 bool fallback =
true;
263 if ((m_bShm) && (d->bpp >= 8) && (size > d->threshold))
266 if( initXImage(sw, sh))
268 XShmGetImage(tqt_xdisplay(), src->handle(), d->ximage, sx, sy, AllPlanes);
269 image = convertFromXImage();
277 TQPixmap pix(sw, sh);
278 bitBlt(&pix, 0, 0, src, sx, sy, sw, sh);
279 image = pix.convertToImage();
290 createShmSegment(size);
299 d->shmpolicy = ShmDontKeep;
303 d->shmpolicy = ShmKeepAndGrow;
312 bool KPixmapIO::initXImage(
int w,
int h)
314 if (d->ximage && (w == d->ximage->width) && (h == d->ximage->height))
317 if( !createXImage(w, h))
319 int size = d->ximage->bytes_per_line * d->ximage->height;
320 if (size > d->shmsize)
322 if( !createShmSegment(size))
328 d->ximage->data = d->shminfo->shmaddr;
333 void KPixmapIO::doneXImage()
335 if (d->shmpolicy == ShmDontKeep)
343 void KPixmapIO::destroyXImage()
347 XDestroyImage(d->ximage);
353 bool KPixmapIO::createXImage(
int w,
int h)
356 d->ximage = XShmCreateImage(tqt_xdisplay(), (Visual *) TQPaintDevice::x11AppVisual(),
357 TQPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, w, h);
358 return d->ximage != None;
362 void KPixmapIO::destroyShmSegment()
366 XShmDetach(tqt_xdisplay(), d->shminfo);
367 shmdt(d->shminfo->shmaddr);
368 shmctl(d->shminfo->shmid, IPC_RMID, 0);
373 static bool use_xshm =
true;
374 static unsigned long kpixmapio_serial;
375 static int (*old_errhandler)(Display *dpy, XErrorEvent *ev) = 0;
377 static int kpixmapio_errorhandler(Display *dpy, XErrorEvent *ev)
379 if(ev->serial == kpixmapio_serial) {
387 return old_errhandler(dpy, ev);
391 bool KPixmapIO::createShmSegment(
int size)
394 d->shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0600);
395 if ( d->shminfo->shmid < 0)
397 kdWarning(290) <<
"Could not get shared memory segment.\n";
402 d->shminfo->shmaddr = (
char *) shmat(d->shminfo->shmid, 0, 0);
403 if (d->shminfo->shmaddr == (
char *)-1)
405 kdWarning(290) <<
"Could not attach shared memory segment.\n";
407 shmctl(d->shminfo->shmid, IPC_RMID, 0);
411 d->shminfo->readOnly =
false;
415 XSync(tqt_xdisplay(), False);
416 old_errhandler = XSetErrorHandler(kpixmapio_errorhandler);
417 kpixmapio_serial = NextRequest(tqt_xdisplay());
420 if ( !XShmAttach(tqt_xdisplay(), d->shminfo))
422 kdWarning() <<
"X-Server could not attach shared memory segment.\n";
424 shmdt(d->shminfo->shmaddr);
425 shmctl(d->shminfo->shmid, IPC_RMID, 0);
429 XSync(tqt_xdisplay(),
false);
434 XSetErrorHandler(old_errhandler);
435 d->first_try =
false;
449 TQImage KPixmapIO::convertFromXImage()
452 int width = d->ximage->width, height = d->ximage->height;
453 int bpl = d->ximage->bytes_per_line;
454 char *data = d->ximage->data;
459 image.create(width, height, 8);
464 XColor *cmap =
new XColor[ncells];
465 for (i=0; i<ncells; i++)
467 XQueryColors(tqt_xdisplay(), TQPaintDevice::x11AppColormap(),
469 image.setNumColors(ncells);
470 for (i=0; i<ncells; i++)
471 image.setColor(i, tqRgb(cmap[i].red, cmap[i].green, cmap[i].blue >> 8));
473 image.create(width, height, 32);
475 switch (d->byteorder)
480 for (y=0; y<height; y++)
481 memcpy(image.scanLine(y), data + y*bpl, width);
488 TQ_INT32 pixel, *src;
490 for (y=0; y<height; y++)
492 src = (TQ_INT32 *) (data + y*bpl);
493 dst = (TQRgb *) image.scanLine(y);
494 for (x=0; x<width/2; x++)
497 val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
498 ((pixel & 0x1f) << 3);
501 val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
502 ((pixel & 0x1f) << 3);
508 val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
509 ((pixel & 0x1f) << 3);
519 TQ_INT32 pixel, *src;
521 for (y=0; y<height; y++)
523 src = (TQ_INT32 *) (data + y*bpl);
524 dst = (TQRgb *) image.scanLine(y);
525 for (x=0; x<width/2; x++)
528 val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
529 ((pixel & 0x1f) << 3);
532 val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
533 ((pixel & 0x1f) << 3);
539 val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
540 ((pixel & 0x1f) << 3);
553 for (y=0; y<height; y++)
556 dst = (TQRgb *) image.scanLine(y);
559 d1 = *((TQ_INT32 *)src);
560 d2 = *((TQ_INT32 *)src + 1);
561 d3 = *((TQ_INT32 *)src + 2);
564 *dst++ = (d1 >> 24) | (d2 << 8);
565 *dst++ = (d3 << 16) | (d2 >> 16);
568 for (x=w1*4; x<width; x++)
585 for (y=0; y<height; y++)
588 dst = (TQRgb *) image.scanLine(y);
591 d1 = *((TQ_INT32 *)src);
592 d2 = *((TQ_INT32 *)src + 1);
593 d3 = *((TQ_INT32 *)src + 2);
596 *dst++ = (d1 >> 24) | (d2 << 8);
597 *dst++ = (d3 << 16) | (d2 >> 16);
600 for (x=w1*4; x<width; x++)
614 for (y=0; y<height; y++)
615 memcpy(image.scanLine(y), data + y*bpl, width*4);
625 void KPixmapIO::convertToXImage(
const TQImage &img)
628 int width = d->ximage->width, height = d->ximage->height;
629 int bpl = d->ximage->bytes_per_line;
630 char *data = d->ximage->data;
632 switch (d->byteorder)
638 if (img.depth() == 32)
642 for (y=0; y<height; y++)
644 src = (TQRgb *) img.scanLine(y);
645 dst = (TQ_INT32 *) (data + y*bpl);
646 for (x=0; x<width/2; x++)
649 val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
650 ((pixel & 0xff) >> 3);
652 val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
653 ((pixel & 0xff) >> 3)) << 16;
659 *((TQ_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
660 ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
667 TQRgb pixel, *clut = img.colorTable();
668 for (y=0; y<height; y++)
670 src =
const_cast<TQImage&
>(img).scanLine(y);
671 dst = (TQ_INT32 *) (data + y*bpl);
672 for (x=0; x<width/2; x++)
674 pixel = clut[*src++];
675 val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
676 ((pixel & 0xff) >> 3);
677 pixel = clut[*src++];
678 val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
679 ((pixel & 0xff) >> 3)) << 16;
684 pixel = clut[*src++];
685 *((TQ_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
686 ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
695 if (img.depth() == 32)
699 for (y=0; y<height; y++)
701 src = (TQRgb *) img.scanLine(y);
702 dst = (TQ_INT32 *) (data + y*bpl);
703 for (x=0; x<width/2; x++)
706 val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
707 ((pixel & 0xff) >> 3);
709 val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
710 ((pixel & 0xff) >> 3)) << 16;
716 *((TQ_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
717 ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
724 TQRgb pixel, *clut = img.colorTable();
725 for (y=0; y<height; y++)
727 src =
const_cast<TQImage&
>(img).scanLine(y);
728 dst = (TQ_INT32 *) (data + y*bpl);
729 for (x=0; x<width/2; x++)
731 pixel = clut[*src++];
732 val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
733 ((pixel & 0xff) >> 3);
734 pixel = clut[*src++];
735 val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
736 ((pixel & 0xff) >> 3)) << 16;
741 pixel = clut[*src++];
742 *((TQ_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
743 ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
751 if (img.depth() == 32)
755 TQRgb *src, d1, d2, d3, d4;
756 for (y=0; y<height; y++)
758 src = (TQRgb *) img.scanLine(y);
762 d1 = (*src++ & 0xffffff);
763 d2 = (*src++ & 0xffffff);
764 d3 = (*src++ & 0xffffff);
765 d4 = (*src++ & 0xffffff);
766 *((TQ_INT32 *)dst) = d1 | (d2 << 24);
767 *((TQ_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
768 *((TQ_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
771 for (x=w1*4; x<width; x++)
775 *dst++ = tqGreen(d1);
783 TQRgb *clut = img.colorTable(), d1, d2, d3, d4;
784 for (y=0; y<height; y++)
786 src =
const_cast<TQImage&
>(img).scanLine(y);
787 dst = (uchar *) data + y*bpl;
790 d1 = (clut[*src++] & 0xffffff);
791 d2 = (clut[*src++] & 0xffffff);
792 d3 = (clut[*src++] & 0xffffff);
793 d4 = (clut[*src++] & 0xffffff);
794 *((TQ_INT32 *)dst) = d1 | (d2 << 24);
795 *((TQ_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
796 *((TQ_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
799 for (x=w1*4; x<width; x++)
803 *dst++ = tqGreen(d1);
812 if (img.depth() == 32)
815 TQRgb *src, d1, d2, d3, d4;
817 for (y=0; y<height; y++)
819 src = (TQRgb *) img.scanLine(y);
823 d1 = (*src++ & 0xffffff);
824 d2 = (*src++ & 0xffffff);
825 d3 = (*src++ & 0xffffff);
826 d4 = (*src++ & 0xffffff);
827 *((TQ_INT32 *)dst) = d1 | (d2 << 24);
828 *((TQ_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
829 *((TQ_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
832 for (x=w1*4; x<width; x++)
836 *dst++ = tqGreen(d1);
844 TQRgb *clut = img.colorTable(), d1, d2, d3, d4;
845 for (y=0; y<height; y++)
847 src =
const_cast<TQImage&
>(img).scanLine(y);
848 dst = (uchar *) data + y*bpl;
851 d1 = (clut[*src++] & 0xffffff);
852 d2 = (clut[*src++] & 0xffffff);
853 d3 = (clut[*src++] & 0xffffff);
854 d4 = (clut[*src++] & 0xffffff);
855 *((TQ_INT32 *)dst) = d1 | (d2 << 24);
856 *((TQ_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
857 *((TQ_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
860 for (x=w1*4; x<width; x++)
864 *dst++ = tqGreen(d1);
874 if (img.depth() == 32)
876 for (y=0; y<height; y++)
877 memcpy(data + y*bpl, img.scanLine(y), width*4);
881 TQRgb *dst, *clut = img.colorTable();
882 for (y=0; y<height; y++)
884 src =
const_cast<TQImage&
>(img).scanLine(y);
885 dst = (TQRgb *) (data + y*bpl);
886 for (x=0; x<width; x++)
887 *dst++ = clut[*src++];
899 bool KPixmapIO::initXImage(
int,
int) {
return false; }
900 void KPixmapIO::doneXImage() {}
901 bool KPixmapIO::createXImage(
int,
int) {
return false; }
902 void KPixmapIO::destroyXImage() {}
903 bool KPixmapIO::createShmSegment(
int) {
return false; }
904 void KPixmapIO::destroyShmSegment() {}
905 TQImage KPixmapIO::convertFromXImage() {
return TQImage(); }
906 void KPixmapIO::convertToXImage(
const TQImage &) {}
void setShmPolicy(int policy)
Set the shared memory allocation policy.
void preAllocShm(int size)
Pre-allocate shared memory.
TQPixmap convertToPixmap(const TQImage &image)
Convert an image to a pixmap.
void putImage(TQPixmap *dst, int dx, int dy, const TQImage *src)
Bitblt an image onto a pixmap.
TQImage getImage(const TQPixmap *src, int sx, int sy, int sw, int sh)
Transfer (a part of) a pixmap to an image.
TQImage convertToImage(const TQPixmap &pixmap)
Convert a pixmap to an image.
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
static TDEConfig * config()
kndbgstream & endl(kndbgstream &s)
kdbgstream kdWarning(int area=0)
kdbgstream kdDebug(int area=0)