void SVGFilterRecordingContext::endContent(FilterData* filterData)
{
    ASSERT(filterData->m_state == FilterData::RecordingContent);

    SourceGraphic* sourceGraphic = filterData->filter->sourceGraphic();
    ASSERT(sourceGraphic);

    GraphicsContext* context = &paintingContext();

    // Use the context that contains the filtered content.
    ASSERT(m_paintController);
    ASSERT(m_context);
    context = m_context.get();
    context->beginRecording(filterData->filter->filterRegion());
    m_paintController->commitNewDisplayItems();
    m_paintController->paintArtifact().replay(*context);

    sourceGraphic->setPicture(context->endRecording());

    // Content is cached by the source graphic so temporaries can be freed.
    m_paintController = nullptr;
    m_context = nullptr;

    filterData->m_state = FilterData::ReadyToPaint;
}
Example #2
0
PassRefPtr<SkImageFilter> FEImage::createImageFilterForRenderer(RenderObject* renderer, SkiaImageFilterBuilder* builder)
{
    FloatRect dstRect = filterPrimitiveSubregion();

    AffineTransform transform;
    SVGElement* contextNode = toSVGElement(renderer->node());

    if (contextNode->hasRelativeLengths()) {
        SVGLengthContext lengthContext(contextNode);
        FloatSize viewportSize;

        // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
        // Build up a transformation that maps from the viewport space to the filter primitive subregion.
        if (lengthContext.determineViewport(viewportSize))
            transform = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), dstRect);
    } else {
        transform.translate(dstRect.x(), dstRect.y());
    }

    GraphicsContext* context = builder->context();
    if (!context)
        return adoptRef(SkBitmapSource::Create(SkBitmap()));
    AffineTransform contentTransformation;
    context->save();
    context->beginRecording(FloatRect(FloatPoint(), dstRect.size()));
    context->concatCTM(transform);
    SVGRenderingContext::renderSubtree(context, renderer, contentTransformation);
    RefPtr<DisplayList> displayList = context->endRecording();
    context->restore();
    RefPtr<SkImageFilter> result = adoptRef(SkPictureImageFilter::Create(displayList->picture(), dstRect));
    return result.release();
}
DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClientWrapper& displayItemClient, DisplayItem::Type displayItemType, const FloatRect& cullRect)
    : m_context(context)
    , m_displayItemClient(displayItemClient)
    , m_displayItemType(displayItemType)
#if ENABLE(ASSERT)
    , m_displayItemPosition(m_context.displayItemList()->newDisplayItems().size())
    , m_underInvalidationCheckingMode(DrawingDisplayItem::CheckPicture)
#endif
{
    ASSERT(context.displayItemList());
    if (context.displayItemList()->displayItemConstructionIsDisabled())
        return;

    // Must check DrawingRecorder::useCachedDrawingIfPossible before creating the DrawingRecorder.
    ASSERT((RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && context.displayItemList()->paintOffsetWasInvalidated(displayItemClient.displayItemClient()))
        || RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
        || !useCachedDrawingIfPossible(m_context, m_displayItemClient, m_displayItemType));

    ASSERT(DisplayItem::isDrawingType(displayItemType));

#if ENABLE(ASSERT)
    context.setInDrawingRecorder(true);
#endif

    context.beginRecording(cullRect);

#if ENABLE(ASSERT)
    if (RuntimeEnabledFeatures::slimmingPaintStrictCullRectClippingEnabled()) {
        // Skia depends on the cull rect containing all of the display item commands. When strict
        // cull rect clipping is enabled, make this explicit. This allows us to identify potential
        // incorrect cull rects that might otherwise be masked due to Skia internal optimizations.
        context.save();
        IntRect verificationClip = enclosingIntRect(cullRect);
        // Expand the verification clip by one pixel to account for Skia's SkCanvas::getClipBounds()
        // expansion, used in testing cull rects.
        // TODO(schenney) This is not the best place to do this. Ideally, we would expand by one pixel
        // in device (pixel) space, but to do that we would need to add the verification mode to Skia.
        verificationClip.inflate(1);
        context.clipRect(verificationClip, NotAntiAliased, SkRegion::kIntersect_Op);
    }
#endif
}