void KisFilterRandomPick::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; double windowsize = (config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5; int seedThreshold = rand(); int seedH = rand(); int seedV = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedH = config->getInt("seedH", seedH); seedV = config->getInt("seedV", seedV); } KisRandomGenerator randT(seedThreshold); KisRandomGenerator randH(seedH); KisRandomGenerator randV(seedV); KisSequentialIterator dstIt(device, applyRect); KisRandomConstAccessorSP srcRA = device->createRandomConstAccessorNG(0, 0); double threshold = (100 - level) / 100.0; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; KoMixColorsOp * mixOp = cs->mixColorsOp(); do{ if (randT.doubleRandomAt(dstIt.x(), dstIt.y()) > threshold) { int x = static_cast<int>(dstIt.x() + windowsize * (randH.doubleRandomAt(dstIt.x(), dstIt.y()) - 0.5)); int y = static_cast<int>(dstIt.y() + windowsize * (randV.doubleRandomAt(dstIt.x(), dstIt.y()) -0.5)); srcRA->moveTo(x, y); pixels[0] = srcRA->oldRawData(); pixels[1] = dstIt.oldRawData(); mixOp->mixColors(pixels, weights, 2, dstIt.rawData()); } if (progressUpdater) progressUpdater->setValue(++count); } while(dstIt.nextPixel()); }
KoColor KoColorSlider::currentColor() const { const quint8 *colors[2]; colors[0] = d->minColor.data(); colors[1] = d->maxColor.data(); KoMixColorsOp * mixOp = d->minColor.colorSpace()->mixColorsOp(); KoColor c(d->minColor.colorSpace()); qint16 weights[2]; weights[1] = (value() - minimum()) / qreal(maximum() - minimum()) * 255; weights[0] = 255 - weights[1]; mixOp->mixColors(colors, weights, 2, c.data()); return c; }
KisPaintDeviceSP KisShearVisitor::yShear(KisPaintDeviceSP src, qreal shearY, KoUpdater *progress) { int start = progress->progress(); KisPaintDeviceSP dst = KisPaintDeviceSP(new KisPaintDevice(src->colorSpace())); KoMixColorsOp * mixOp = src->colorSpace()->mixColorsOp(); dst->setX(src->x()); dst->setY(src->y()); QRect r = src->exactBounds(); qreal displacement; qint32 displacementInt; qreal weight; for (qint32 x = r.left(); x <= r.right(); x++) { //calculate displacement displacement = x * shearY; displacementInt = (qint32)(floor(displacement)); weight = displacement - displacementInt; qint16 pixelWeights[2]; pixelWeights[0] = static_cast<quint8>(weight * 255 + 0.5); pixelWeights[1] = 255 - pixelWeights[0]; KisVLineConstIteratorPixel srcIt = src->createVLineIterator(x, r.y(), r.height() + 1); KisVLineIteratorPixel leftSrcIt = src->createVLineIterator(x, r.y() - 1, r.height() + 1); KisVLineIteratorPixel dstIt = dst->createVLineIterator(x, r.y() + displacementInt, r.height() + 1); while (!srcIt.isDone()) { const quint8 *pixelPtrs[2]; pixelPtrs[0] = leftSrcIt.rawData(); pixelPtrs[1] = srcIt.rawData(); mixOp->mixColors(pixelPtrs, pixelWeights, 2, dstIt.rawData()); ++srcIt; ++leftSrcIt; ++dstIt; } progress->setProgress(start + x); } return dst; }
KisPaintDeviceSP KisShearVisitor::xShear(KisPaintDeviceSP src, qreal shearX, KoUpdater *progress) { KisPaintDeviceSP dst = KisPaintDeviceSP(new KisPaintDevice(src->colorSpace())); dst->setX(src->x()); dst->setY(src->y()); QRect r = src->exactBounds(); qreal displacement; qint32 displacementInt; qreal weight; KoMixColorsOp * mixOp = src->colorSpace()->mixColorsOp(); for (qint32 y = r.top(); y <= r.bottom(); y++) { //calculate displacement displacement = -y * shearX; displacementInt = (qint32)(floor(displacement)); weight = displacement - displacementInt; qint16 pixelWeights[2]; pixelWeights[0] = static_cast<quint8>(weight * 255 + 0.5); pixelWeights[1] = 255 - pixelWeights[0]; KisHLineConstIteratorPixel srcIt = src->createHLineIterator(r.x(), y, r.width() + 1); KisHLineConstIteratorPixel leftSrcIt = src->createHLineIterator(r.x() - 1, y, r.width() + 1); KisHLineIteratorPixel dstIt = dst->createHLineIterator(r.x() + displacementInt, y, r.width() + 1); while (!srcIt.isDone()) { const quint8 *pixelPtrs[2]; pixelPtrs[0] = leftSrcIt.rawData(); pixelPtrs[1] = srcIt.rawData(); mixOp->mixColors(pixelPtrs, pixelWeights, 2, dstIt.rawData()); ++srcIt; ++leftSrcIt; ++dstIt; } progress->setProgress(y); } return dst; }
void KoRgbU8ColorSpaceTester::testMixColorsAverage() { const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); KoMixColorsOp * mixOp = cs->mixColorsOp(); // Test mixColors. quint8 pixel1[4]; quint8 pixel2[4]; quint8 outputPixel[4]; pixel1[PIXEL_RED] = 255; pixel1[PIXEL_GREEN] = 255; pixel1[PIXEL_BLUE] = 255; pixel1[PIXEL_ALPHA] = 255; pixel2[PIXEL_RED] = 0; pixel2[PIXEL_GREEN] = 0; pixel2[PIXEL_BLUE] = 0; pixel2[PIXEL_ALPHA] = 0; const quint8 *pixelPtrs[2]; pixelPtrs[0] = pixel1; pixelPtrs[1] = pixel2; mixOp->mixColors(pixelPtrs, 2, outputPixel); QCOMPARE((int)outputPixel[PIXEL_RED], 255); QCOMPARE((int)outputPixel[PIXEL_GREEN], 255); QCOMPARE((int)outputPixel[PIXEL_BLUE], 255); QCOMPARE((int)outputPixel[PIXEL_ALPHA], 127); pixel2[PIXEL_ALPHA] = 255; mixOp->mixColors(pixelPtrs, 2, outputPixel); QCOMPARE((int)outputPixel[PIXEL_RED], 127); QCOMPARE((int)outputPixel[PIXEL_GREEN], 127); QCOMPARE((int)outputPixel[PIXEL_BLUE], 127); QCOMPARE((int)outputPixel[PIXEL_ALPHA], 255); }
void KoXYColorSelector::drawContents( QPainter *painter ) { KoColor c = m_colors[0]; // quick way to set the colorspace QColor color; const quint8 *colors[4]; colors[0] = m_colors[0].data(); colors[1] = m_colors[1].data(); colors[2] = m_colors[2].data(); colors[3] = m_colors[3].data(); QRect contentsRect_(contentsRect()); QImage image(contentsRect_.width(), contentsRect_.height(), QImage::Format_ARGB32 ); KoMixColorsOp * mixOp = m_colorSpace->mixColorsOp(); for (int x = 0; x < contentsRect_.width(); x++) for (int y = 0; y < contentsRect_.height(); y++){ qreal xVal = static_cast<qreal>(x) / (contentsRect_.width() - 1); qreal yVal = static_cast<qreal>(y) / (contentsRect_.height() - 1); qint16 colorWeights[4]; colorWeights[0] = static_cast<quint8>((1.0 - yVal) * (1.0 - xVal) * 255 + 0.5); colorWeights[1] = static_cast<quint8>((1.0 - yVal) * (xVal) * 255 + 0.5); colorWeights[2] = static_cast<quint8>((yVal) * (1.0 - xVal) * 255 + 0.5); colorWeights[3] = static_cast<quint8>((yVal) * (xVal) * 255 + 0.5); mixOp->mixColors(colors, colorWeights, 4, c.data()); c.toQColor( &color); image.setPixel(x, y, color.rgba()); } painter->drawImage( contentsRect_, image, QRect( 0, 0, image.width(), image.height()) ); }
void SprayBrush::paint(KisPaintDeviceSP dab, KisPaintDeviceSP source, const KisPaintInformation& info, qreal rotation, qreal scale, const KoColor &color, const KoColor &bgColor) { // initializing painter if (!m_painter) { m_painter = new KisPainter(dab); m_painter->setFillStyle(KisPainter::FillStyleForegroundColor); m_painter->setMaskImageSize(m_shapeProperties->width, m_shapeProperties->height); m_dabPixelSize = dab->colorSpace()->pixelSize(); if (m_colorProperties->useRandomHSV) { m_transfo = dab->colorSpace()->createColorTransformation("hsv_adjustment", QHash<QString, QVariant>()); } m_brushQImage = m_shapeProperties->image; if (!m_brushQImage.isNull()) { m_brushQImage = m_brushQImage.scaled(m_shapeProperties->width, m_shapeProperties->height); } m_imageDevice = new KisPaintDevice(dab->colorSpace()); } qreal x = info.pos().x(); qreal y = info.pos().y(); KisRandomAccessorSP accessor = dab->createRandomAccessorNG(qRound(x), qRound(y)); Q_ASSERT(color.colorSpace()->pixelSize() == dab->pixelSize()); m_inkColor = color; KisCrossDeviceColorPicker colorPicker(source, m_inkColor); // apply size sensor m_radius = m_properties->radius * scale; // jitter movement if (m_properties->jitterMovement) { x = x + ((2 * m_radius * drand48()) - m_radius) * m_properties->amount; y = y + ((2 * m_radius * drand48()) - m_radius) * m_properties->amount; } // this is wrong for every shape except pixel and anti-aliased pixel if (m_properties->useDensity) { m_particlesCount = (m_properties->coverage * (M_PI * m_radius * m_radius)); } else { m_particlesCount = m_properties->particleCount; } QHash<QString, QVariant> params; qreal nx, ny; int ix, iy; qreal angle; qreal length; qreal rotationZ = 0.0; qreal particleScale = 1.0; bool shouldColor = true; if (m_colorProperties->fillBackground) { m_painter->setPaintColor(bgColor); paintCircle(m_painter, x, y, m_radius); } QTransform m; m.reset(); m.rotateRadians(-rotation + deg2rad(m_properties->brushRotation)); m.scale(m_properties->scale, m_properties->scale); for (quint32 i = 0; i < m_particlesCount; i++) { // generate random angle angle = drand48() * M_PI * 2; // generate random length if (m_properties->gaussian) { length = qBound<qreal>(0.0, m_rand->nextGaussian(0.0, 0.50) , 1.0); } else { length = drand48(); } if (m_shapeDynamicsProperties->enabled) { // rotation rotationZ = rotationAngle(); if (m_shapeDynamicsProperties->followCursor) { rotationZ = linearInterpolation(rotationZ, angle, m_shapeDynamicsProperties->followCursorWeigth); } if (m_shapeDynamicsProperties->followDrawingAngle) { rotationZ = linearInterpolation(rotationZ, info.drawingAngle(), m_shapeDynamicsProperties->followDrawingAngleWeight); } // random size - scale if (m_shapeDynamicsProperties->randomSize) { particleScale = drand48(); } } // generate polar coordinate nx = (m_radius * cos(angle) * length); ny = (m_radius * sin(angle) * length); // compute the height of the ellipse ny *= m_properties->aspect; // transform m.map(nx, ny, &nx, &ny); // color transformation if (shouldColor) { if (m_colorProperties->sampleInputColor) { colorPicker.pickOldColor(nx + x, ny + y, m_inkColor.data()); } // mix the color with background color if (m_colorProperties->mixBgColor) { KoMixColorsOp * mixOp = dab->colorSpace()->mixColorsOp(); const quint8 *colors[2]; colors[0] = m_inkColor.data(); colors[1] = bgColor.data(); qint16 colorWeights[2]; int MAX_16BIT = 255; qreal blend = info.pressure(); colorWeights[0] = static_cast<quint16>(blend * MAX_16BIT); colorWeights[1] = static_cast<quint16>((1.0 - blend) * MAX_16BIT); mixOp->mixColors(colors, colorWeights, 2, m_inkColor.data()); } if (m_colorProperties->useRandomHSV && m_transfo) { params["h"] = (m_colorProperties->hue / 180.0) * drand48(); params["s"] = (m_colorProperties->saturation / 100.0) * drand48(); params["v"] = (m_colorProperties->value / 100.0) * drand48(); m_transfo->setParameters(params); m_transfo->transform(m_inkColor.data(), m_inkColor.data() , 1); } if (m_colorProperties->useRandomOpacity) { quint8 alpha = qRound(drand48() * OPACITY_OPAQUE_U8); m_inkColor.setOpacity(alpha); m_painter->setOpacity(alpha); } if (!m_colorProperties->colorPerParticle) { shouldColor = false; } m_painter->setPaintColor(m_inkColor); } qreal jitteredWidth = qMax(qreal(1.0), m_shapeProperties->width * particleScale); qreal jitteredHeight = qMax(qreal(1.0), m_shapeProperties->height * particleScale); if (m_shapeProperties->enabled){ switch (m_shapeProperties->shape){ // ellipse case 0: { if (m_shapeProperties->width == m_shapeProperties->height){ paintCircle(m_painter, nx + x, ny + y, qRound(jitteredWidth * 0.5)); } else { paintEllipse(m_painter, nx + x, ny + y, qRound(jitteredWidth * 0.5) , qRound(jitteredHeight * 0.5), rotationZ); } break; } // rectangle case 1: { paintRectangle(m_painter, nx + x, ny + y, qRound(jitteredWidth) , qRound(jitteredHeight), rotationZ); break; } // wu-particle case 2: { paintParticle(accessor, m_inkColor, nx + x, ny + y); break; } // pixel case 3: { ix = qRound(nx + x); iy = qRound(ny + y); accessor->moveTo(ix, iy); memcpy(accessor->rawData(), m_inkColor.data(), m_dabPixelSize); break; } case 4: { if (!m_brushQImage.isNull()) { QTransform m; m.rotate(rad2deg(rotationZ)); if (m_shapeDynamicsProperties->randomSize) { m.scale(particleScale, particleScale); } m_transformed = m_brushQImage.transformed(m, Qt::SmoothTransformation); m_imageDevice->convertFromQImage(m_transformed, 0); KisRandomAccessorSP ac = m_imageDevice->createRandomAccessorNG(0, 0); QRect rc = m_transformed.rect(); if (m_colorProperties->useRandomHSV && m_transfo) { for (int y = rc.y(); y < rc.y() + rc.height(); y++) { for (int x = rc.x(); x < rc.x() + rc.width(); x++) { ac->moveTo(x, y); m_transfo->transform(ac->rawData(), ac->rawData() , 1); } } } ix = qRound(nx + x - rc.width() * 0.5); iy = qRound(ny + y - rc.height() * 0.5); m_painter->bitBlt(QPoint(ix, iy), m_imageDevice, rc); m_imageDevice->clear(); break; } } } // Auto-brush } else { QPointF hotSpot = m_brush->hotSpot(particleScale, particleScale, -rotationZ, info); QPointF pos(nx + x, ny + y); QPointF pt = pos - hotSpot; qint32 ix; qreal xFraction; qint32 iy; qreal yFraction; KisPaintOp::splitCoordinate(pt.x(), &ix, &xFraction); KisPaintOp::splitCoordinate(pt.y(), &iy, &yFraction); //KisFixedPaintDeviceSP dab; if (m_brush->brushType() == IMAGE || m_brush->brushType() == PIPE_IMAGE) { m_fixedDab = m_brush->paintDevice(m_fixedDab->colorSpace(), particleScale, -rotationZ, info, xFraction, yFraction); if (m_colorProperties->useRandomHSV && m_transfo) { quint8 * dabPointer = m_fixedDab->data(); int pixelCount = m_fixedDab->bounds().width() * m_fixedDab->bounds().height(); m_transfo->transform(dabPointer, dabPointer, pixelCount); } } else { m_brush->mask(m_fixedDab, m_inkColor, particleScale, particleScale, -rotationZ, info, xFraction, yFraction); } m_painter->bltFixed(QPoint(ix, iy), m_fixedDab, m_fixedDab->bounds()); } } // recover from jittering of color, // m_inkColor.opacity is recovered with every paint }
void KisFilterNoise::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; KisSequentialIterator it(device, applyRect); quint8* interm = new quint8[cs->pixelSize()]; double threshold = (100.0 - level) * 0.01; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; pixels[0] = interm; KoMixColorsOp * mixOp = cs->mixColorsOp(); int seedThreshold = rand(); int seedRed = rand(); int seedGreen = rand(); int seedBlue = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedRed = config->getInt("seedRed", seedRed); seedGreen = config->getInt("seedGreen", seedGreen); seedBlue = config->getInt("seedBlue", seedBlue); } KisRandomGenerator randt(seedThreshold); KisRandomGenerator randr(seedRed); KisRandomGenerator randg(seedGreen); KisRandomGenerator randb(seedBlue); do { if (randt.doubleRandomAt(it.x(), it.y()) > threshold) { // XXX: Added static_cast to get rid of warnings QColor c = qRgb(static_cast<int>((double)randr.doubleRandomAt(it.x(), it.y()) * 255), static_cast<int>((double)randg.doubleRandomAt(it.x(), it.y()) * 255), static_cast<int>((double)randb.doubleRandomAt(it.x(), it.y()) * 255)); cs->fromQColor(c, interm, 0); pixels[1] = it.oldRawData(); mixOp->mixColors(pixels, weights, 2, it.rawData()); } if (progressUpdater) progressUpdater->setValue(++count); } while (it.nextPixel() && !(progressUpdater && progressUpdater->interrupted())); delete [] interm; }
void KoRgbColorSpaceTester::testMixColors() { const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); KoMixColorsOp * mixOp = cs->mixColorsOp(); // Test mixColors. quint8 pixel1[4]; quint8 pixel2[4]; quint8 outputPixel[4]; pixel1[PIXEL_RED] = 255; pixel1[PIXEL_GREEN] = 255; pixel1[PIXEL_BLUE] = 255; pixel1[PIXEL_ALPHA] = 255; pixel2[PIXEL_RED] = 0; pixel2[PIXEL_GREEN] = 0; pixel2[PIXEL_BLUE] = 0; pixel2[PIXEL_ALPHA] = 0; const quint8 *pixelPtrs[2]; qint16 weights[2]; pixelPtrs[0] = pixel1; pixelPtrs[1] = pixel2; weights[0] = 255; weights[1] = 0; mixOp->mixColors(pixelPtrs, weights, 2, outputPixel); QVERIFY((int)outputPixel[PIXEL_RED] == 255); QVERIFY((int)outputPixel[PIXEL_GREEN] == 255); QVERIFY((int)outputPixel[PIXEL_BLUE] == 255); QVERIFY((int)outputPixel[PIXEL_ALPHA] == 255); weights[0] = 0; weights[1] = 255; mixOp->mixColors(pixelPtrs, weights, 2, outputPixel); QVERIFY((int)outputPixel[PIXEL_RED] == 0); QVERIFY((int)outputPixel[PIXEL_GREEN] == 0); QVERIFY((int)outputPixel[PIXEL_BLUE] == 0); QVERIFY((int)outputPixel[PIXEL_ALPHA] == 0); weights[0] = 128; weights[1] = 127; mixOp->mixColors(pixelPtrs, weights, 2, outputPixel); QVERIFY((int)outputPixel[PIXEL_RED] == 255); QVERIFY((int)outputPixel[PIXEL_GREEN] == 255); QVERIFY((int)outputPixel[PIXEL_BLUE] == 255); QVERIFY((int)outputPixel[PIXEL_ALPHA] == 128); pixel1[PIXEL_RED] = 200; pixel1[PIXEL_GREEN] = 100; pixel1[PIXEL_BLUE] = 50; pixel1[PIXEL_ALPHA] = 255; pixel2[PIXEL_RED] = 100; pixel2[PIXEL_GREEN] = 200; pixel2[PIXEL_BLUE] = 20; pixel2[PIXEL_ALPHA] = 255; mixOp->mixColors(pixelPtrs, weights, 2, outputPixel); QVERIFY((int)outputPixel[PIXEL_RED] == 150); QCOMPARE((int)outputPixel[PIXEL_GREEN], 149); QVERIFY((int)outputPixel[PIXEL_BLUE] == 35); QVERIFY((int)outputPixel[PIXEL_ALPHA] == 255); pixel1[PIXEL_RED] = 0; pixel1[PIXEL_GREEN] = 0; pixel1[PIXEL_BLUE] = 0; pixel1[PIXEL_ALPHA] = 0; pixel2[PIXEL_RED] = 255; pixel2[PIXEL_GREEN] = 255; pixel2[PIXEL_BLUE] = 255; pixel2[PIXEL_ALPHA] = 254; weights[0] = 89; weights[1] = 166; mixOp->mixColors(pixelPtrs, weights, 2, outputPixel); QVERIFY((int)outputPixel[PIXEL_RED] == 255); QVERIFY((int)outputPixel[PIXEL_GREEN] == 255); QVERIFY((int)outputPixel[PIXEL_BLUE] == 255); QVERIFY((int)outputPixel[PIXEL_ALPHA] == 165); }
void KoColorSlider::drawContents( QPainter *painter ) { QPixmap checker(8, 8); QPainter p(&checker); p.fillRect(0, 0, 4, 4, Qt::lightGray); p.fillRect(4, 0, 4, 4, Qt::darkGray); p.fillRect(0, 4, 4, 4, Qt::darkGray); p.fillRect(4, 4, 4, 4, Qt::lightGray); p.end(); QRect contentsRect_(contentsRect()); painter->fillRect(contentsRect_, QBrush(checker)); if( !d->upToDate || d->pixmap.isNull() || d->pixmap.width() != contentsRect_.width() || d->pixmap.height() != contentsRect_.height() ) { KoColor c = d->minColor; // smart way to fetch colorspace QColor color; const quint8 *colors[2]; colors[0] = d->minColor.data(); colors[1] = d->maxColor.data(); KoMixColorsOp * mixOp = c.colorSpace()->mixColorsOp(); QImage image(contentsRect_.width(), contentsRect_.height(), QImage::Format_ARGB32 ); if( orientation() == Qt::Horizontal ) { for (int x = 0; x < contentsRect_.width(); x++) { qreal t = static_cast<qreal>(x) / (contentsRect_.width() - 1); qint16 colorWeights[2]; colorWeights[0] = static_cast<quint8>((1.0 - t) * 255 + 0.5); colorWeights[1] = 255 - colorWeights[0]; mixOp->mixColors(colors, colorWeights, 2, c.data()); c.toQColor(&color); for (int y = 0; y < contentsRect_.height(); y++) image.setPixel(x, y, color.rgba()); } } else { for (int y = 0; y < contentsRect_.height(); y++) { qreal t = static_cast<qreal>(y) / (contentsRect_.height() - 1); qint16 colorWeights[2]; colorWeights[0] = static_cast<quint8>((t) * 255 + 0.5); colorWeights[1] = 255 - colorWeights[0]; mixOp->mixColors(colors, colorWeights, 2, c.data()); c.toQColor(&color); for (int x = 0; x < contentsRect_.width(); x++) image.setPixel(x, y, color.rgba()); } } d->pixmap = QPixmap::fromImage(image); d->upToDate = true; } painter->drawPixmap( contentsRect_, d->pixmap, QRect( 0, 0, d->pixmap.width(), d->pixmap.height()) ); }
void KisCubismFilter::fillPolyColor(KisPaintDeviceSP src, const QPoint& srcTopLeft, KisPaintDeviceSP dst, const QPoint & dstTopLeft, const QSize& size, KisPolygon* poly, const quint8* col, quint8* dest) const // void KisCubismFilter::fillPolyColor (KisPaintDeviceSP src, KisPaintDeviceSP dst, KisPolygon* poly, const quint8* col, quint8* /*s*/, QRect rect) const { Q_UNUSED(srcTopLeft); Q_UNUSED(dest); qint32 val; double alpha; qint32 x, y; double xx, yy; double vec[2]; QRect rect(dstTopLeft, size); qint32 x1 = rect.left(), y1 = rect.top(), x2 = rect.right(), y2 = rect.bottom(); // qint32 selWidth, selHeight; qint32 *vals, *valsIter, *valsEnd; qint32 xs, ys, xe, ye; qint32 sx = (qint32)(*poly)[0].x(); qint32 sy = (qint32)(*poly)[0].y(); qint32 ex = (qint32)(*poly)[1].x(); qint32 ey = (qint32)(*poly)[1].y(); double dist = sqrt((double)(SQR(ex - sx) + SQR(ey - sy))); double oneOverDist = 0.0; if (dist > 0.0) { double oneOverDist = 1 / dist; vec[0] = (ex - sx) * oneOverDist; vec[1] = (ey - sy) * oneOverDist; } qint32 pixelSize = src->pixelSize(); //get the extents of the polygon double dMinX, dMinY, dMaxX, dMaxY; poly->extents(dMinX, dMinY, dMaxX, dMaxY); qint32 minX = static_cast<qint32>(dMinX); qint32 minY = static_cast<qint32>(dMinY); qint32 maxX = static_cast<qint32>(dMaxX); qint32 maxY = static_cast<qint32>(dMaxY); qint32 sizeX = (maxX - minX) * SUPERSAMPLE; qint32 sizeY = (maxY - minY) * SUPERSAMPLE; qint32 *minScanlines = new qint32[sizeY]; qint32 *minScanlinesIter = minScanlines; qint32 *maxScanlines = new qint32[sizeY]; qint32 *maxScanlinesIter = maxScanlines; for (qint32 i = 0; i < sizeY; i++) { minScanlines[i] = maxX * SUPERSAMPLE; maxScanlines[i] = minX * SUPERSAMPLE; } if (poly->numberOfPoints()) { qint32 polyNpts = poly->numberOfPoints(); xs = static_cast<qint32>((*poly)[polyNpts-1].x()); ys = static_cast<qint32>((*poly)[polyNpts-1].y()); xe = static_cast<qint32>((*poly)[0].x()); ye = static_cast<qint32>((*poly)[0].y()); xs *= SUPERSAMPLE; ys *= SUPERSAMPLE; xe *= SUPERSAMPLE; ye *= SUPERSAMPLE; convertSegment(xs, ys, xe, ye, minY * SUPERSAMPLE, minScanlines, maxScanlines, minX* SUPERSAMPLE, maxX* SUPERSAMPLE); KisPolygon::iterator it; for (it = poly->begin(); it != poly->end();) { xs = static_cast<qint32>((*it).x()); ys = static_cast<qint32>((*it).y()); ++it; if (it != poly->end()) { xe = static_cast<qint32>((*it).x()); ye = static_cast<qint32>((*it).y()); xs *= SUPERSAMPLE; ys *= SUPERSAMPLE; xe *= SUPERSAMPLE; ye *= SUPERSAMPLE; convertSegment(xs, ys, xe, ye, minY * SUPERSAMPLE, minScanlines, maxScanlines, minX* SUPERSAMPLE, maxX* SUPERSAMPLE); } } } KisRandomAccessor dstAccessor = dst->createRandomAccessor(0, 0); KoMixColorsOp * mixOp = src->colorSpace()->mixColorsOp(); quint8* buf = new quint8[pixelSize]; vals = new qint32[sizeX]; // x1 = minX; x2 = maxX; y1 = minY; y2 = maxY; for (qint32 i = 0; i < sizeY; i++, minScanlinesIter++, maxScanlinesIter++) { if (!(i % SUPERSAMPLE)) { memset(vals, 0, sizeof(qint32) * sizeX); } yy = static_cast<double>(i) / static_cast<double>(SUPERSAMPLE) + minY; for (qint32 j = *minScanlinesIter; j < *maxScanlinesIter; j++) { x = j - minX * SUPERSAMPLE; vals[x] += 255; } if (!((i + 1) % SUPERSAMPLE)) { y = (i / SUPERSAMPLE) + minY; if (y >= y1 && y <= y2) { for (qint32 j = 0; j < sizeX; j += SUPERSAMPLE) { x = (j / SUPERSAMPLE) + minX; if (x >= x1 && x <= x2) { for (val = 0, valsIter = &vals[j], valsEnd = &valsIter[SUPERSAMPLE]; valsIter < valsEnd; valsIter++) { val += *valsIter; } val /= SQR(SUPERSAMPLE); if (val > 0) { xx = static_cast<double>(j) / static_cast<double>(SUPERSAMPLE) + minX; alpha = calcAlphaBlend(vec, oneOverDist, xx - sx, yy - sy); qint16 weights[2]; weights[0] = static_cast<quint8>(alpha * 255); weights[1] = 255 - weights[0]; dstAccessor.moveTo(x, y); memcpy(buf, dstAccessor.rawData(), sizeof(quint8) * pixelSize); const quint8* colors[2]; colors[0] = col; colors[1] = buf; mixOp->mixColors(colors, weights, 2, dstAccessor.rawData()); } } } } } } delete[] buf; delete[] vals; delete[] minScanlines; delete[] maxScanlines; }