Esempio n. 1
0
quint8 KisPressureRateOption::apply( quint8 opacity, qint32 sw,  qint32 sh, KisPaintDeviceSP srcdev, double pressure) const
{
    opacity = rate();

    if (isChecked()) {
        if (customCurve()) {
            opacity = qBound((qint32)OPACITY_TRANSPARENT, 
                             (qint32)(double(opacity) * scaleToCurve(pressure) / PRESSURE_DEFAULT),
                             (qint32)OPACITY_OPAQUE);

        } else {
            opacity = qBound((qint32)OPACITY_TRANSPARENT,
                             (qint32)(double(opacity) * pressure / PRESSURE_DEFAULT),
                             (qint32)OPACITY_OPAQUE);
        }
    }

#if 0
    // TODO It's also applied in the smudgeop, do other paintops that require a rate
    // needs to do this to their srcDev ?
    KisRectIterator it = srcdev->createRectIterator(0, 0, sw, sh);
    KoColorSpace* cs = srcdev->colorSpace();

    while (not it.isDone()) {
        cs->setAlpha(it.rawData(), (cs->alpha(it.rawData()) * opacity) / OPACITY_OPAQUE, 1);
        ++it;
    }
    return OPACITY_OPAQUE - opacity;
#else
    return opacity;
#endif


}
Esempio n. 2
0
void KisPixelSelection::invert()
{
    // Extent is needed here (not exactBounds), because unselected but existing pixel
    // need to be inverted too
    QRect rc = extent();

    KisRectIterator it = createRectIterator(rc.x(), rc.y(), rc.width(), rc.height());
    while (! it.isDone()) {
        *(it.rawData()) = MAX_SELECTED - *(it.rawData());
        ++it;
    }
    quint8 defPixel = MAX_SELECTED - *(m_datamanager->defaultPixel());
    m_datamanager->setDefaultPixel(&defPixel);
}
Esempio n. 3
0
void KisBidirectionalMixingOption::apply(KisPaintDeviceSP dab, KisPaintDeviceSP device, KisPainter* painter, qint32 sx, qint32 sy, qint32 sw, qint32 sh, quint8 pressure, const QRect& dstRect)
{
    if (!isChecked()) return;

    KoColorSpace *cs = dab->colorSpace();
    KisPaintDeviceSP canvas = new KisPaintDevice(cs);
    KisPainter p(canvas);
    p.setCompositeOp(COMPOSITE_COPY);
    p.bitBlt(sx, sy, device, dstRect.x(), dstRect.y(), sw, sh);

    int count = cs->channelCount();
    KisRectIterator cit = canvas->createRectIterator(sx, sy, sw, sh);
    KisRectIterator dit = dab->createRectIterator(sx, sy, sw, sh);
    QVector<float> cc(count), dc(count);
    while (!cit.isDone()) {
        if (cs->alpha(dit.rawData()) > 10 && cs->alpha(cit.rawData()) > 10) {
            cs->normalisedChannelsValue(cit.rawData(), cc);
            cs->normalisedChannelsValue(dit.rawData(), dc);
            for (int i = 0; i < count; i++)
                dc[i] = (1.0 - 0.4 * pressure) * cc[i] + 0.4 * pressure * dc[i];
            cs->fromNormalisedChannelsValue(dit.rawData(), dc);
            if (dit.x() == (int)(sw / 2) && dit.y() == (int)(sh / 2))
                painter->setPaintColor(KoColor(dit.rawData(), cs));
        }
        ++cit;
        ++dit;
    }
}
Esempio n. 4
0
void KisSmudgeOp::paintAt(const KisPaintInformation& info)
{
    if (!painter()->device()) return;

    KisBrushSP brush = m_brush;

    Q_ASSERT(brush);
    if (!brush) return;

    KisPaintInformation adjustedInfo = settings->m_optionsWidget->m_sizeOption->apply(info);
    if (! brush->canPaintFor(adjustedInfo))
        return;

    KisPaintDeviceSP device = painter()->device();
    double pScale = KisPaintOp::scaleForPressure(adjustedInfo.pressure());
    QPointF hotSpot = brush->hotSpot(pScale, pScale);
    QPointF pt = info.pos() - hotSpot;

    // Split the coordinates into integer plus fractional parts. The integer
    // is where the dab will be positioned and the fractional part determines
    // the sub-pixel positioning.
    qint32 x;
    double xFraction;
    qint32 y;
    double yFraction;

    splitCoordinate(pt.x(), &x, &xFraction);
    splitCoordinate(pt.y(), &y, &yFraction);

    KisFixedPaintDeviceSP dab = 0;

    double scale = KisPaintOp::scaleForPressure(adjustedInfo.pressure());

    QRect dabRect = QRect(0, 0, brush->maskWidth(scale, 0.0), brush->maskHeight(scale, 0.0));
    QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height());
    if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;

    if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
        dab = brush->image(device->colorSpace(), pScale, 0.0, adjustedInfo, xFraction, yFraction);
        dab->convertTo(KoColorSpaceRegistry::instance()->alpha8());
    } else {
        dab = cachedDab();
        KoColor color = painter()->paintColor();
        dab->convertTo(KoColorSpaceRegistry::instance()->alpha8());
        brush->mask(dab, color, scale, pScale, 0.0, info, xFraction, yFraction);
    }

    qint32 sw = dab->bounds().width();
    qint32 sh = dab->bounds().height();

    /* To smudge, one does the following:
         * at first, initialize a temporary paint device with a copy of the original (dab-sized piece, really).
         * all other times:
             reduce the transparency of the temporary paint device so as to let it mix gradually
         * combine the temp device with the piece the brush currently is 'painting', according to a mix (opacity)
             note that in the first step, this does the actual copying of the data
         * this combination is then composited upon the actual image
       TODO: what happened exactly in 1.6 (and should happen now) when the dab resizes halfway due to pressure?
    */
    int opacity = OPACITY_OPAQUE;
    if (!m_firstRun) {
        opacity = settings->m_optionsWidget->m_rateOption->apply( opacity, sw, sh, m_srcdev, info.pressure() );

        KisRectIterator it = m_srcdev->createRectIterator(0, 0, sw, sh);
        KoColorSpace* cs = m_srcdev->colorSpace();
        while(!it.isDone()) {
            cs->setAlpha(it.rawData(), (cs->alpha(it.rawData()) * opacity) / OPACITY_OPAQUE, 1);
            ++it;
        }

        opacity = OPACITY_OPAQUE - opacity;
    } else {
        m_firstRun = false;
    }

    KisPainter copyPainter(m_srcdev);
    copyPainter.setOpacity(opacity);
    copyPainter.bitBlt(0, 0, device, pt.x(), pt.y(), sw, sh);
    copyPainter.end();

    m_target = new KisPaintDevice(device->colorSpace());

    // Looks hacky, but we lost bltMask, or the ability to easily convert alpha8 paintdev to selection?
    KisSelectionSP dabAsSelection = new KisSelection();
    copyPainter.begin(dabAsSelection);
    copyPainter.setOpacity(OPACITY_OPAQUE);
    copyPainter.setCompositeOp(COMPOSITE_COPY);
    copyPainter.bltFixed(0, 0, dab, 0, 0, sw, sh);
    copyPainter.end();

    copyPainter.begin(m_target);
    copyPainter.setCompositeOp(COMPOSITE_OVER);
    copyPainter.setSelection(dabAsSelection);
    copyPainter.bitBlt(0, 0, m_srcdev, 0, 0, sw, sh);
    copyPainter.end();

    qint32 sx = dstRect.x() - x;
    qint32 sy = dstRect.y() - y;
    sw = dstRect.width();
    sh = dstRect.height();

    painter()->bitBlt(dstRect.x(), dstRect.y(), m_target, sx, sy, sw, sh);

}