//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;
}
    void saveGradientStops(QTextStream &str, const QGradient *g) {
        QGradientStops stops = g->stops();

        if (g->interpolationMode() == QGradient::ColorInterpolation) {
            bool constantAlpha = true;
            int alpha = stops.at(0).second.alpha();
            for (int i = 1; i < stops.size(); ++i)
                constantAlpha &= (stops.at(i).second.alpha() == alpha);

            if (!constantAlpha) {
                const qreal spacing = qreal(0.02);
                QGradientStops newStops;
                QRgb fromColor = PREMUL(stops.at(0).second.rgba());
                QRgb toColor;
                for (int i = 0; i + 1 < stops.size(); ++i) {
                    int parts = qCeil((stops.at(i + 1).first - stops.at(i).first) / spacing);
                    newStops.append(stops.at(i));
                    toColor = PREMUL(stops.at(i + 1).second.rgba());

                    if (parts > 1) {
                        qreal step = (stops.at(i + 1).first - stops.at(i).first) / parts;
                        for (int j = 1; j < parts; ++j) {
                            QRgb color = INV_PREMUL(INTERPOLATE_PIXEL_256(fromColor, 256 - 256 * j / parts, toColor, 256 * j / parts));
                            newStops.append(QGradientStop(stops.at(i).first + j * step, QColor::fromRgba(color)));
                        }
                    }
                    fromColor = toColor;
                }
                newStops.append(stops.back());
                stops = newStops;
            }
        }

        foreach(QGradientStop stop, stops) {
            QString color =
                QString::fromLatin1("#%1%2%3")
                .arg(stop.second.red(), 2, 16, QLatin1Char('0'))
                .arg(stop.second.green(), 2, 16, QLatin1Char('0'))
                .arg(stop.second.blue(), 2, 16, QLatin1Char('0'));
            str << QLatin1String("    <stop offset=\"")<< stop.first << QLatin1String("\" ")
                << QLatin1String("stop-color=\"") << color << QLatin1String("\" ")
                << QLatin1String("stop-opacity=\"") << stop.second.alphaF() <<QLatin1String("\" />\n");
        }
Esempio n. 3
0
void QCosmeticStroker::setup()
{
    blend = state->penData.blend;
    if (state->clip && state->clip->enabled && state->clip->hasRectClip && !state->clip->clipRect.isEmpty()) {
        clip &= state->clip->clipRect;
        blend = state->penData.unclipped_blend;
    }

    int strokeSelection = 0;
    if (blend == state->penData.unclipped_blend
        && state->penData.type == QSpanData::Solid
        && (state->penData.rasterBuffer->format == QImage::Format_ARGB32_Premultiplied
            || state->penData.rasterBuffer->format == QImage::Format_RGB32)
        && state->compositionMode() == QPainter::CompositionMode_SourceOver)
        strokeSelection |= FastDraw;

    if (state->renderHints & QPainter::Antialiasing)
        strokeSelection |= AntiAliased;

    const QVector<qreal> &penPattern = state->lastPen.dashPattern();
    if (penPattern.isEmpty()) {
        Q_ASSERT(!pattern && !reversePattern);
        pattern = 0;
        reversePattern = 0;
        patternLength = 0;
        patternSize = 0;
    } else {
        pattern = (int *)malloc(penPattern.size()*sizeof(int));
        reversePattern = (int *)malloc(penPattern.size()*sizeof(int));
        patternSize = penPattern.size();

        patternLength = 0;
        for (int i = 0; i < patternSize; ++i) {
            patternLength += (int) qMax(1. , penPattern.at(i)*64.);
            pattern[i] = patternLength;
        }
        patternLength = 0;
        for (int i = 0; i < patternSize; ++i) {
            patternLength += (int) qMax(1., penPattern.at(patternSize - 1 - i)*64.);
            reversePattern[i] = patternLength;
        }
        strokeSelection |= Dashed;
//        qDebug() << "setup: size=" << patternSize << "length=" << patternLength/64.;
    }

    stroke = strokeLine(strokeSelection);

    qreal width = state->lastPen.widthF();
    if (width == 0)
        opacity = 256;
    else if (state->lastPen.isCosmetic())
        opacity = (int) 256*width;
    else
        opacity = (int) 256*width*state->txscale;
    opacity = qBound(0, opacity, 256);

    drawCaps = state->lastPen.capStyle() != Qt::FlatCap;

    if (strokeSelection & FastDraw) {
        color = INTERPOLATE_PIXEL_256(state->penData.solid.color, opacity, 0, 0);
        QRasterBuffer *buffer = state->penData.rasterBuffer;
        pixels = (uint *)buffer->buffer();
        ppl = buffer->bytesPerLine()>>2;
    }