void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object) { m_itemBBox = object->objectBoundingBox(); m_filterBBox = filterBBoxForItemBBox(m_itemBBox); // clip sourceImage to filterRegion FloatRect clippedSourceRect = m_itemBBox; clippedSourceRect.intersect(m_filterBBox); // prepare Filters m_filter = SVGFilter::create(m_itemBBox, m_filterBBox, m_effectBBoxMode, m_filterBBoxMode); FilterEffect* lastEffect = m_filterBuilder->lastEffect(); if (lastEffect) lastEffect->calculateEffectRect(m_filter.get()); // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. // The size of the SourceGraphic is clipped to the size of the filterRegion. IntRect bufferRect = enclosingIntRect(clippedSourceRect); OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB)); if (!sourceGraphic.get()) return; GraphicsContext* sourceGraphicContext = sourceGraphic->context(); sourceGraphicContext->translate(-m_itemBBox.x(), -m_itemBBox.y()); sourceGraphicContext->clearRect(FloatRect(FloatPoint(), m_itemBBox.size())); m_sourceGraphicBuffer.set(sourceGraphic.release()); m_savedContext = context; context = sourceGraphicContext; }
PassRefPtr<SkImageFilter> SourceAlpha::createImageFilter(SkiaImageFilterBuilder& builder) { RefPtr<SkImageFilter> sourceGraphic(builder.build(inputEffect(0), operatingColorSpace())); SkScalar matrix[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1, 0 }; RefPtr<SkColorFilter> colorFilter(adoptRef(SkColorMatrixFilter::Create(matrix))); return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), sourceGraphic.get())); }
void KoShapeShadow::paint(KoShape *shape, QPainter &painter, const KoViewConverter &converter) { if (! d->visible) return; // So the approach we are taking here is to draw into a buffer image the size of boundingRect // We offset by the shadow offset at the time we draw into the buffer // Then we filter the image and draw it at the position of the bounding rect on canvas //the boundingRect of the shape or the KoSelection boundingRect of the group QRectF shadowRect = shape->boundingRect(); QRectF zoomedClipRegion = converter.documentToView(shadowRect); // Init the buffer image QImage sourceGraphic(zoomedClipRegion.size().toSize(), QImage::Format_ARGB32_Premultiplied); sourceGraphic.fill(qRgba(0,0,0,0)); // Init the buffer painter QPainter imagePainter(&sourceGraphic); imagePainter.setPen(Qt::NoPen); imagePainter.setBrush(Qt::NoBrush); imagePainter.setRenderHint(QPainter::Antialiasing, painter.testRenderHint(QPainter::Antialiasing)); // Since our imagebuffer and the canvas don't align we need to offset our drawings imagePainter.translate(-1.0f*converter.documentToView(shadowRect.topLeft())); // Handle the shadow offset imagePainter.translate(converter.documentToView(offset())); KoShapeGroup *group = dynamic_cast<KoShapeGroup*>(shape); if (group) { d->paintGroupShadow(group, imagePainter, converter); } else { //apply shape's transformation imagePainter.setTransform(shape->absoluteTransformation(&converter), true); d->paintShadow(shape, imagePainter, converter); } imagePainter.end(); // Blur the shadow (well the entire buffer) d->blurShadow(sourceGraphic, converter.documentToViewX(d->blur), d->color); // Paint the result painter.save(); // The painter is initialized for us with canvas transform 'plus' shape transform // we are only interested in the canvas transform so 'subtract' the shape transform part painter.setTransform(shape->absoluteTransformation(&converter).inverted() * painter.transform()); painter.drawImage(zoomedClipRegion.topLeft(), sourceGraphic); painter.restore(); }
bool SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object) { m_ownerElement->buildFilter(object->objectBoundingBox()); const SVGRenderBase* renderer = object->toSVGRenderBase(); if (!renderer) return false; FloatRect paintRect = renderer->strokeBoundingBox(); paintRect.unite(renderer->markerBoundingBox()); if (shouldProcessFilter(this, m_filterBBox)) return false; // clip sourceImage to filterRegion FloatRect clippedSourceRect = paintRect; clippedSourceRect.intersect(m_filterBBox); // scale filter size to filterRes FloatRect tempSourceRect = clippedSourceRect; if (m_filterRes) { m_scaleX = m_filterResSize.width() / m_filterBBox.width(); m_scaleY = m_filterResSize.height() / m_filterBBox.height(); } // scale to big sourceImage size to kMaxFilterSize tempSourceRect.scale(m_scaleX, m_scaleY); fitsInMaximumImageSize(tempSourceRect.size()); // prepare Filters m_filter = SVGFilter::create(paintRect, m_filterBBox, m_effectBBoxMode); m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY)); FilterEffect* lastEffect = m_filterBuilder->lastEffect(); if (lastEffect) { lastEffect->calculateEffectRect(m_filter.get()); // at least one FilterEffect has a too big image size, // recalculate the effect sizes with new scale factors if (!fitsInMaximumImageSize(m_filter->maxImageSize())) { m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY)); lastEffect->calculateEffectRect(m_filter.get()); } } else return false; clippedSourceRect.scale(m_scaleX, m_scaleY); // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. // The size of the SourceGraphic is clipped to the size of the filterRegion. IntRect bufferRect = enclosingIntRect(clippedSourceRect); OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB)); if (!sourceGraphic.get()) return false; GraphicsContext* sourceGraphicContext = sourceGraphic->context(); sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y()); sourceGraphicContext->scale(FloatSize(m_scaleX, m_scaleY)); sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size())); m_sourceGraphicBuffer.set(sourceGraphic.release()); m_savedContext = context; context = sourceGraphicContext; return true; }
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) { ASSERT(object); ASSERT(context); #ifndef NDEBUG ASSERT(resourceMode == ApplyToDefaultMode); #else UNUSED_PARAM(resourceMode); #endif // Returning false here, to avoid drawings onto the context. We just want to // draw the stored filter output, not the unfiltered object as well. if (m_filter.contains(object)) { FilterData* filterData = m_filter.get(object); if (filterData->builded) return false; delete m_filter.take(object); // Oops, have to rebuild, go through normal code path } OwnPtr<FilterData> filterData(new FilterData); filterData->builder = buildPrimitives(); if (!filterData->builder) return false; FloatRect paintRect = object->strokeBoundingBox(); // Calculate the scale factor for the use of filterRes. // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); filterData->boundaries = filterElement->filterBoundingBox(object->objectBoundingBox()); if (filterData->boundaries.isEmpty()) return false; FloatSize scale(1.0f, 1.0f); if (filterElement->hasAttribute(SVGNames::filterResAttr)) { scale.setWidth(filterElement->filterResX() / filterData->boundaries.width()); scale.setHeight(filterElement->filterResY() / filterData->boundaries.height()); } if (scale.isEmpty()) return false; // clip sourceImage to filterRegion FloatRect clippedSourceRect = paintRect; clippedSourceRect.intersect(filterData->boundaries); // scale filter size to filterRes FloatRect tempSourceRect = clippedSourceRect; // scale to big sourceImage size to kMaxFilterSize tempSourceRect.scale(scale.width(), scale.height()); fitsInMaximumImageSize(tempSourceRect.size(), scale); // prepare Filters bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; filterData->filter = SVGFilter::create(paintRect, filterData->boundaries, primitiveBoundingBoxMode); filterData->filter->setFilterResolution(scale); FilterEffect* lastEffect = filterData->builder->lastEffect(); if (!lastEffect) return false; lastEffect->calculateEffectRect(filterData->filter.get()); // At least one FilterEffect has a too big image size, // recalculate the effect sizes with new scale factors. if (!fitsInMaximumImageSize(filterData->filter->maxImageSize(), scale)) { filterData->filter->setFilterResolution(scale); lastEffect->calculateEffectRect(filterData->filter.get()); } clippedSourceRect.scale(scale.width(), scale.height()); // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. // The size of the SourceGraphic is clipped to the size of the filterRegion. IntRect bufferRect = enclosingIntRect(clippedSourceRect); OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB)); if (!sourceGraphic.get()) return false; GraphicsContext* sourceGraphicContext = sourceGraphic->context(); sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y()); sourceGraphicContext->scale(scale); sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size())); filterData->sourceGraphicBuffer = sourceGraphic.release(); filterData->savedContext = context; context = sourceGraphicContext; ASSERT(!m_filter.contains(object)); m_filter.set(object, filterData.leakPtr()); return true; }