//TODO: Let GL generate the texture using an FBO void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const { int pos = 0; QGradientStops s = gradient.stops(); QVector<uint> colors(s.size()); for (int i = 0; i < s.size(); ++i) colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian) bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); uint alpha = qRound(opacity * 256); uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); while (fpos <= s.first().first) { colorTable[pos] = colorTable[pos - 1]; pos++; fpos += incr; } if (colorInterpolation) current_color = qPremultiply(current_color); for (int i = 0; i < s.size() - 1; ++i) { qreal delta = 1/(s[i+1].first - s[i].first); uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); if (colorInterpolation) next_color = qPremultiply(next_color); while (fpos < s[i+1].first && pos < size) { int dist = int(256 * ((fpos - s[i].first) * delta)); int idist = 256 - dist; if (colorInterpolation) colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); else colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); ++pos; fpos += incr; } current_color = next_color; } Q_ASSERT(s.size() > 0); uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); for (;pos < size; ++pos) colorTable[pos] = last_color; // Make sure the last color stop is represented at the end of the table colorTable[size-1] = last_color; }
QColor KarbonGradientHelper::colorAt(qreal position, const QGradientStops &stops) { if (! stops.count()) return QColor(); if (stops.count() == 1) return stops.first().second; QGradientStop prevStop(-1.0, QColor()); QGradientStop nextStop(2.0, QColor()); // find framing gradient stops foreach(const QGradientStop & stop, stops) { if (stop.first > prevStop.first && stop.first < position) prevStop = stop; if (stop.first < nextStop.first && stop.first > position) nextStop = stop; } QColor theColor; if (prevStop.first < 0.0) { // new stop is before the first stop theColor = nextStop.second; } else if (nextStop.first > 1.0) { // new stop is after the last stop theColor = prevStop.second; } else { // linear interpolate colors between framing stops QColor prevColor = prevStop.second, nextColor = nextStop.second; qreal colorScale = (position - prevStop.first) / (nextStop.first - prevStop.first); theColor.setRedF(prevColor.redF() + colorScale *(nextColor.redF() - prevColor.redF())); theColor.setGreenF(prevColor.greenF() + colorScale *(nextColor.greenF() - prevColor.greenF())); theColor.setBlueF(prevColor.blueF() + colorScale *(nextColor.blueF() - prevColor.blueF())); theColor.setAlphaF(prevColor.alphaF() + colorScale *(nextColor.alphaF() - prevColor.alphaF())); } return theColor; }