void Shadow::draw(QPainter* painter) { // if nothing to show outside the item, just draw source if ((blurRadius() + distance()) <= 0) { drawSource(painter); return; } PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect; QPoint offset; const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); // return if no source if (px.isNull()) return; // save world transform QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); // Calculate size for the background image QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance()); QImage tmp(szi, QImage::Format_ARGB32_Premultiplied); QPixmap scaled = px.scaled(szi); tmp.fill(0); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled); tmpPainter.end(); // blur the alpha channel QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.fill(0); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, blurRadius(), false, true); blurPainter.end(); tmp = blurred; // blacken the image... tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color()); tmpPainter.end(); // draw the blurred shadow... painter->drawImage(offset, tmp); // draw the actual pixmap... painter->drawPixmap(offset, px, QRectF()); // restore world transform painter->setWorldTransform(restoreTransform); }
void FEDropShadow::applySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Filter* filter = this->filter(); FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY)); FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); GraphicsContext* resultContext = resultImage->context(); ASSERT(resultContext); Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity)); SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(blurRadius.width(), blurRadius.height())); SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(color.rgb(), SkXfermode::kSrcIn_Mode)); SkPaint paint; paint.setImageFilter(blurFilter.get()); paint.setColorFilter(colorFilter.get()); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame(); if (!nativeImage) return; resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x() + offset.width(), drawingRegion.y() + offset.height(), &paint); resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y()); }
void QVGPixmapDropShadowFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const { if (src.isNull()) return; if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { // The pixmap data is not an instance of QVGPixmapData, so fall // back to the default drop shadow filter implementation. QPixmapDropShadowFilter::draw(painter, dest, src, srcRect); return; } QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); VGImage srcImage = pd->toVGImage(); if (srcImage == VG_INVALID_HANDLE) return; QSize size = pd->size(); VGImage dstImage = QVGImagePool::instance()->createTemporaryImage (VG_A_8, size.width(), size.height(), VG_IMAGE_QUALITY_FASTER, pd); if (dstImage == VG_INVALID_HANDLE) return; // Clamp the radius range. We divide by 2 because the OpenVG blur // is "too blurry" compared to the default raster implementation. VGfloat maxRadius = VGfloat(vgGeti(VG_MAX_GAUSSIAN_STD_DEVIATION)); VGfloat radiusF = VGfloat(blurRadius()) / 2.0f; if (radiusF < 0.001f) radiusF = 0.001f; else if (radiusF > maxRadius) radiusF = maxRadius; // Blur the blackened source image. vgGaussianBlur(dstImage, srcImage, radiusF, radiusF, VG_TILE_PAD); VGImage child = VG_INVALID_HANDLE; QRect srect; if (srcRect.isNull() || (srcRect.topLeft().isNull() && srcRect.size() == size)) { child = dstImage; srect = QRect(0, 0, size.width(), size.height()); } else { srect = srcRect.toRect(); child = vgChildImage(dstImage, srect.x(), srect.y(), srect.width(), srect.height()); } qt_vg_drawVGImageStencil(painter, dest + offset(), child, color()); if(child != dstImage) vgDestroyImage(child); QVGImagePool::instance()->releaseImage(0, dstImage); // Now draw the actual pixmap over the top. painter->drawPixmap(dest, src, srect); }
QT_END_NAMESPACE void ShadowEffect::draw(QPainter* painter){ if((blurRadius() + distance()) <= 0){ drawSource(painter); return; } PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect; QPoint offset; const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); if(px.isNull()) return; QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance()); QImage tmp(szi, QImage::Format_ARGB32_Premultiplied); QPixmap scaled = px.scaled(szi); tmp.fill(0); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled); tmpPainter.end(); QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.fill(0); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, blurRadius(), false, true); blurPainter.end(); tmp = blurred; tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color()); tmpPainter.end(); painter->drawImage(offset, tmp); painter->drawPixmap(offset, px, QRectF()); painter->setWorldTransform(restoreTransform); }
void CSDirection::blurRadius(const int dBlur) { if (m_lX > 0 && m_lY > 0 && m_dir) { std::unique_ptr<UCHAR[]> sel(new UCHAR[m_lX * m_lY]); if (!sel) throw SMemAllocError("in directionMap"); memcpy(sel.get(), m_dir.get(), m_lX * m_lY * sizeof(UCHAR)); UCHAR *pSel = sel.get(); UCHAR *pDir = m_dir.get(); for (int y = 0; y < m_lY; y++) for (int x = 0; x < m_lX; x++, pSel++, pDir++) if (*pSel > (UCHAR)0) *pDir = blurRadius(sel.get(), x, y, dBlur); } }
int QGraphicsDropShadowEffect::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QGraphicsEffect::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { if (_id < 10) qt_static_metacall(this, _c, _id, _a); _id -= 10; } #ifndef QT_NO_PROPERTIES else if (_c == QMetaObject::ReadProperty) { void *_v = _a[0]; switch (_id) { case 0: *reinterpret_cast< QPointF*>(_v) = offset(); break; case 1: *reinterpret_cast< qreal*>(_v) = xOffset(); break; case 2: *reinterpret_cast< qreal*>(_v) = yOffset(); break; case 3: *reinterpret_cast< qreal*>(_v) = blurRadius(); break; case 4: *reinterpret_cast< QColor*>(_v) = color(); break; } _id -= 5; } else if (_c == QMetaObject::WriteProperty) { void *_v = _a[0]; switch (_id) { case 0: setOffset(*reinterpret_cast< QPointF*>(_v)); break; case 1: setXOffset(*reinterpret_cast< qreal*>(_v)); break; case 2: setYOffset(*reinterpret_cast< qreal*>(_v)); break; case 3: setBlurRadius(*reinterpret_cast< qreal*>(_v)); break; case 4: setColor(*reinterpret_cast< QColor*>(_v)); break; } _id -= 5; } else if (_c == QMetaObject::ResetProperty) { _id -= 5; } else if (_c == QMetaObject::QueryPropertyDesignable) { _id -= 5; } else if (_c == QMetaObject::QueryPropertyScriptable) { _id -= 5; } else if (_c == QMetaObject::QueryPropertyStored) { _id -= 5; } else if (_c == QMetaObject::QueryPropertyEditable) { _id -= 5; } else if (_c == QMetaObject::QueryPropertyUser) { _id -= 5; } #endif // QT_NO_PROPERTIES return _id; }
void CSDirection::doRadius(const double rH, const double rLR, const double rV, const double rRL, const int dBlur) { try { int xy = m_lX * m_lY; UCHAR *pDir = m_dir.get(); double r[4] = {D_CUT_0_1(rH), D_CUT_0_1(rLR), D_CUT_0_1(rV), D_CUT_0_1(rRL)}; for (int i = 0; i < xy; i++, pDir++) if (*pDir < (UCHAR)50) { *pDir = (UCHAR)0; } else *pDir = getRadius((double)(*pDir - 50), r); if (dBlur > 0) blurRadius(dBlur); } catch (SMemAllocError) { throw; } }
void FEDropShadow::platformApplySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Filter& filter = this->filter(); FloatSize blurRadius(2 * filter.applyHorizontalScale(m_stdX), 2 * filter.applyVerticalScale(m_stdY)); blurRadius.scale(filter.filterScale()); FloatSize offset(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy)); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); FloatRect drawingRegionWithOffset(drawingRegion); drawingRegionWithOffset.move(offset); ImageBuffer* sourceImage = in->asImageBuffer(); if (!sourceImage) return; GraphicsContext& resultContext = resultImage->context(); resultContext.setAlpha(m_shadowOpacity); resultContext.drawImageBuffer(*sourceImage, drawingRegionWithOffset); resultContext.setAlpha(1); ShadowBlur contextShadow(blurRadius, offset, m_shadowColor); // TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData. IntRect shadowArea(IntPoint(), resultImage->internalSize()); RefPtr<Uint8ClampedArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea, ImageBuffer::BackingStoreCoordinateSystem); contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width()); resultImage->putByteArray(Premultiplied, srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint(), ImageBuffer::BackingStoreCoordinateSystem); resultContext.setCompositeOperation(CompositeSourceIn); resultContext.fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor); resultContext.setCompositeOperation(CompositeDestinationOver); resultImage->context().drawImageBuffer(*sourceImage, drawingRegion); }
int QGraphicsBlurEffect::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QGraphicsEffect::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { if (_id < 4) qt_static_metacall(this, _c, _id, _a); _id -= 4; } #ifndef QT_NO_PROPERTIES else if (_c == QMetaObject::ReadProperty) { void *_v = _a[0]; switch (_id) { case 0: *reinterpret_cast< qreal*>(_v) = blurRadius(); break; case 1: *reinterpret_cast<int*>(_v) = QFlag(blurHints()); break; } _id -= 2; } else if (_c == QMetaObject::WriteProperty) { void *_v = _a[0]; switch (_id) { case 0: setBlurRadius(*reinterpret_cast< qreal*>(_v)); break; case 1: setBlurHints(QFlag(*reinterpret_cast<int*>(_v))); break; } _id -= 2; } else if (_c == QMetaObject::ResetProperty) { _id -= 2; } else if (_c == QMetaObject::QueryPropertyDesignable) { _id -= 2; } else if (_c == QMetaObject::QueryPropertyScriptable) { _id -= 2; } else if (_c == QMetaObject::QueryPropertyStored) { _id -= 2; } else if (_c == QMetaObject::QueryPropertyEditable) { _id -= 2; } else if (_c == QMetaObject::QueryPropertyUser) { _id -= 2; } #endif // QT_NO_PROPERTIES return _id; }
void FEDropShadow::platformApplySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Filter* filter = this->filter(); FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY)); FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); FloatRect drawingRegionWithOffset(drawingRegion); drawingRegionWithOffset.move(offset); ImageBuffer* sourceImage = in->asImageBuffer(); ASSERT(sourceImage); GraphicsContext* resultContext = resultImage->context(); ASSERT(resultContext); resultContext->setAlpha(m_shadowOpacity); resultContext->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegionWithOffset); resultContext->setAlpha(1); ShadowBlur contextShadow(blurRadius, offset, m_shadowColor, ColorSpaceDeviceRGB); // TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData. IntRect shadowArea(IntPoint(), resultImage->size()); RefPtr<ByteArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea); contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width()); resultImage->putPremultipliedImageData(srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint()); resultContext->setCompositeOperation(CompositeSourceIn); resultContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor, ColorSpaceDeviceRGB); resultContext->setCompositeOperation(CompositeDestinationOver); resultImage->context()->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegion); }
QRectF Shadow::boundingRectFor(const QRectF& rect) const { qreal delta = blurRadius() + distance(); return rect.united(rect.adjusted(-delta, -delta, delta, delta)); }