summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qpixmap_x11.cpp
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-06-27 03:04:41 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-06-27 03:04:41 (GMT)
commit863733d86e2dd0cd508e2928e5f995b88579ab40 (patch)
tree79aeb4a18db6e50d84c7934d517eb32f382dd13a /src/gui/image/qpixmap_x11.cpp
parent59c58576efd3ceff7add46a359fd99e56a2fb279 (diff)
parentcc75093e3b300a37d05a81921d7811caabbfb449 (diff)
downloadQt-863733d86e2dd0cd508e2928e5f995b88579ab40.zip
Qt-863733d86e2dd0cd508e2928e5f995b88579ab40.tar.gz
Qt-863733d86e2dd0cd508e2928e5f995b88579ab40.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2: (21 commits) EGL plane levels are the same as all other GL backends. Need to access extensionFuncs in subclasses too. Export QGLWindowSurface too. Export the QGLPixmapData so that we can override it in a custom graphics system. Fixed autotest failure in QPathClipper on N900. Fixed autotest failure in QPainter::setOpacity when NEON is used. Fix compilation when configured with -no-xrender Add a new (internal) flag QGraphicsItem::ItemStopsClickFocusPropagation. Fixed some potential index-out-of-bounds issues in QImage. Fixed autotest failure in fillRect_stretchToDeviceMode Adding a known issue for VC2010 64 bit Added a note to desupport VC2010 64-bit Normalize integers when calling glVertexAttribPointer() Add an implementation of comp_func_solid_SourceOver_neon() with Neon. Fix the casts of qdrawhelper_sse2 Add a SSE2 implementation of comp_func_solid_SourceOver() Add a SSE2 version of comp_func_SourceOver() Fixed missing copy of raster pixmap data after change fb76a872e20bd. Fixed QPixmap::toImage() bug introduced in fb76a872e20bd. Optimized sub-rect copying / painting of QPixmaps. ...
Diffstat (limited to 'src/gui/image/qpixmap_x11.cpp')
-rw-r--r--src/gui/image/qpixmap_x11.cpp182
1 files changed, 124 insertions, 58 deletions
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index e8dc5ae..3d9c363 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -1458,6 +1458,105 @@ int QX11PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
}
}
+struct QXImageWrapper
+{
+ XImage *xi;
+};
+
+bool QX11PixmapData::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const
+{
+ XImage *xi = xiWrapper.xi;
+
+ // ARGB32_Premultiplied
+ if (picture && depth() == 32)
+ return true;
+
+ Visual *visual = (Visual *)xinfo.visual();
+
+ // RGB32
+ if (depth() == 24 && xi->bits_per_pixel == 32 && visual->red_mask == 0xff0000
+ && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
+ return true;
+
+ // RGB16
+ if (depth() == 16 && xi->bits_per_pixel == 16 && visual->red_mask == 0xf800
+ && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
+ return true;
+
+ return false;
+}
+
+QImage QX11PixmapData::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const
+{
+ XImage *xi = xiWrapper.xi;
+
+ QImage::Format format = QImage::Format_ARGB32_Premultiplied;
+ if (depth() == 24)
+ format = QImage::Format_RGB32;
+ else if (depth() == 16)
+ format = QImage::Format_RGB16;
+
+ QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format);
+ // take ownership
+ image.data_ptr()->own_data = true;
+ xi->data = 0;
+
+ // we may have to swap the byte order
+ if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
+ || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
+ {
+ for (int i=0; i < image.height(); i++) {
+ if (depth() == 16) {
+ ushort *p = (ushort*)image.scanLine(i);
+ ushort *end = p + image.width();
+ while (p < end) {
+ *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
+ p++;
+ }
+ } else {
+ uint *p = (uint*)image.scanLine(i);
+ uint *end = p + image.width();
+ while (p < end) {
+ *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
+ p++;
+ }
+ }
+ }
+ }
+
+ // fix-up alpha channel
+ if (format == QImage::Format_RGB32) {
+ QRgb *p = (QRgb *)image.bits();
+ for (int y = 0; y < xi->height; ++y) {
+ for (int x = 0; x < xi->width; ++x)
+ p[x] |= 0xff000000;
+ p += xi->bytes_per_line / 4;
+ }
+ }
+
+ XDestroyImage(xi);
+ return image;
+}
+
+QImage QX11PixmapData::toImage(const QRect &rect) const
+{
+ QXImageWrapper xiWrapper;
+ xiWrapper.xi = XGetImage(X11->display, hd, rect.x(), rect.y(), rect.width(), rect.height(),
+ AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap);
+
+ Q_CHECK_PTR(xiWrapper.xi);
+ if (!xiWrapper.xi)
+ return QImage();
+
+ if (canTakeQImageFromXImage(xiWrapper))
+ return takeQImageFromXImage(xiWrapper);
+
+ QImage image = toImage(xiWrapper, rect);
+ qSafeXDestroyImage(xiWrapper.xi);
+ return image;
+}
+
/*!
Converts the pixmap to a QImage. Returns a null image if the
conversion fails.
@@ -1475,6 +1574,13 @@ int QX11PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
QImage QX11PixmapData::toImage() const
{
+ return toImage(QRect(0, 0, w, h));
+}
+
+QImage QX11PixmapData::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const
+{
+ XImage *xi = xiWrapper.xi;
+
int d = depth();
Visual *visual = (Visual *)xinfo.visual();
bool trucol = (visual->c_class >= TrueColor) && d > 1;
@@ -1492,59 +1598,21 @@ QImage QX11PixmapData::toImage() const
format = QImage::Format_RGB32;
}
- XImage *xi = XGetImage(X11->display, hd, 0, 0, w, h, AllPlanes,
- (d == 1) ? XYPixmap : ZPixmap);
-
- Q_CHECK_PTR(xi);
- if (!xi)
- return QImage();
-
- if (picture && depth() == 32) {
- QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
- memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height);
-
- // we may have to swap the byte order
- if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
- || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
- {
- for (int i=0; i < image.height(); i++) {
- uint *p = (uint*)image.scanLine(i);
- uint *end = p + image.width();
- if ((xi->byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
- || (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
- while (p < end) {
- *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- } else if (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- while (p < end) {
- *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
- | ((*p ) & 0xff00ff00);
- p++;
- }
- }
- }
- }
-
- // throw away image data
- qSafeXDestroyImage(xi);
-
- return image;
- }
-
if (d == 1 && xi->bitmap_bit_order == LSBFirst)
format = QImage::Format_MonoLSB;
if (x11_mask && format == QImage::Format_RGB32)
format = QImage::Format_ARGB32;
- QImage image(w, h, format);
+ QImage image(xi->width, xi->height, format);
if (image.isNull()) // could not create image
return image;
QImage alpha;
if (x11_mask) {
- alpha = mask().toImage();
+ if (rect.contains(QRect(0, 0, w, h)))
+ alpha = mask().toImage();
+ else
+ alpha = mask().toImage().copy(rect);
}
bool ale = alpha.format() == QImage::Format_MonoLSB;
@@ -1587,11 +1655,11 @@ QImage QX11PixmapData::toImage() const
if (bppc > 8 && xi->byte_order == LSBFirst)
bppc++;
- for (int y = 0; y < h; ++y) {
+ for (int y = 0; y < xi->height; ++y) {
uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
dst = (QRgb *)image.scanLine(y);
src = (uchar *)xi->data + xi->bytes_per_line*y;
- for (int x = 0; x < w; x++) {
+ for (int x = 0; x < xi->width; x++) {
switch (bppc) {
case 8:
pixel = *src++;
@@ -1621,8 +1689,8 @@ QImage QX11PixmapData::toImage() const
src += 4;
break;
default: // should not really happen
- x = w; // leave loop
- y = h;
+ x = xi->width; // leave loop
+ y = xi->height;
pixel = 0; // eliminate compiler warning
qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
}
@@ -1660,7 +1728,7 @@ QImage QX11PixmapData::toImage() const
} else if (xi->bits_per_pixel == d) { // compatible depth
char *xidata = xi->data; // copy each scanline
int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
- for (int y=0; y<h; y++) {
+ for (int y=0; y<xi->height; y++) {
memcpy(image.scanLine(y), xidata, bpl);
xidata += xi->bytes_per_line;
}
@@ -1686,17 +1754,17 @@ QImage QX11PixmapData::toImage() const
bpl = image.bytesPerLine();
if (x11_mask) { // which pixels are used?
- for (int i = 0; i < h; i++) {
+ for (int i = 0; i < xi->height; i++) {
uchar* asrc = alpha.scanLine(i);
p = image.scanLine(i);
if (ale) {
- for (int x = 0; x < w; x++) {
+ for (int x = 0; x < xi->width; x++) {
if (asrc[x >> 3] & (1 << (x & 7)))
use[*p] = 1;
++p;
}
} else {
- for (int x = 0; x < w; x++) {
+ for (int x = 0; x < xi->width; x++) {
if (asrc[x >> 3] & (0x80 >> (x & 7)))
use[*p] = 1;
++p;
@@ -1704,7 +1772,7 @@ QImage QX11PixmapData::toImage() const
}
}
} else {
- for (int i = 0; i < h; i++) {
+ for (int i = 0; i < xi->height; i++) {
p = image.scanLine(i);
end = p + bpl;
while (p < end)
@@ -1716,7 +1784,7 @@ QImage QX11PixmapData::toImage() const
if (use[i])
pix[i] = ncols++;
}
- for (int i = 0; i < h; i++) { // translate pixels
+ for (int i = 0; i < xi->height; i++) { // translate pixels
p = image.scanLine(i);
end = p + bpl;
while (p < end) {
@@ -1736,17 +1804,17 @@ QImage QX11PixmapData::toImage() const
// use first pixel in image (as good as any).
trans = image.scanLine(0)[0];
}
- for (int i = 0; i < h; i++) {
+ for (int i = 0; i < xi->height; i++) {
uchar* asrc = alpha.scanLine(i);
p = image.scanLine(i);
if (ale) {
- for (int x = 0; x < w; x++) {
+ for (int x = 0; x < xi->width; x++) {
if (!(asrc[x >> 3] & (1 << (x & 7))))
*p = trans;
++p;
}
} else {
- for (int x = 0; x < w; x++) {
+ for (int x = 0; x < xi->width; x++) {
if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
*p = trans;
++p;
@@ -1764,8 +1832,6 @@ QImage QX11PixmapData::toImage() const
}
}
- qSafeXDestroyImage(xi);
-
return image;
}