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;
}
Example #2
0
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;
}
Example #5
0
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;
}