Пример #1
0
void HairyBrush::fromDabWithDensity(KisFixedPaintDeviceSP dab, qreal density)
{
    int width = dab->bounds().width();
    int height = dab->bounds().height(); 

    int centerX = width * 0.5;
    int centerY = height * 0.5;
   
    // make mask 
    Bristle * bristle = 0;
    qreal alpha;
    
    quint8 * dabPointer = dab->data();
    quint8 pixelSize = dab->pixelSize();
    const KoColorSpace * cs = dab->colorSpace();
    KoColor bristleColor(cs);
    
    srand48(12345678);
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            alpha =  cs->opacityF(dabPointer);
            if (alpha != 0.0){
                if (density == 1.0 || drand48() <= density){
                    memcpy(bristleColor.data(), dabPointer, pixelSize);
                
                    bristle = new Bristle(x - centerX, y - centerY, alpha); // using value from image as length of bristle    
                    bristle->setColor(bristleColor);
                
                    m_bristles.append(bristle);
                }
            } 
            dabPointer += pixelSize;
        }
    }
}
Пример #2
0
void HairyBrush::colorifyBristles(KisPaintDeviceSP source, QPointF point)
{
    KoColor bristleColor(m_dab->colorSpace());
    KisCrossDeviceColorPickerInt colorPicker(source, bristleColor);

    Bristle *b = 0;
    int size = m_bristles.size();
    for (int i = 0; i < size; i++) {
        b = m_bristles[i];
        int x = qRound(b->x() + point.x());
        int y = qRound(b->y() + point.y());

        colorPicker.pickOldColor(x, y, bristleColor.data());
        b->setColor(bristleColor);
    }

}
Пример #3
0
void HairyBrush::paintLine(KisPaintDeviceSP dab, KisPaintDeviceSP layer, const KisPaintInformation &pi1, const KisPaintInformation &pi2, qreal scale, qreal rotation)
{
    m_counter++;

    qreal x1 = pi1.pos().x();
    qreal y1 = pi1.pos().y();

    qreal x2 = pi2.pos().x();
    qreal y2 = pi2.pos().y();

    qreal dx = x2 - x1;
    qreal dy = y2 - y1;

    // TODO:this angle is different from the drawing angle in sensor (info.angle()). The bug is caused probably due to
    // not computing the drag vector properly in paintBezierLine when smoothing is used
    //qreal angle = atan2(dy, dx);
    qreal angle = rotation;

    qreal mousePressure = 1.0;
    if (m_properties->useMousePressure) { // want pressure from mouse movement
        qreal distance = sqrt(dx * dx + dy * dy);
        mousePressure = (1.0 - computeMousePressure(distance));
        scale *= mousePressure;
    }
    // this pressure controls shear and ink depletion
    qreal pressure = mousePressure * (pi2.pressure() * 2);

    Bristle *bristle = 0;
    KoColor bristleColor(dab->colorSpace());

    m_dabAccessor = dab->createRandomAccessorNG((int)x1, (int)y1);

    m_dab = dab;

    // initialization block
    if (firstStroke()) {
        initAndCache();
    }

    // if this is first time the brush touches the canvas and we use soak the ink from canvas
    if (firstStroke() && m_properties->useSoakInk) {
        if (layer) {
            colorifyBristles(layer, pi1.pos());
        }
        else {
            dbgKrita << "Can't soak the ink from the layer";
        }
    }

    KisRandomSourceSP randomSource = pi2.randomSource();

    qreal fx1, fy1, fx2, fy2;
    qreal randomX, randomY;
    qreal shear;

    float inkDeplation = 0.0;
    int inkDepletionSize = m_properties->inkDepletionCurve.size();
    int bristleCount = m_bristles.size();
    int bristlePathSize;
    qreal treshold = 1.0 - pi2.pressure();
    for (int i = 0; i < bristleCount; i++) {

        if (!m_bristles.at(i)->enabled()) continue;
        bristle = m_bristles[i];

        randomX = (randomSource->generateNormalized() * 2 - 1.0) * m_properties->randomFactor;
        randomY = (randomSource->generateNormalized() * 2 - 1.0) * m_properties->randomFactor;

        shear = pressure * m_properties->shearFactor;

        m_transform.reset();
        m_transform.rotateRadians(-angle);
        m_transform.scale(scale, scale);
        m_transform.translate(randomX, randomY);
        m_transform.shear(shear, shear);

        if (firstStroke() || (!m_properties->connectedPath)) {
            // transform start dab
            m_transform.map(bristle->x(), bristle->y(), &fx1, &fy1);
            // transform end dab
            m_transform.map(bristle->x(), bristle->y(), &fx2, &fy2);
        }
        else {
            // continue the path of the bristle from the previous position
            fx1 = bristle->prevX();
            fy1 = bristle->prevY();
            m_transform.map(bristle->x(), bristle->y(), &fx2, &fy2);
        }
        // remember the end point
        bristle->setPrevX(fx2);
        bristle->setPrevY(fy2);

        // all coords relative to device position
        fx1 += x1;
        fy1 += y1;

        fx2 += x2;
        fy2 += y2;

        if (m_properties->threshold && (bristle->length() < treshold)) continue;
        // paint between first and last dab
        const QVector<QPointF> bristlePath = m_trajectory.getLinearTrajectory(QPointF(fx1, fy1), QPointF(fx2, fy2), 1.0);
        bristlePathSize = m_trajectory.size();

        memcpy(bristleColor.data(), bristle->color().data() , m_pixelSize);
        for (int i = 0; i < bristlePathSize ; i++) {

            if (m_properties->inkDepletionEnabled) {
                inkDeplation = fetchInkDepletion(bristle, inkDepletionSize);

                if (m_properties->useSaturation && m_transfo != 0) {
                    saturationDepletion(bristle, bristleColor, pressure, inkDeplation);
                }

                if (m_properties->useOpacity) {
                    opacityDepletion(bristle, bristleColor, pressure, inkDeplation);
                }

            }
            else {
                if (bristleColor.opacityU8() != 0) {
                    bristleColor.setOpacity(bristle->length());
                }
            }

            addBristleInk(bristle, bristlePath.at(i), bristleColor);
            bristle->setInkAmount(1.0 - inkDeplation);
            bristle->upIncrement();
        }

    }
    m_dab = 0;
    m_dabAccessor = 0;
}