diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-02-11 11:13:03 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-04-10 09:15:59 +0000 |
commit | 60e8519544b9194d4a44db61fb5b0b10572282cc (patch) | |
tree | 46fcacacf6c81725ebeb5a9a543783e4bb03d409 /src/gui/painting/qpaintengine_raster.cpp | |
parent | 853cba729bc2bbac254ee36be6d42241eb92fd21 (diff) |
Solid and gradients in high color accuracy
This patch updates the internal color precisions of solids and
gradients to 16bit per color. This makes it possible to render
at higher precision on non-premultiplied ARGB32, the RGB30
formats and any other hi-color formats if more are added.
[ChangeLog][QtGui][Painting] Internal precision of solids and gradients
is now up to 16bit per color.
Change-Id: Ieae5468bd6de1f56adfa4cb9fa966faf2ed824fd
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Diffstat (limited to 'src/gui/painting/qpaintengine_raster.cpp')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 101 |
1 files changed, 48 insertions, 53 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 18522cb6d0..3be6e0f1f4 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -57,6 +57,7 @@ #include <private/qstatictext_p.h> #include <private/qcosmeticstroker_p.h> #include "qmemrotate_p.h" +#include "qrgba64_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -830,7 +831,7 @@ void QRasterPaintEngine::updateRasterState() && s->intOpacity == 256 && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(s->penData.solid.color) == 255)); + && s->penData.solid.color.isOpaque())); } s->dirty = 0; @@ -1412,10 +1413,9 @@ static void fillRect_normalized(const QRect &r, QSpanData *data, if (data->fillRect && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(data->solid.color) == 255))) + && data->solid.color.isOpaque()))) { - data->fillRect(data->rasterBuffer, x1, y1, width, height, - data->solid.color); + data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solid.color); return; } } @@ -1773,8 +1773,9 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity)); + + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) { return; } @@ -2219,19 +2220,15 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe case QImage::Format_A2BGR30_Premultiplied: case QImage::Format_A2RGB30_Premultiplied: // Combine premultiplied color with the opacity set on the painter. - d->solid_color_filler.solid.color = - ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) - | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); + d->solid_color_filler.solid.color = multiplyAlpha256(QRgba64::fromArgb32(color), s->intOpacity); break; default: - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(QRgba64::fromArgb32(color), s->intOpacity)); break; } - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 - && s->composition_mode == QPainter::CompositionMode_SourceOver) { + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) return; - } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); @@ -4137,7 +4134,7 @@ class QGradientCache { inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) : stops(s), opacity(op), interpolationMode(mode) {} - uint buffer[GRADIENT_STOPTABLE_SIZE]; + QRgba64 buffer[GRADIENT_STOPTABLE_SIZE]; QGradientStops stops; int opacity; QGradient::InterpolationMode interpolationMode; @@ -4146,12 +4143,12 @@ class QGradientCache typedef QMultiHash<quint64, CacheInfo> QGradientColorTableHash; public: - inline const uint *getBuffer(const QGradient &gradient, int opacity) { + inline const QRgba64 *getBuffer(const QGradient &gradient, int opacity) { quint64 hash_val = 0; QGradientStops stops = gradient.stops(); for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); + hash_val += stops[i].second.rgba64(); QMutexLocker lock(&mutex); QGradientColorTableHash::const_iterator it = cache.constFind(hash_val); @@ -4174,9 +4171,9 @@ public: protected: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& g, - uint *colorTable, + QRgba64 *colorTable, int size, int opacity) const; - uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { + QRgba64 *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK cache.erase(cache.begin() + (qrand() % maxCacheSize())); @@ -4190,7 +4187,7 @@ protected: QMutex mutex; }; -void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, int opacity) const +void QGradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, int opacity) const { QGradientStops stops = gradient.stops(); int stopCount = stops.count(); @@ -4199,14 +4196,16 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); if (stopCount == 2) { - uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); - uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity); + QRgba64 first_color = combineAlpha256(stops[0].second.rgba64(), opacity); + QRgba64 second_color = combineAlpha256(stops[1].second.rgba64(), opacity); qreal first_stop = stops[0].first; qreal second_stop = stops[1].first; if (second_stop < first_stop) { - qSwap(first_color, second_color); + quint64 tmp = first_color; + first_color = second_color; + second_color = tmp; qSwap(first_stop, second_stop); } @@ -4218,15 +4217,15 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1)); int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1)); - uint red_first = qRed(first_color) << 16; - uint green_first = qGreen(first_color) << 16; - uint blue_first = qBlue(first_color) << 16; - uint alpha_first = qAlpha(first_color) << 16; + uint red_first = uint(first_color.red()) << 16; + uint green_first = uint(first_color.green()) << 16; + uint blue_first = uint(first_color.blue()) << 16; + uint alpha_first = uint(first_color.alpha()) << 16; - uint red_second = qRed(second_color) << 16; - uint green_second = qGreen(second_color) << 16; - uint blue_second = qBlue(second_color) << 16; - uint alpha_second = qAlpha(second_color) << 16; + uint red_second = uint(second_color.red()) << 16; + uint green_second = uint(second_color.green()) << 16; + uint blue_second = uint(second_color.blue()) << 16; + uint alpha_second = uint(second_color.alpha()) << 16; int i = 0; for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) { @@ -4239,10 +4238,10 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (i < second_index) { qreal reciprocal = qreal(1) / (second_index - first_index); - int red_delta = qRound(int(red_second - red_first) * reciprocal); - int green_delta = qRound(int(green_second - green_first) * reciprocal); - int blue_delta = qRound(int(blue_second - blue_first) * reciprocal); - int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal); + int red_delta = qRound((qreal(red_second) - red_first) * reciprocal); + int green_delta = qRound((qreal(green_second) - green_first) * reciprocal); + int blue_delta = qRound((qreal(blue_second) - blue_first) * reciprocal); + int alpha_delta = qRound((qreal(alpha_second) - alpha_first) * reciprocal); // rounding red_first += 1 << 15; @@ -4256,8 +4255,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint blue_first += blue_delta; alpha_first += alpha_delta; - const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000) - | ((green_first >> 8) & 0xff00) | (blue_first >> 16); + const QRgba64 color = qRgba64(red_first >> 16, green_first >> 16, blue_first >> 16, alpha_first >> 16); if (colorInterpolation) colorTable[i] = color; @@ -4276,7 +4274,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint return; } - uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); + QRgba64 current_color = combineAlpha256(stops[0].second.rgba64(), opacity); if (stopCount == 1) { current_color = qPremultiply(current_color); for (int i = 0; i < size; ++i) @@ -4289,7 +4287,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint qreal end_pos = stops[stopCount-1].first; int pos = 0; // The position in the color table. - uint next_color; + QRgba64 next_color; qreal incr = 1 / qreal(size); // the double increment. qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1) @@ -4313,8 +4311,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint ++current_stop; if (current_stop != 0) - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { current_color = qPremultiply(current_color); @@ -4333,9 +4331,9 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int idist = 256 - dist; if (colorInterpolation) - colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); + colorTable[pos] = interpolate256(current_color, idist, next_color, dist); else - colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); ++pos; dpos += incr; @@ -4354,8 +4352,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (skip == 1) current_color = next_color; else - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { if (skip != 1) @@ -4372,7 +4370,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint } // After last point - current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); + current_color = qPremultiply(combineAlpha256(stops[stopCount - 1].second.rgba64(), opacity)); while (pos < size - 1) { colorTable[pos] = current_color; ++pos; @@ -4405,12 +4403,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode case Qt::SolidPattern: { type = Solid; QColor c = qbrush_color(brush); - QRgb rgba = c.rgba(); - solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha)); - if ((solid.color & 0xff000000) == 0 - && compositionMode == QPainter::CompositionMode_SourceOver) { + solid.color = qPremultiply(combineAlpha256(c.rgba64(), alpha)); + if (solid.color.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver) type = None; - } break; } @@ -4419,7 +4414,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = LinearGradient; const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QLinearGradientData &linearData = gradient.linear; @@ -4436,7 +4431,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = RadialGradient; const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QRadialGradientData &radialData = gradient.radial; @@ -4457,7 +4452,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = ConicalGradient; const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = QGradient::RepeatSpread; QConicalGradientData &conicalData = gradient.conical; |