introduce static QX11Data methods to copy QImage from and to XImage

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-12-17 13:58:42 +02:00
parent fd8bd537e4
commit 6551966697
5 changed files with 204 additions and 146 deletions

View file

@ -748,6 +748,7 @@ set(GUI_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qx11info_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qx11info_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qkeymapper_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qkeymapper_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qeventdispatcher_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qeventdispatcher_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qt_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/math3d/qgenericmatrix.cpp ${CMAKE_CURRENT_SOURCE_DIR}/math3d/qgenericmatrix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/math3d/qmatrix4x4.cpp ${CMAKE_CURRENT_SOURCE_DIR}/math3d/qmatrix4x4.cpp
${CMAKE_CURRENT_SOURCE_DIR}/math3d/qquaternion.cpp ${CMAKE_CURRENT_SOURCE_DIR}/math3d/qquaternion.cpp
@ -995,6 +996,7 @@ katie_unity_exclude(
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qwidget_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qwidget_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qx11embed_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qx11embed_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qx11info_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qx11info_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qt_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/painting/qbackingstore.cpp ${CMAKE_CURRENT_SOURCE_DIR}/painting/qbackingstore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/painting/qcolor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/painting/qcolor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/painting/qcolormap_x11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/painting/qcolormap_x11.cpp

View file

@ -344,85 +344,7 @@ void QX11PixmapData::fromImage(const QImage &img,
xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0); xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0);
Q_CHECK_PTR(xi); Q_CHECK_PTR(xi);
newbits = (uchar *)::malloc(size_t(xi->bytes_per_line) * h); QX11Data::copyQImageToXImage(image, xi);
Q_CHECK_PTR(newbits);
xi->data = (char *)newbits;
switch(image.format()) {
case QImage::Format_Indexed8: {
QVector<QRgb> colorTable = image.colorTable();
uint *xidata = (uint *)xi->data;
for (int y = 0; y < h; ++y) {
const uchar *p = image.constScanLine(y);
for (int x = 0; x < w; ++x) {
const QRgb rgb = colorTable[p[x]];
const int a = qAlpha(rgb);
if (a == 0xff)
*xidata = rgb;
else
// RENDER expects premultiplied alpha
*xidata = qRgba(qt_div_255(qRed(rgb) * a),
qt_div_255(qGreen(rgb) * a),
qt_div_255(qBlue(rgb) * a),
a);
++xidata;
}
}
break;
}
case QImage::Format_RGB32: {
uint *xidata = (uint *)xi->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
for (int x = 0; x < w; ++x)
*xidata++ = p[x] | 0xff000000;
}
break;
}
case QImage::Format_ARGB32: {
uint *xidata = (uint *)xi->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
for (int x = 0; x < w; ++x) {
const QRgb rgb = p[x];
const int a = qAlpha(rgb);
if (a == 0xff)
*xidata = rgb;
else
// RENDER expects premultiplied alpha
*xidata = qRgba(qt_div_255(qRed(rgb) * a),
qt_div_255(qGreen(rgb) * a),
qt_div_255(qBlue(rgb) * a),
a);
++xidata;
}
}
break;
}
case QImage::Format_ARGB32_Premultiplied: {
uint *xidata = (uint *)xi->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
memcpy(xidata, p, w*sizeof(QRgb));
xidata += w;
}
break;
}
default:
Q_ASSERT(false);
}
if ((xi->byte_order == MSBFirst) != (Q_BYTE_ORDER == Q_BIG_ENDIAN)) {
uint *xidata = (uint *)xi->data;
uint *xiend = xidata + w*h;
while (xidata < xiend) {
*xidata = (*xidata >> 24)
| ((*xidata >> 8) & 0xff00)
| ((*xidata << 8) & 0xff0000)
| (*xidata << 24);
++xidata;
}
}
GC gc = XCreateGC(dpy, hd, 0, 0); GC gc = XCreateGC(dpy, hd, 0, 0);
XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h); XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
@ -435,22 +357,13 @@ void QX11PixmapData::fromImage(const QImage &img,
#endif // QT_NO_XRENDER #endif // QT_NO_XRENDER
if (!xi) { // X image not created if (!xi) { // X image not created
xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
Q_CHECK_PTR(xi);
newbits = (uchar *)::malloc(size_t(xi->bytes_per_line) * h);
Q_CHECK_PTR(newbits);
xi->data = (char *)newbits;
if (image.format() != QImage::Format_RGB32) { if (image.format() != QImage::Format_RGB32) {
image = image.convertToFormat(QImage::Format_RGB32, flags); image = image.convertToFormat(QImage::Format_RGB32, flags);
} }
uint *xidata = (uint *)xi->data; xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
for (int y = 0; y < h; ++y) { Q_CHECK_PTR(xi);
const QRgb *p = (const QRgb *) image.constScanLine(y); QX11Data::copyQImageToXImage(image, xi);
for (int x = 0; x < w; ++x)
*xidata++ = p[x] | 0xff000000;
}
} }
hd = (Qt::HANDLE)XCreatePixmap(qt_x11Data->display, hd = (Qt::HANDLE)XCreatePixmap(qt_x11Data->display,

194
src/gui/kernel/qt_x11.cpp Normal file
View file

@ -0,0 +1,194 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2016 Ivailo Monev
**
** This file is part of the QtGui module of the Katie Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcolor.h"
#include "qimage.h"
#include "qdrawhelper_p.h"
#include "qt_x11_p.h"
#include "qx11info_x11.h"
QT_BEGIN_NAMESPACE
#ifndef QT_NO_XRENDER
XRenderColor QX11Data::preMultiply(const QColor &c)
{
XRenderColor color;
const uint A = c.alpha(),
R = c.red(),
G = c.green(),
B = c.blue();
color.alpha = (A | A << 8);
color.red = (R | R << 8) * color.alpha / 0x10000;
color.green = (G | G << 8) * color.alpha / 0x10000;
color.blue = (B | B << 8) * color.alpha / 0x10000;
return color;
}
Picture QX11Data::getSolidFill(int screen, const QColor &c)
{
if (!qt_x11Data->use_xrender)
return XNone;
XRenderColor color = preMultiply(c);
for (int i = 0; i < QX11Data::solid_fill_count; ++i) {
if (qt_x11Data->solid_fills[i].screen == screen
&& qt_x11Data->solid_fills[i].color.alpha == color.alpha
&& qt_x11Data->solid_fills[i].color.red == color.red
&& qt_x11Data->solid_fills[i].color.green == color.green
&& qt_x11Data->solid_fills[i].color.blue == color.blue)
return qt_x11Data->solid_fills[i].picture;
}
// none found, replace one
int i = qrand() % QX11Data::solid_fill_count;
if (qt_x11Data->solid_fills[i].screen != screen && qt_x11Data->solid_fills[i].picture) {
XRenderFreePicture (qt_x11Data->display, qt_x11Data->solid_fills[i].picture);
qt_x11Data->solid_fills[i].picture = 0;
}
if (!qt_x11Data->solid_fills[i].picture) {
Pixmap pixmap = XCreatePixmap (qt_x11Data->display, RootWindow (qt_x11Data->display, screen), 1, 1, 32);
XRenderPictureAttributes attrs;
attrs.repeat = True;
qt_x11Data->solid_fills[i].picture = XRenderCreatePicture (qt_x11Data->display, pixmap,
XRenderFindStandardFormat(qt_x11Data->display, PictStandardARGB32),
CPRepeat, &attrs);
XFreePixmap (qt_x11Data->display, pixmap);
}
qt_x11Data->solid_fills[i].color = color;
qt_x11Data->solid_fills[i].screen = screen;
XRenderFillRectangle (qt_x11Data->display, PictOpSrc, qt_x11Data->solid_fills[i].picture, &color, 0, 0, 1, 1);
return qt_x11Data->solid_fills[i].picture;
}
#endif
void QX11Data::copyQImageToXImage(const QImage &image, XImage *ximage)
{
Q_ASSERT(ximage);
ximage->data = static_cast<char*>(::malloc(size_t(ximage->bytes_per_line) * image.height()));
Q_CHECK_PTR(ximage->data);
#if 0
for (int h = 0; h < image.height(); h++) {
for (int w = 0; w < image.width(); w++) {
const QRgb pixel = image.pixel(w, h);
XPutPixel(ximage, w, h, pixel);
}
}
#else
const int w = image.width();
const int h = image.height();
switch(image.format()) {
case QImage::Format_Indexed8: {
QVector<QRgb> colorTable = image.colorTable();
uint *xidata = (uint *)ximage->data;
for (int y = 0; y < h; ++y) {
const uchar *p = image.constScanLine(y);
for (int x = 0; x < w; ++x) {
const QRgb rgb = colorTable[p[x]];
const int a = qAlpha(rgb);
if (a == 0xff)
*xidata = rgb;
else
// RENDER expects premultiplied alpha
*xidata = qRgba(qt_div_255(qRed(rgb) * a),
qt_div_255(qGreen(rgb) * a),
qt_div_255(qBlue(rgb) * a),
a);
++xidata;
}
}
break;
}
case QImage::Format_RGB32: {
uint *xidata = (uint *)ximage->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
for (int x = 0; x < w; ++x)
*xidata++ = p[x] | 0xff000000;
}
break;
}
case QImage::Format_ARGB32: {
uint *xidata = (uint *)ximage->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
for (int x = 0; x < w; ++x) {
const QRgb rgb = p[x];
const int a = qAlpha(rgb);
if (a == 0xff)
*xidata = rgb;
else
// RENDER expects premultiplied alpha
*xidata = qRgba(qt_div_255(qRed(rgb) * a),
qt_div_255(qGreen(rgb) * a),
qt_div_255(qBlue(rgb) * a),
a);
++xidata;
}
}
break;
}
case QImage::Format_ARGB32_Premultiplied: {
uint *xidata = (uint *)ximage->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
memcpy(xidata, p, w*sizeof(QRgb));
xidata += w;
}
break;
}
default:
Q_ASSERT(false);
}
if ((ximage->byte_order == MSBFirst) != (Q_BYTE_ORDER == Q_BIG_ENDIAN)) {
uint *xidata = (uint *)ximage->data;
uint *xiend = xidata + w*h;
while (xidata < xiend) {
*xidata = (*xidata >> 24)
| ((*xidata >> 8) & 0xff00)
| ((*xidata << 8) & 0xff0000)
| (*xidata << 24);
++xidata;
}
}
#endif
}
void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image)
{
Q_ASSERT(ximage);
QImage qimage(ximage->height, ximage->height, QImage::systemFormat());
for (int h = 0; h < ximage->height; h++) {
for (int w = 0; w < ximage->width; w++) {
const unsigned long xpixel = XGetPixel(ximage, w, h);
qimage.setPixel(w, h, xpixel);
}
}
image = qimage;
}
QT_END_NAMESPACE

View file

@ -256,6 +256,9 @@ struct QX11Data
XRenderColor preMultiply(const QColor &c); XRenderColor preMultiply(const QColor &c);
#endif #endif
static void copyQImageToXImage(const QImage &image, XImage *ximage);
static void copyXImageToQImage(XImage *ximage, QImage &image);
bool has_fontconfig; bool has_fontconfig;
bool fc_antialias; bool fc_antialias;
int fc_hint_style; int fc_hint_style;

View file

@ -2824,60 +2824,6 @@ Qt::HANDLE QWidget::x11PictureHandle() const
#endif // QT_NO_XRENDER #endif // QT_NO_XRENDER
} }
#ifndef QT_NO_XRENDER
XRenderColor QX11Data::preMultiply(const QColor &c)
{
XRenderColor color;
const uint A = c.alpha(),
R = c.red(),
G = c.green(),
B = c.blue();
color.alpha = (A | A << 8);
color.red = (R | R << 8) * color.alpha / 0x10000;
color.green = (G | G << 8) * color.alpha / 0x10000;
color.blue = (B | B << 8) * color.alpha / 0x10000;
return color;
}
Picture QX11Data::getSolidFill(int screen, const QColor &c)
{
if (!qt_x11Data->use_xrender)
return XNone;
XRenderColor color = preMultiply(c);
for (int i = 0; i < QX11Data::solid_fill_count; ++i) {
if (qt_x11Data->solid_fills[i].screen == screen
&& qt_x11Data->solid_fills[i].color.alpha == color.alpha
&& qt_x11Data->solid_fills[i].color.red == color.red
&& qt_x11Data->solid_fills[i].color.green == color.green
&& qt_x11Data->solid_fills[i].color.blue == color.blue)
return qt_x11Data->solid_fills[i].picture;
}
// none found, replace one
int i = qrand() % QX11Data::solid_fill_count;
if (qt_x11Data->solid_fills[i].screen != screen && qt_x11Data->solid_fills[i].picture) {
XRenderFreePicture (qt_x11Data->display, qt_x11Data->solid_fills[i].picture);
qt_x11Data->solid_fills[i].picture = 0;
}
if (!qt_x11Data->solid_fills[i].picture) {
Pixmap pixmap = XCreatePixmap (qt_x11Data->display, RootWindow (qt_x11Data->display, screen), 1, 1, 32);
XRenderPictureAttributes attrs;
attrs.repeat = True;
qt_x11Data->solid_fills[i].picture = XRenderCreatePicture (qt_x11Data->display, pixmap,
XRenderFindStandardFormat(qt_x11Data->display, PictStandardARGB32),
CPRepeat, &attrs);
XFreePixmap (qt_x11Data->display, pixmap);
}
qt_x11Data->solid_fills[i].color = color;
qt_x11Data->solid_fills[i].screen = screen;
XRenderFillRectangle (qt_x11Data->display, PictOpSrc, qt_x11Data->solid_fills[i].picture, &color, 0, 0, 1, 1);
return qt_x11Data->solid_fills[i].picture;
}
#endif
void QWidgetPrivate::updateX11AcceptFocus() void QWidgetPrivate::updateX11AcceptFocus()
{ {
Q_Q(QWidget); Q_Q(QWidget);