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; }
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; } }
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); }
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; }
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(); } }
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; }
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(); } }
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; }
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; }
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; }
void ClearRect::apply(GraphicsContext& context) const { context.clearRect(m_rect); }
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; }