QPixmap: move mask functions into QPlatformPixmap

These used to be in QPixmapData in Qt4, allowing platforms to override
mask handling. Useful when native 32-bit ARGB might not be available.

Change-Id: I1fcb77222ee4bc4705a8b4c614c9d5c3938c47ba
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Louai Al-Khanji 2016-11-21 14:00:45 -08:00 committed by Eirik Aavitsland
parent 208c71768c
commit a512c9c2f7
3 changed files with 81 additions and 69 deletions

View File

@ -596,44 +596,7 @@ void QPixmap::setMask(const QBitmap &mask)
return;
detach();
QImage image = data->toImage();
if (mask.size().isEmpty()) {
if (image.depth() != 1) { // hw: ????
image = image.convertToFormat(QImage::Format_RGB32);
}
} else {
const int w = image.width();
const int h = image.height();
switch (image.depth()) {
case 1: {
const QImage imageMask = mask.toImage().convertToFormat(image.format());
for (int y = 0; y < h; ++y) {
const uchar *mscan = imageMask.scanLine(y);
uchar *tscan = image.scanLine(y);
int bytesPerLine = image.bytesPerLine();
for (int i = 0; i < bytesPerLine; ++i)
tscan[i] &= mscan[i];
}
break;
}
default: {
const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
for (int y = 0; y < h; ++y) {
const uchar *mscan = imageMask.scanLine(y);
QRgb *tscan = (QRgb *)image.scanLine(y);
for (int x = 0; x < w; ++x) {
if (!(mscan[x>>3] & (1 << (x&7))))
tscan[x] = 0;
}
}
break;
}
}
}
data->fromImage(image, Qt::AutoColor);
data->setMask(mask);
}
/*!
@ -1496,37 +1459,7 @@ QPaintEngine *QPixmap::paintEngine() const
*/
QBitmap QPixmap::mask() const
{
if (!data || !hasAlphaChannel())
return QBitmap();
const QImage img = toImage();
bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
const int w = image.width();
const int h = image.height();
QImage mask(w, h, QImage::Format_MonoLSB);
if (mask.isNull()) // allocation failed
return QBitmap();
mask.setColorCount(2);
mask.setColor(0, QColor(Qt::color0).rgba());
mask.setColor(1, QColor(Qt::color1).rgba());
const int bpl = mask.bytesPerLine();
for (int y = 0; y < h; ++y) {
const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
uchar *dest = mask.scanLine(y);
memset(dest, 0, bpl);
for (int x = 0; x < w; ++x) {
if (qAlpha(*src) > 0)
dest[x >> 3] |= (1 << (x & 7));
++src;
}
}
return QBitmap::fromImage(mask);
return data ? data->mask() : QBitmap();
}
/*!

View File

@ -160,6 +160,82 @@ bool QPlatformPixmap::scroll(int dx, int dy, const QRect &rect)
return false;
}
QBitmap QPlatformPixmap::mask() const
{
if (!hasAlphaChannel())
return QBitmap();
const QImage img = toImage();
bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
const int w = image.width();
const int h = image.height();
QImage mask(w, h, QImage::Format_MonoLSB);
if (mask.isNull()) // allocation failed
return QBitmap();
mask.setColorCount(2);
mask.setColor(0, QColor(Qt::color0).rgba());
mask.setColor(1, QColor(Qt::color1).rgba());
const int bpl = mask.bytesPerLine();
for (int y = 0; y < h; ++y) {
const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
uchar *dest = mask.scanLine(y);
memset(dest, 0, bpl);
for (int x = 0; x < w; ++x) {
if (qAlpha(*src) > 0)
dest[x >> 3] |= (1 << (x & 7));
++src;
}
}
return QBitmap::fromImage(mask);
}
void QPlatformPixmap::setMask(const QBitmap &mask)
{
QImage image = toImage();
if (mask.size().isEmpty()) {
if (image.depth() != 1) { // hw: ????
image = image.convertToFormat(QImage::Format_RGB32);
}
} else {
const int w = image.width();
const int h = image.height();
switch (image.depth()) {
case 1: {
const QImage imageMask = mask.toImage().convertToFormat(image.format());
for (int y = 0; y < h; ++y) {
const uchar *mscan = imageMask.scanLine(y);
uchar *tscan = image.scanLine(y);
int bytesPerLine = image.bytesPerLine();
for (int i = 0; i < bytesPerLine; ++i)
tscan[i] &= mscan[i];
}
break;
}
default: {
const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
for (int y = 0; y < h; ++y) {
const uchar *mscan = imageMask.scanLine(y);
QRgb *tscan = (QRgb *)image.scanLine(y);
for (int x = 0; x < w; ++x) {
if (!(mscan[x>>3] & (1 << (x&7))))
tscan[x] = 0;
}
}
break;
}
}
}
fromImage(image, Qt::AutoColor);
}
QPixmap QPlatformPixmap::transformed(const QTransform &matrix,
Qt::TransformationMode mode) const
{

View File

@ -99,6 +99,9 @@ public:
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
virtual QBitmap mask() const;
virtual void setMask(const QBitmap &mask);
virtual bool hasAlphaChannel() const = 0;
virtual QPixmap transformed(const QTransform &matrix,
Qt::TransformationMode mode) const;