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;
}
GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* oldContext)
{
    ASSERT(m_renderLayer);

    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
    filter->allocateBackingStoreIfNeeded();
    // Paint into the context that represents the SourceGraphic of the filter.
    GraphicsContext* sourceGraphicsContext = filter->inputContext();
    if (!sourceGraphicsContext || !FilterEffect::isFilterSizeValid(filter->absoluteFilterRegion())) {
        // Disable the filters and continue.
        m_haveFilterEffect = false;
        return oldContext;
    }

    m_savedGraphicsContext = oldContext;

    // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
    sourceGraphicsContext->save();
    // FIXME: can we just use sourceImageRect for everything, and get rid of
    // m_repaintRect?
    FloatPoint offset = filter->sourceImageRect().location();
    sourceGraphicsContext->translate(-offset.x(), -offset.y());
    sourceGraphicsContext->clearRect(m_repaintRect);
    sourceGraphicsContext->clip(m_repaintRect);

    return sourceGraphicsContext;
}
Esempio n. 3
0
GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(RenderLayer* renderLayer, GraphicsContext* oldContext, const LayoutRect& filterRect)
{
    ASSERT(m_haveFilterEffect && renderLayer->filter());
    m_savedGraphicsContext = oldContext;
    m_renderLayer = renderLayer;
    m_paintOffset = filterRect.location();
    
    FloatRect filterSourceRect = filterRect;
    filterSourceRect.setLocation(LayoutPoint());
    
    FilterEffectRenderer* filter = renderLayer->filter();
    filter->updateBackingStore(filterSourceRect);
    filter->prepare();
    
    // Paint into the context that represents the SourceGraphic of the filter.
    GraphicsContext* sourceGraphicsContext = filter->inputContext();
    if (!sourceGraphicsContext) {
        // Could not allocate a new graphics context. Disable the filters and continue.
        m_haveFilterEffect = false;
        return m_savedGraphicsContext;
    }
    
    sourceGraphicsContext->save();
    sourceGraphicsContext->translate(-filterRect.x(), -filterRect.y());
    sourceGraphicsContext->clearRect(filterRect);
    
    return sourceGraphicsContext;
}
void CoordinatedLayerTreeHost::paintLayerContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, const IntRect& clipRect)
{
    if (graphicsLayer == m_pageOverlayLayer) {
        // Overlays contain transparent contents and won't clear the context as part of their rendering, so we do it here.
        graphicsContext.clearRect(clipRect);
        m_webPage->drawPageOverlay(m_pageOverlay.get(), graphicsContext, clipRect);
        return;
    }
}
Esempio n. 5
0
 virtual void paint(GraphicsContext& context, const IntRect& contentRect)
 {
     double paintStart = currentTime();
     context.clearRect(contentRect);
     context.clip(contentRect);
     m_owner->paintGraphicsLayerContents(context, contentRect);
     double paintEnd = currentTime();
     double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart);
     PlatformBridge::histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
     PlatformBridge::histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
 }
void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
{
    if (!validateRectForCanvas(x, y, width, height))
        return;
    GraphicsContext* c = drawingContext();
    if (!c)
        return;
    FloatRect rect(x, y, width, height);
    willDraw(rect);
    c->clearRect(rect);
}
void BitmapTextureImageBuffer::updateContents(TextureMapper*, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& sourceOffset, UpdateContentsFlag)
{
    GraphicsContext* context = m_image->context();

    context->clearRect(targetRect);

    IntRect sourceRect(targetRect);
    sourceRect.setLocation(sourceOffset);
    context->save();
    context->translate(targetRect.x() - sourceOffset.x(), targetRect.y() - sourceOffset.y());
    sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
    context->restore();
}
void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height, ExceptionCode& ec)
{
    ec = 0;
    if (!(width >= 0 && height >= 0)) {
        ec = INDEX_SIZE_ERR;
        return;
    }
    GraphicsContext* c = drawingContext();
    if (!c)
        return;
    FloatRect rect(x, y, width, height);
    willDraw(rect);
    c->clearRect(rect);
}
Esempio n. 9
0
void RegionOverlay::drawRect(PageOverlay&, GraphicsContext& context, const IntRect& dirtyRect)
{
    context.clearRect(dirtyRect);

    if (!m_region)
        return;
    
    GraphicsContextStateSaver saver(context);
    context.setFillColor(m_color);
    for (auto rect : m_region->rects()) {
    
        if (rect.intersects(dirtyRect))
            context.fillRect(rect);
    }
}
GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* context)
{
    ASSERT(m_renderLayer);

    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
    if (m_renderLayer->renderer()->document().settings()->deferredFiltersEnabled()) {
        SkiaImageFilterBuilder builder(context);
        RefPtr<ImageFilter> imageFilter = builder.build(filter->lastEffect().get(), ColorSpaceDeviceRGB);
        if (!imageFilter) {
            m_haveFilterEffect = false;
            return context;
        }
        m_savedGraphicsContext = context;
        context->save();
        FloatRect boundaries = mapImageFilterRect(imageFilter.get(), m_filterBoxRect);
        context->translate(m_filterBoxRect.x(), m_filterBoxRect.y());
        boundaries.move(-m_filterBoxRect.x(), -m_filterBoxRect.y());
        context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get());
        context->translate(-m_filterBoxRect.x(), -m_filterBoxRect.y());
        return context;
    }
    filter->allocateBackingStoreIfNeeded();
    // Paint into the context that represents the SourceGraphic of the filter.
    GraphicsContext* sourceGraphicsContext = filter->inputContext();
    if (!sourceGraphicsContext || !FilterEffect::isFilterSizeValid(filter->absoluteFilterRegion())) {
        // Disable the filters and continue.
        m_haveFilterEffect = false;
        return context;
    }

    m_savedGraphicsContext = context;

    // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
    sourceGraphicsContext->save();
    // FIXME: can we just use sourceImageRect for everything, and get rid of
    // m_paintInvalidationRect?
    FloatPoint offset = filter->sourceImageRect().location();
    sourceGraphicsContext->translate(-offset.x(), -offset.y());
    sourceGraphicsContext->clearRect(m_paintInvalidationRect);
    sourceGraphicsContext->clip(m_paintInvalidationRect);

    return sourceGraphicsContext;
}
Esempio n. 11
0
void FindController::drawRect(PageOverlay*, GraphicsContext& graphicsContext, const IntRect& dirtyRect)
{
    Color overlayBackgroundColor(0.1f, 0.1f, 0.1f, 0.25f);

    Vector<IntRect> rects = rectsForTextMatches();

    // Draw the background.
    graphicsContext.fillRect(dirtyRect, overlayBackgroundColor, ColorSpaceSRGB);

    {
        GraphicsContextStateSaver stateSaver(graphicsContext);

#if ENABLE(LEGACY_FIND_INDICATOR_STYLE)
        graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, Color::black, ColorSpaceSRGB);
#endif
        graphicsContext.setFillColor(Color::white, ColorSpaceSRGB);

        // Draw white frames around the holes.
        for (auto& rect : rects) {
            IntRect whiteFrameRect = rect;
            whiteFrameRect.inflate(1);
            graphicsContext.fillRect(whiteFrameRect);
        }
    }

    // Clear out the holes.
    for (auto& rect : rects)
        graphicsContext.clearRect(rect);

    if (!m_isShowingFindIndicator)
        return;

    if (Frame* selectedFrame = frameWithSelection(m_webPage->corePage())) {
        IntRect findIndicatorRect = selectedFrame->view()->contentsToWindow(enclosingIntRect(selectedFrame->selection().selectionBounds()));

        if (findIndicatorRect != m_findIndicatorRect)
            hideFindIndicator();
    }
}
Esempio n. 12
0
bool FilterEffectRendererHelper::beginFilterEffect()
{
    ASSERT(m_renderLayer);
    
    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
    filter->allocateBackingStoreIfNeeded();
    // Paint into the context that represents the SourceGraphic of the filter.
    GraphicsContext* sourceGraphicsContext = filter->inputContext();
    if (!sourceGraphicsContext || filter->filterRegion().isEmpty() || ImageBuffer::sizeNeedsClamping(filter->filterRegion().size())) {
        // Disable the filters and continue.
        m_haveFilterEffect = false;
        return false;
    }
    
    // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
    sourceGraphicsContext->save();
    sourceGraphicsContext->translate(-m_paintOffset.x(), -m_paintOffset.y());
    sourceGraphicsContext->clearRect(m_repaintRect);
    sourceGraphicsContext->clip(m_repaintRect);

    m_startedFilterEffect = true;
    return true;
}
Esempio n. 13
0
void FindController::drawRect(PageOverlay*, GraphicsContext& graphicsContext, const IntRect& dirtyRect)
{
    Color overlayBackgroundColor(overlayBackgroundRed, overlayBackgroundGreen, overlayBackgroundBlue, overlayBackgroundAlpha);

    Vector<IntRect> rects = rectsForTextMatches();

    // Draw the background.
    graphicsContext.fillRect(dirtyRect, overlayBackgroundColor, ColorSpaceSRGB);

    {
        GraphicsContextStateSaver stateSaver(graphicsContext);

        graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, Color::black, ColorSpaceSRGB);
        graphicsContext.setFillColor(Color::white, ColorSpaceSRGB);

        // Draw white frames around the holes.
        for (size_t i = 0; i < rects.size(); ++i) {
            IntRect whiteFrameRect = rects[i];
            whiteFrameRect.inflate(1);
            graphicsContext.fillRect(whiteFrameRect);
        }
    }

    // Clear out the holes.
    for (size_t i = 0; i < rects.size(); ++i)
        graphicsContext.clearRect(rects[i]);

    if (!m_isShowingFindIndicator)
        return;

    if (Frame* selectedFrame = frameWithSelection(m_webPage->corePage())) {
        IntRect findIndicatorRect = selectedFrame->view()->contentsToWindow(enclosingIntRect(selectedFrame->selection().selectionBounds()));

        if (findIndicatorRect != m_findIndicatorRect)
            hideFindIndicator();
    }
}
Esempio n. 14
0
GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* oldContext)
{
    ASSERT(m_renderLayer);
    
    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
    filter->allocateBackingStoreIfNeeded();
    // Paint into the context that represents the SourceGraphic of the filter.
    GraphicsContext* sourceGraphicsContext = filter->inputContext();
    if (!sourceGraphicsContext || !isFilterSizeValid(filter->filterRegion())) {
        // Disable the filters and continue.
        m_haveFilterEffect = false;
        return oldContext;
    }
    
    m_savedGraphicsContext = oldContext;
    
    // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
    sourceGraphicsContext->save();
    sourceGraphicsContext->translate(-m_paintOffset.x(), -m_paintOffset.y());
    sourceGraphicsContext->clearRect(m_repaintRect);
    sourceGraphicsContext->clip(m_repaintRect);
    
    return sourceGraphicsContext;
}
Esempio n. 15
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;
}
Esempio n. 16
0
void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, const IntSize& shadowTemplateSize)
{
    const float roundedRadius = ceilf(m_blurRadius);
    const float twiceRadius = roundedRadius * 2;

    // Size of the tiling side.
    const int templateSideLength = 1;

    m_layerImage = ScratchBuffer::shared().getScratchBuffer(shadowTemplateSize);

    // Draw shadow into a new ImageBuffer.
    GraphicsContext* shadowContext = m_layerImage->context();
    shadowContext->save();
    
    shadowContext->clearRect(FloatRect(0, 0, shadowTemplateSize.width(), shadowTemplateSize.height()));

    // Draw the rectangle.
    FloatRect templateRect = FloatRect(roundedRadius, roundedRadius, shadowTemplateSize.width() - twiceRadius, shadowTemplateSize.height() - twiceRadius);
    Path path;
    path.addRoundedRect(templateRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());

    shadowContext->setFillColor(Color(.0f, .0f, .0f, 1.f), ColorSpaceDeviceRGB);
    shadowContext->fillPath(path);

    // Blur the image.
    {
        IntRect blurRect(IntPoint(), shadowTemplateSize);
        RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
        blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
        m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
    }

    // Mask the image with the shadow color.
    shadowContext->setCompositeOperation(CompositeSourceIn);
    shadowContext->setFillColor(m_color, m_colorSpace);
    shadowContext->fillRect(FloatRect(0, 0, shadowTemplateSize.width(), shadowTemplateSize.height()));
    
    shadowContext->restore();

    FloatRect shadowRect = shadowedRect;
    shadowRect.inflate(roundedRadius); // FIXME: duplicating code with calculateLayerBoundingRect.
    shadowRect.move(m_offset.width(), m_offset.height());

    // Fill the internal part of the shadow.
    shadowRect.inflate(-twiceRadius);
    if (!shadowRect.isEmpty()) {
        graphicsContext->save();
        
        path.clear();
        path.addRoundedRect(shadowRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());

        graphicsContext->setFillColor(m_color, m_colorSpace);
        graphicsContext->fillPath(path);
        
        graphicsContext->restore();
    }
    shadowRect.inflate(twiceRadius);

    // Note that drawing the ImageBuffer is faster than creating a Image and drawing that,
    // because ImageBuffer::draw() knows that it doesn't have to copy the image bits.
        
    // Draw top side.
    FloatRect tileRect = FloatRect(twiceRadius + radii.topLeft().width(), 0, templateSideLength, twiceRadius);
    FloatRect destRect = tileRect;
    destRect.move(shadowRect.x(), shadowRect.y());
    destRect.setWidth(shadowRect.width() - radii.topLeft().width() - radii.topRight().width() - roundedRadius * 4);
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the bottom side.
    tileRect = FloatRect(twiceRadius + radii.bottomLeft().width(), shadowTemplateSize.height() - twiceRadius, templateSideLength, twiceRadius);
    destRect = tileRect;
    destRect.move(shadowRect.x(), shadowRect.y() + twiceRadius + shadowedRect.height() - shadowTemplateSize.height());
    destRect.setWidth(shadowRect.width() - radii.bottomLeft().width() - radii.bottomRight().width() - roundedRadius * 4);
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the right side.
    tileRect = FloatRect(shadowTemplateSize.width() - twiceRadius, twiceRadius + radii.topRight().height(), twiceRadius, templateSideLength);
    destRect = tileRect;
    destRect.move(shadowRect.x() + twiceRadius + shadowedRect.width() - shadowTemplateSize.width(), shadowRect.y());
    destRect.setHeight(shadowRect.height() - radii.topRight().height() - radii.bottomRight().height() - roundedRadius * 4);
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the left side.
    tileRect = FloatRect(0, twiceRadius + radii.topLeft().height(), twiceRadius, templateSideLength);
    destRect = tileRect;
    destRect.move(shadowRect.x(), shadowRect.y());
    destRect.setHeight(shadowRect.height() - radii.topLeft().height() - radii.bottomLeft().height() - roundedRadius * 4);
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the top left corner.
    tileRect = FloatRect(0, 0, twiceRadius + radii.topLeft().width(), twiceRadius + radii.topLeft().height());
    destRect = tileRect;
    destRect.move(shadowRect.x(), shadowRect.y());
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the top right corner.
    tileRect = FloatRect(shadowTemplateSize.width() - twiceRadius - radii.topRight().width(), 0, twiceRadius + radii.topRight().width(),
                         twiceRadius + radii.topRight().height());
    destRect = tileRect;
    destRect.move(shadowRect.x() + shadowedRect.width() - shadowTemplateSize.width() + twiceRadius, shadowRect.y());
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the bottom right corner.
    tileRect = FloatRect(shadowTemplateSize.width() - twiceRadius - radii.bottomRight().width(),
                         shadowTemplateSize.height() - twiceRadius - radii.bottomRight().height(),
                         twiceRadius + radii.bottomRight().width(), twiceRadius + radii.bottomRight().height());
    destRect = tileRect;
    destRect.move(shadowRect.x() + shadowedRect.width() - shadowTemplateSize.width() + twiceRadius,
                  shadowRect.y() + shadowedRect.height() - shadowTemplateSize.height() + twiceRadius);
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    // Draw the bottom left corner.
    tileRect = FloatRect(0, shadowTemplateSize.height() - twiceRadius - radii.bottomLeft().height(),
                         twiceRadius + radii.bottomLeft().width(), twiceRadius + radii.bottomLeft().height());
    destRect = tileRect;
    destRect.move(shadowRect.x(), shadowRect.y() + shadowedRect.height() - shadowTemplateSize.height() + twiceRadius);
    graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect);

    m_layerImage = 0;
    // Schedule a purge of the scratch buffer.
    ScratchBuffer::shared().scheduleScratchBufferPurge();
}
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;
}
Esempio n. 18
0
void ClearRect::apply(GraphicsContext& context) const
{
    context.clearRect(m_rect);
}
Esempio n. 19
0
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    // 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(adoptPtr(new FilterData));
    FloatRect targetBoundingBox = object->objectBoundingBox();

    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
    filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits(), targetBoundingBox);
    if (filterData->boundaries.isEmpty())
        return false;

    // Determine absolute transformation matrix for filter. 
    AffineTransform absoluteTransform;
    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
    if (!absoluteTransform.isInvertible())
        return false;

    // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
    filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);

    // Determine absolute boundaries of the filter and the drawing region.
    FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
    FloatRect drawingRegion = object->strokeBoundingBox();
    drawingRegion.intersect(filterData->boundaries);
    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion);

    // Create the SVGFilter object.
    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);

    // Create all relevant filter primitives.
    filterData->builder = buildPrimitives(filterData->filter.get());
    if (!filterData->builder)
        return false;

    // Calculate the scale factor for the use of filterRes.
    // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
    FloatSize scale(1, 1);
    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
        scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width());
        scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height());
    }

    if (scale.isEmpty())
        return false;

    // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
    FloatRect tempSourceRect = absoluteDrawingRegion;
    tempSourceRect.scale(scale.width(), scale.height());
    fitsInMaximumImageSize(tempSourceRect.size(), scale);

    // Set the scale level in SVGFilter.
    filterData->filter->setFilterResolution(scale);

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    if (!lastEffect)
        return false;

    RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
    FloatRect subRegion = lastEffect->maxEffectRect();
    // At least one FilterEffect has a too big image size,
    // recalculate the effect sizes with new scale factors.
    if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
        filterData->filter->setFilterResolution(scale);
        RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
    }

    // If the drawingRegion is empty, we have something like <g filter=".."/>.
    // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
    if (drawingRegion.isEmpty()) {
        ASSERT(!m_filter.contains(object));
        filterData->savedContext = context;
        m_filter.set(object, filterData.leakPtr());
        return false;
    }

    absoluteDrawingRegion.scale(scale.width(), scale.height());

    OwnPtr<ImageBuffer> sourceGraphic;
    if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, ColorSpaceLinearRGB)) {
        ASSERT(!m_filter.contains(object));
        filterData->savedContext = context;
        m_filter.set(object, filterData.leakPtr());
        return false;
    }
    
    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
    ASSERT(sourceGraphicContext);
  
    sourceGraphicContext->translate(-absoluteDrawingRegion.x(), -absoluteDrawingRegion.y());
    if (scale.width() != 1 || scale.height() != 1)
        sourceGraphicContext->scale(scale);

    sourceGraphicContext->concatCTM(filterData->shearFreeAbsoluteTransform);
    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), absoluteDrawingRegion.size()));
    filterData->sourceGraphicBuffer = sourceGraphic.release();
    filterData->savedContext = context;

    context = sourceGraphicContext;

    ASSERT(!m_filter.contains(object));
    m_filter.set(object, filterData.leakPtr());

    return true;
}