src/gui/image/qpixmap_x11.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
  1248 {
  1248 {
  1249     delete pengine;
  1249     delete pengine;
  1250     pengine = 0;
  1250     pengine = 0;
  1251 
  1251 
  1252     if (!X11) {
  1252     if (!X11) {
  1253 #ifndef QT_NO_DEBUG
  1253         // At this point, the X server will already have freed our resources,
  1254         qWarning("~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication"
  1254         // so there is nothing to do.
  1255                  " object, otherwise the native pixmap object will be leaked.");
       
  1256 #endif
       
  1257         return;
  1255         return;
  1258     }
  1256     }
  1259 
  1257 
  1260     if (x11_mask) {
  1258     if (x11_mask) {
  1261 #ifndef QT_NO_XRENDER
  1259 #ifndef QT_NO_XRENDER
  1458         qWarning("QX11PixmapData::metric(): Invalid metric");
  1456         qWarning("QX11PixmapData::metric(): Invalid metric");
  1459         return 0;
  1457         return 0;
  1460     }
  1458     }
  1461 }
  1459 }
  1462 
  1460 
       
  1461 struct QXImageWrapper
       
  1462 {
       
  1463     XImage *xi;
       
  1464 };
       
  1465 
       
  1466 bool QX11PixmapData::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const
       
  1467 {
       
  1468     XImage *xi = xiWrapper.xi;
       
  1469 
       
  1470     // ARGB32_Premultiplied
       
  1471     if (picture && depth() == 32)
       
  1472         return true;
       
  1473 
       
  1474     Visual *visual = (Visual *)xinfo.visual();
       
  1475 
       
  1476     // RGB32
       
  1477     if (depth() == 24 && xi->bits_per_pixel == 32 && visual->red_mask == 0xff0000
       
  1478         && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
       
  1479         return true;
       
  1480 
       
  1481     // RGB16
       
  1482     if (depth() == 16 && xi->bits_per_pixel == 16 && visual->red_mask == 0xf800
       
  1483         && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
       
  1484         return true;
       
  1485 
       
  1486     return false;
       
  1487 }
       
  1488 
       
  1489 QImage QX11PixmapData::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const
       
  1490 {
       
  1491     XImage *xi = xiWrapper.xi;
       
  1492 
       
  1493     QImage::Format format = QImage::Format_ARGB32_Premultiplied;
       
  1494     if (depth() == 24)
       
  1495         format = QImage::Format_RGB32;
       
  1496     else if (depth() == 16)
       
  1497         format = QImage::Format_RGB16;
       
  1498 
       
  1499     QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format);
       
  1500     // take ownership
       
  1501     image.data_ptr()->own_data = true;
       
  1502     xi->data = 0;
       
  1503 
       
  1504     // we may have to swap the byte order
       
  1505     if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
       
  1506         || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
       
  1507     {
       
  1508         for (int i=0; i < image.height(); i++) {
       
  1509             if (depth() == 16) {
       
  1510                 ushort *p = (ushort*)image.scanLine(i);
       
  1511                 ushort *end = p + image.width();
       
  1512                 while (p < end) {
       
  1513                     *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
       
  1514                     p++;
       
  1515                 }
       
  1516             } else {
       
  1517                 uint *p = (uint*)image.scanLine(i);
       
  1518                 uint *end = p + image.width();
       
  1519                 while (p < end) {
       
  1520                     *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
       
  1521                          | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
       
  1522                     p++;
       
  1523                 }
       
  1524             }
       
  1525         }
       
  1526     }
       
  1527 
       
  1528     // fix-up alpha channel
       
  1529     if (format == QImage::Format_RGB32) {
       
  1530         QRgb *p = (QRgb *)image.bits();
       
  1531         for (int y = 0; y < xi->height; ++y) {
       
  1532             for (int x = 0; x < xi->width; ++x)
       
  1533                 p[x] |= 0xff000000;
       
  1534             p += xi->bytes_per_line / 4;
       
  1535         }
       
  1536     }
       
  1537 
       
  1538     XDestroyImage(xi);
       
  1539     return image;
       
  1540 }
       
  1541 
       
  1542 QImage QX11PixmapData::toImage(const QRect &rect) const
       
  1543 {
       
  1544     QXImageWrapper xiWrapper;
       
  1545     xiWrapper.xi = XGetImage(X11->display, hd, rect.x(), rect.y(), rect.width(), rect.height(),
       
  1546                              AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap);
       
  1547 
       
  1548     Q_CHECK_PTR(xiWrapper.xi);
       
  1549     if (!xiWrapper.xi)
       
  1550         return QImage();
       
  1551 
       
  1552     if (canTakeQImageFromXImage(xiWrapper))
       
  1553         return takeQImageFromXImage(xiWrapper);
       
  1554 
       
  1555     QImage image = toImage(xiWrapper, rect);
       
  1556     qSafeXDestroyImage(xiWrapper.xi);
       
  1557     return image;
       
  1558 }
       
  1559 
  1463 /*!
  1560 /*!
  1464     Converts the pixmap to a QImage. Returns a null image if the
  1561     Converts the pixmap to a QImage. Returns a null image if the
  1465     conversion fails.
  1562     conversion fails.
  1466 
  1563 
  1467     If the pixmap has 1-bit depth, the returned image will also be 1
  1564     If the pixmap has 1-bit depth, the returned image will also be 1
  1475     \sa fromImage(), {QImage#Image Formats}{Image Formats}
  1572     \sa fromImage(), {QImage#Image Formats}{Image Formats}
  1476 */
  1573 */
  1477 
  1574 
  1478 QImage QX11PixmapData::toImage() const
  1575 QImage QX11PixmapData::toImage() const
  1479 {
  1576 {
       
  1577     return toImage(QRect(0, 0, w, h));
       
  1578 }
       
  1579 
       
  1580 QImage QX11PixmapData::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const
       
  1581 {
       
  1582     XImage *xi = xiWrapper.xi;
       
  1583 
  1480     int d = depth();
  1584     int d = depth();
  1481     Visual *visual = (Visual *)xinfo.visual();
  1585     Visual *visual = (Visual *)xinfo.visual();
  1482     bool trucol = (visual->c_class >= TrueColor) && d > 1;
  1586     bool trucol = (visual->c_class >= TrueColor) && d > 1;
  1483 
  1587 
  1484     QImage::Format format = QImage::Format_Mono;
  1588     QImage::Format format = QImage::Format_Mono;
  1492     if (d > 8 || trucol) {
  1596     if (d > 8 || trucol) {
  1493         d = 32;
  1597         d = 32;
  1494         format = QImage::Format_RGB32;
  1598         format = QImage::Format_RGB32;
  1495     }
  1599     }
  1496 
  1600 
  1497     XImage *xi = XGetImage(X11->display, hd, 0, 0, w, h, AllPlanes,
       
  1498                            (d == 1) ? XYPixmap : ZPixmap);
       
  1499 
       
  1500     Q_CHECK_PTR(xi);
       
  1501     if (!xi)
       
  1502         return QImage();
       
  1503 
       
  1504     if (picture && depth() == 32) {
       
  1505         QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
       
  1506         memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height);
       
  1507 
       
  1508         // we may have to swap the byte order
       
  1509         if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
       
  1510             || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
       
  1511         {
       
  1512             for (int i=0; i < image.height(); i++) {
       
  1513                 uint *p = (uint*)image.scanLine(i);
       
  1514                 uint *end = p + image.width();
       
  1515                 if ((xi->byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
       
  1516                     || (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
       
  1517                     while (p < end) {
       
  1518                         *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
       
  1519                              | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
       
  1520                         p++;
       
  1521                     }
       
  1522                 } else if (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) {
       
  1523                     while (p < end) {
       
  1524                         *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
       
  1525                              | ((*p ) & 0xff00ff00);
       
  1526                         p++;
       
  1527                     }
       
  1528                 }
       
  1529             }
       
  1530         }
       
  1531 
       
  1532         // throw away image data
       
  1533         qSafeXDestroyImage(xi);
       
  1534 
       
  1535         return image;
       
  1536     }
       
  1537 
       
  1538     if (d == 1 && xi->bitmap_bit_order == LSBFirst)
  1601     if (d == 1 && xi->bitmap_bit_order == LSBFirst)
  1539         format = QImage::Format_MonoLSB;
  1602         format = QImage::Format_MonoLSB;
  1540     if (x11_mask && format == QImage::Format_RGB32)
  1603     if (x11_mask && format == QImage::Format_RGB32)
  1541         format = QImage::Format_ARGB32;
  1604         format = QImage::Format_ARGB32;
  1542 
  1605 
  1543     QImage image(w, h, format);
  1606     QImage image(xi->width, xi->height, format);
  1544     if (image.isNull())                        // could not create image
  1607     if (image.isNull())                        // could not create image
  1545         return image;
  1608         return image;
  1546 
  1609 
  1547     QImage alpha;
  1610     QImage alpha;
  1548     if (x11_mask) {
  1611     if (x11_mask) {
  1549         alpha = mask().toImage();
  1612         if (rect.contains(QRect(0, 0, w, h)))
       
  1613             alpha = mask().toImage();
       
  1614         else
       
  1615             alpha = mask().toImage().copy(rect);
  1550     }
  1616     }
  1551     bool ale = alpha.format() == QImage::Format_MonoLSB;
  1617     bool ale = alpha.format() == QImage::Format_MonoLSB;
  1552 
  1618 
  1553     if (trucol) {                                // truecolor
  1619     if (trucol) {                                // truecolor
  1554         const uint red_mask = (uint)visual->red_mask;
  1620         const uint red_mask = (uint)visual->red_mask;
  1587         int bppc = xi->bits_per_pixel;
  1653         int bppc = xi->bits_per_pixel;
  1588 
  1654 
  1589         if (bppc > 8 && xi->byte_order == LSBFirst)
  1655         if (bppc > 8 && xi->byte_order == LSBFirst)
  1590             bppc++;
  1656             bppc++;
  1591 
  1657 
  1592         for (int y = 0; y < h; ++y) {
  1658         for (int y = 0; y < xi->height; ++y) {
  1593             uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
  1659             uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
  1594             dst = (QRgb *)image.scanLine(y);
  1660             dst = (QRgb *)image.scanLine(y);
  1595             src = (uchar *)xi->data + xi->bytes_per_line*y;
  1661             src = (uchar *)xi->data + xi->bytes_per_line*y;
  1596             for (int x = 0; x < w; x++) {
  1662             for (int x = 0; x < xi->width; x++) {
  1597                 switch (bppc) {
  1663                 switch (bppc) {
  1598                 case 8:
  1664                 case 8:
  1599                     pixel = *src++;
  1665                     pixel = *src++;
  1600                     break;
  1666                     break;
  1601                 case 16:                        // 16 bit MSB
  1667                 case 16:                        // 16 bit MSB
  1621                 case 33:                        // 32 bit LSB
  1687                 case 33:                        // 32 bit LSB
  1622                     pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24;
  1688                     pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24;
  1623                     src += 4;
  1689                     src += 4;
  1624                     break;
  1690                     break;
  1625                 default:                        // should not really happen
  1691                 default:                        // should not really happen
  1626                     x = w;                        // leave loop
  1692                     x = xi->width;                        // leave loop
  1627                     y = h;
  1693                     y = xi->height;
  1628                     pixel = 0;                // eliminate compiler warning
  1694                     pixel = 0;                // eliminate compiler warning
  1629                     qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
  1695                     qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
  1630                 }
  1696                 }
  1631                 if (red_shift > 0)
  1697                 if (red_shift > 0)
  1632                     r = (pixel & red_mask) >> red_shift;
  1698                     r = (pixel & red_mask) >> red_shift;
  1660             }
  1726             }
  1661         }
  1727         }
  1662     } else if (xi->bits_per_pixel == d) {        // compatible depth
  1728     } else if (xi->bits_per_pixel == d) {        // compatible depth
  1663         char *xidata = xi->data;                // copy each scanline
  1729         char *xidata = xi->data;                // copy each scanline
  1664         int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
  1730         int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
  1665         for (int y=0; y<h; y++) {
  1731         for (int y=0; y<xi->height; y++) {
  1666             memcpy(image.scanLine(y), xidata, bpl);
  1732             memcpy(image.scanLine(y), xidata, bpl);
  1667             xidata += xi->bytes_per_line;
  1733             xidata += xi->bytes_per_line;
  1668         }
  1734         }
  1669     } else {
  1735     } else {
  1670         /* Typically 2 or 4 bits display depth */
  1736         /* Typically 2 or 4 bits display depth */
  1686         memset(use, 0, 256);
  1752         memset(use, 0, 256);
  1687         memset(pix, 0, 256);
  1753         memset(pix, 0, 256);
  1688         bpl = image.bytesPerLine();
  1754         bpl = image.bytesPerLine();
  1689 
  1755 
  1690         if (x11_mask) {                         // which pixels are used?
  1756         if (x11_mask) {                         // which pixels are used?
  1691             for (int i = 0; i < h; i++) {
  1757             for (int i = 0; i < xi->height; i++) {
  1692                 uchar* asrc = alpha.scanLine(i);
  1758                 uchar* asrc = alpha.scanLine(i);
  1693                 p = image.scanLine(i);
  1759                 p = image.scanLine(i);
  1694                 if (ale) {
  1760                 if (ale) {
  1695                     for (int x = 0; x < w; x++) {
  1761                     for (int x = 0; x < xi->width; x++) {
  1696                         if (asrc[x >> 3] & (1 << (x & 7)))
  1762                         if (asrc[x >> 3] & (1 << (x & 7)))
  1697                             use[*p] = 1;
  1763                             use[*p] = 1;
  1698                         ++p;
  1764                         ++p;
  1699                     }
  1765                     }
  1700                 } else {
  1766                 } else {
  1701                     for (int x = 0; x < w; x++) {
  1767                     for (int x = 0; x < xi->width; x++) {
  1702                         if (asrc[x >> 3] & (0x80 >> (x & 7)))
  1768                         if (asrc[x >> 3] & (0x80 >> (x & 7)))
  1703                             use[*p] = 1;
  1769                             use[*p] = 1;
  1704                         ++p;
  1770                         ++p;
  1705                     }
  1771                     }
  1706                 }
  1772                 }
  1707             }
  1773             }
  1708         } else {
  1774         } else {
  1709             for (int i = 0; i < h; i++) {
  1775             for (int i = 0; i < xi->height; i++) {
  1710                 p = image.scanLine(i);
  1776                 p = image.scanLine(i);
  1711                 end = p + bpl;
  1777                 end = p + bpl;
  1712                 while (p < end)
  1778                 while (p < end)
  1713                     use[*p++] = 1;
  1779                     use[*p++] = 1;
  1714             }
  1780             }
  1716         ncols = 0;
  1782         ncols = 0;
  1717         for (int i = 0; i < 256; i++) {                // build translation table
  1783         for (int i = 0; i < 256; i++) {                // build translation table
  1718             if (use[i])
  1784             if (use[i])
  1719                 pix[i] = ncols++;
  1785                 pix[i] = ncols++;
  1720         }
  1786         }
  1721         for (int i = 0; i < h; i++) {                        // translate pixels
  1787         for (int i = 0; i < xi->height; i++) {                        // translate pixels
  1722             p = image.scanLine(i);
  1788             p = image.scanLine(i);
  1723             end = p + bpl;
  1789             end = p + bpl;
  1724             while (p < end) {
  1790             while (p < end) {
  1725                 *p = pix[*p];
  1791                 *p = pix[*p];
  1726                 p++;
  1792                 p++;
  1736                 image.setColorCount(ncols);        // create color table
  1802                 image.setColorCount(ncols);        // create color table
  1737                 // oh dear... no spare "transparent" pixel.
  1803                 // oh dear... no spare "transparent" pixel.
  1738                 // use first pixel in image (as good as any).
  1804                 // use first pixel in image (as good as any).
  1739                 trans = image.scanLine(0)[0];
  1805                 trans = image.scanLine(0)[0];
  1740             }
  1806             }
  1741             for (int i = 0; i < h; i++) {
  1807             for (int i = 0; i < xi->height; i++) {
  1742                 uchar* asrc = alpha.scanLine(i);
  1808                 uchar* asrc = alpha.scanLine(i);
  1743                 p = image.scanLine(i);
  1809                 p = image.scanLine(i);
  1744                 if (ale) {
  1810                 if (ale) {
  1745                     for (int x = 0; x < w; x++) {
  1811                     for (int x = 0; x < xi->width; x++) {
  1746                         if (!(asrc[x >> 3] & (1 << (x & 7))))
  1812                         if (!(asrc[x >> 3] & (1 << (x & 7))))
  1747                             *p = trans;
  1813                             *p = trans;
  1748                         ++p;
  1814                         ++p;
  1749                     }
  1815                     }
  1750                 } else {
  1816                 } else {
  1751                     for (int x = 0; x < w; x++) {
  1817                     for (int x = 0; x < xi->width; x++) {
  1752                         if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
  1818                         if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
  1753                             *p = trans;
  1819                             *p = trans;
  1754                         ++p;
  1820                         ++p;
  1755                     }
  1821                     }
  1756                 }
  1822                 }
  1763         for (int i=0; i<colors.size(); i++) {                // translate pixels
  1829         for (int i=0; i<colors.size(); i++) {                // translate pixels
  1764             if (use[i])
  1830             if (use[i])
  1765                 image.setColor(j++, 0xff000000 | colors.at(i).rgb());
  1831                 image.setColor(j++, 0xff000000 | colors.at(i).rgb());
  1766         }
  1832         }
  1767     }
  1833     }
  1768 
       
  1769     qSafeXDestroyImage(xi);
       
  1770 
  1834 
  1771     return image;
  1835     return image;
  1772 }
  1836 }
  1773 
  1837 
  1774 /*!
  1838 /*!