FloatRect FEImage::determineAbsolutePaintRect(const FloatRect& originalRequestedRect) { RenderObject* renderer = referencedRenderer(); if (!m_image && !renderer) return FloatRect(); FloatRect requestedRect = originalRequestedRect; if (clipsToBounds()) requestedRect.intersect(maxEffectRect()); FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion()); FloatRect srcRect; if (renderer) { srcRect = getRendererRepaintRect(renderer); SVGElement* contextNode = toSVGElement(renderer->node()); if (contextNode->hasRelativeLengths()) { // FIXME: This fixes relative lengths but breaks non-relative ones (see crbug/260709). SVGLengthContext lengthContext(contextNode); FloatSize viewportSize; if (lengthContext.determineViewport(viewportSize)) { srcRect = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect).mapRect(srcRect); } } else { srcRect = filter()->mapLocalRectToAbsoluteRect(srcRect); srcRect.move(destRect.x(), destRect.y()); } destRect.intersect(srcRect); } else { srcRect = FloatRect(FloatPoint(), m_image->size()); m_preserveAspectRatio->transformRect(destRect, srcRect); } destRect.intersect(requestedRect); addAbsolutePaintRect(destRect); return destRect; }
void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImageOrientation, ImageClampingMode clampMode) { TRACE_EVENT0("skia", "BitmapImage::draw"); RefPtr<SkImage> image = imageForCurrentFrame(); if (!image) return; // It's too early and we don't have an image yet. FloatRect adjustedSrcRect = srcRect; adjustedSrcRect.intersect(FloatRect(0, 0, image->width(), image->height())); if (adjustedSrcRect.isEmpty() || dstRect.isEmpty()) return; // Nothing to draw. ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); int initialSaveCount = canvas->getSaveCount(); FloatRect adjustedDstRect = dstRect; if (orientation != DefaultImageOrientation) { canvas->save(); // ImageOrientation expects the origin to be at (0, 0) canvas->translate(adjustedDstRect.x(), adjustedDstRect.y()); adjustedDstRect.setLocation(FloatPoint()); canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefault(adjustedDstRect.size()))); if (orientation.usesWidthAsHeight()) { // The destination rect will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. adjustedDstRect = FloatRect(adjustedDstRect.x(), adjustedDstRect.y(), adjustedDstRect.height(), adjustedDstRect.width()); } } SkRect skSrcRect = adjustedSrcRect; canvas->drawImageRect(image.get(), skSrcRect, adjustedDstRect, &paint, WebCoreClampingModeToSkiaRectConstraint(clampMode)); canvas->restoreToCount(initialSaveCount); if (currentFrameIsLazyDecoded()) PlatformInstrumentation::didDrawLazyPixelRef(image->uniqueID()); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); startAnimation(); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, BlendMode, RespectImageOrientationEnum shouldRespectImageOrientation) { // Spin the animation to the correct frame before we try to draw it, so we // don't draw an old frame and then immediately need to draw a newer one, // causing flicker and wasting CPU. startAnimation(); RefPtr<NativeImageSkia> bm = nativeImageForCurrentFrame(); if (!bm) return; // It's too early and we don't have an image yet. FloatRect normDstRect = normalizeRect(dstRect); FloatRect normSrcRect = normalizeRect(srcRect); normSrcRect.intersect(FloatRect(0, 0, bm->bitmap().width(), bm->bitmap().height())); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); GraphicsContextStateSaver saveContext(*ctxt, false); if (orientation != DefaultImageOrientation) { saveContext.save(); // ImageOrientation expects the origin to be at (0, 0) ctxt->translate(normDstRect.x(), normDstRect.y()); normDstRect.setLocation(FloatPoint()); ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rect will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRect.height(), normDstRect.width()); } } paintSkBitmap(ctxt->platformContext(), *bm, normSrcRect, normDstRect, WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); }
void FEImage::determineAbsolutePaintRect() { FloatRect paintRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion()); FloatRect srcRect; if (m_image) { srcRect.setSize(m_image->size()); m_preserveAspectRatio.transformRect(paintRect, srcRect); } else if (RenderElement* renderer = referencedRenderer()) srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); if (clipsToBounds()) paintRect.intersect(maxEffectRect()); else paintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(paintRect)); }
FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlags flags) { Filter* filter = this->filter(); ASSERT(filter); // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect. FloatRect subregion; if (unsigned numberOfInputEffects = inputEffects().size()) { subregion = inputEffect(0)->determineFilterPrimitiveSubregion(flags); for (unsigned i = 1; i < numberOfInputEffects; ++i) subregion.unite(inputEffect(i)->determineFilterPrimitiveSubregion(flags)); } else { subregion = filter->filterRegion(); } // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>. if (filterEffectType() == FilterEffectTypeTile) subregion = filter->filterRegion(); if (flags & MapRectForward) { // mapRect works on absolute rectangles. subregion = filter->mapAbsoluteRectToLocalRect(mapRect( filter->mapLocalRectToAbsoluteRect(subregion))); } FloatRect boundaries = effectBoundaries(); if (hasX()) subregion.setX(boundaries.x()); if (hasY()) subregion.setY(boundaries.y()); if (hasWidth()) subregion.setWidth(boundaries.width()); if (hasHeight()) subregion.setHeight(boundaries.height()); setFilterPrimitiveSubregion(subregion); FloatRect absoluteSubregion = filter->mapLocalRectToAbsoluteRect(subregion); // Clip every filter effect to the filter region. if (flags & ClipToFilterRegion) { absoluteSubregion.intersect(filter->absoluteFilterRegion()); } setMaxEffectRect(absoluteSubregion); return subregion; }
LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect) { if (hasCustomShaderFilter()) { // When we have at least a custom shader in the chain, we need to compute the whole source image, because the shader can // reference any pixel and we cannot control that. return filterBoxRect; } // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect". FloatRect rectForRepaint = dirtyRect; rectForRepaint.move(-filterBoxRect.location().x(), -filterBoxRect.location().y()); float inf = std::numeric_limits<float>::infinity(); FloatRect clipRect = FloatRect(FloatPoint(-inf, -inf), FloatSize(inf, inf)); rectForRepaint = lastEffect()->getSourceRect(rectForRepaint, clipRect); rectForRepaint.move(filterBoxRect.location().x(), filterBoxRect.location().y()); rectForRepaint.intersect(filterBoxRect); return LayoutRect(rectForRepaint); }
void HTMLCanvasElement::didDraw(const FloatRect& rect) { clearCopiedImage(); if (RenderBox* ro = renderBox()) { FloatRect destRect = ro->contentBoxRect(); FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect); r.intersect(destRect); if (r.isEmpty() || m_dirtyRect.contains(r)) return; m_dirtyRect.unite(r); ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } notifyObserversCanvasChanged(rect); }
void FEGaussianBlur::determineAbsolutePaintRect() { FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); if (clipsToBounds()) absolutePaintRect.intersect(maxEffectRect()); else absolutePaintRect.unite(maxEffectRect()); unsigned kernelSizeX = 0; unsigned kernelSizeY = 0; calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY); // We take the half kernel size and multiply it with three, because we run box blur three times. absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f); absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const { // Apply our local transforms (except for x/y translation), then our shadow, // and then call RenderBox's method to handle all the normal CSS Box model bits repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect); const SVGRenderStyle* svgStyle = style()->svgStyle(); if (const ShadowData* shadow = svgStyle->shadow()) shadow->adjustRectForShadow(repaintRect); // Apply initial viewport clip - not affected by overflow settings repaintRect.intersect(pixelSnappedBorderBoxRect()); LayoutRect rect = enclosingIntRect(repaintRect); RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed); repaintRect = rect; }
void StaticBitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum, ImageClampingMode clampMode) { FloatRect adjustedSrcRect = srcRect; adjustedSrcRect.intersect(SkRect::Make(m_image->bounds())); if (dstRect.isEmpty() || adjustedSrcRect.isEmpty()) return; // Nothing to draw. canvas->drawImageRect(m_image.get(), adjustedSrcRect, dstRect, &paint, WebCoreClampingModeToSkiaRectConstraint(clampMode)); if (ImageObserver* observer = getImageObserver()) observer->didDraw(this); }
void HTMLCanvasElement::willDraw(const FloatRect& rect) { CanvasSurface::willDraw(rect); if (RenderBox* ro = renderBox()) { FloatRect destRect = ro->contentBoxRect(); FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect); r.intersect(destRect); if (m_dirtyRect.contains(r)) return; m_dirtyRect.unite(r); ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } if (m_observer) m_observer->canvasChanged(this, rect); }
bool RenderSVGResourceFilter::prepareEffect(RenderObject* object, GraphicsContext*& context) { ASSERT(object); ASSERT(context); clearInvalidationMask(); if (m_filter.contains(object)) { FilterData* filterData = m_filter.get(object); if (filterData->state == FilterData::PaintingSource) filterData->state = FilterData::CycleDetected; return false; // Already built, or we're in a cycle. Regardless, just do nothing more now. } OwnPtrWillBeRawPtr<FilterData> filterData = FilterData::create(); FloatRect targetBoundingBox = object->objectBoundingBox(); SVGFilterElement* filterElement = toSVGFilterElement(element()); filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox); if (filterData->boundaries.isEmpty()) return false; // Create the SVGFilter object. FloatRect drawingRegion = object->strokeBoundingBox(); drawingRegion.intersect(filterData->boundaries); bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; filterData->filter = SVGFilter::create(enclosingIntRect(drawingRegion), targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode); // Create all relevant filter primitives. filterData->builder = buildPrimitives(filterData->filter.get()); if (!filterData->builder) return false; FilterEffect* lastEffect = filterData->builder->lastEffect(); if (!lastEffect) return false; lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion); FilterData* data = filterData.get(); m_filter.set(object, filterData.release()); beginDeferredFilter(context, data); return true; }
void HTMLCanvasElement::didDraw(const FloatRect& rect) { m_copiedImage.clear(); // Clear our image snapshot if we have one. if (RenderBox* ro = renderBox()) { FloatRect destRect = ro->contentBoxRect(); FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect); r.intersect(destRect); if (r.isEmpty() || m_dirtyRect.contains(r)) return; m_dirtyRect.unite(r); ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } HashSet<CanvasObserver*>::iterator end = m_observers.end(); for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) (*it)->canvasChanged(this, rect); }
FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect) { SVGFilter* filter = static_cast<SVGFilter*>(effect->filter()); ASSERT(filter); // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect. FloatRect subregion; if (unsigned numberOfInputEffects = effect->inputEffects().size()) { subregion = determineFilterPrimitiveSubregion(effect->inputEffect(0)); for (unsigned i = 1; i < numberOfInputEffects; ++i) subregion.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i))); } else subregion = filter->filterRegionInUserSpace(); // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>. if (effect->filterEffectType() == FilterEffectTypeTile) subregion = filter->filterRegionInUserSpace(); FloatRect effectBoundaries = effect->effectBoundaries(); if (effect->hasX()) subregion.setX(effectBoundaries.x()); if (effect->hasY()) subregion.setY(effectBoundaries.y()); if (effect->hasWidth()) subregion.setWidth(effectBoundaries.width()); if (effect->hasHeight()) subregion.setHeight(effectBoundaries.height()); effect->setFilterPrimitiveSubregion(subregion); FloatRect absoluteSubregion = filter->absoluteTransform().mapRect(subregion); FloatSize filterResolution = filter->filterResolution(); absoluteSubregion.scale(filterResolution.width(), filterResolution.height()); // Clip every filter effect to the filter region. FloatRect absoluteScaledFilterRegion = filter->filterRegion(); absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height()); absoluteSubregion.intersect(absoluteScaledFilterRegion); effect->setMaxEffectRect(absoluteSubregion); return subregion; }
void SVGFilter::calculateEffectSubRegion(FilterEffect* effect) { FloatRect subRegionBBox = effect->effectBoundaries(); FloatRect useBBox = effect->unionOfChildEffectSubregions(); FloatRect newSubRegion = subRegionBBox; if (m_effectBBoxMode) { newSubRegion = useBBox; if (effect->hasX()) newSubRegion.setX(m_itemBox.x() + subRegionBBox.x() * m_itemBox.width()); if (effect->hasY()) newSubRegion.setY(m_itemBox.y() + subRegionBBox.y() * m_itemBox.height()); if (effect->hasWidth()) newSubRegion.setWidth(subRegionBBox.width() * m_itemBox.width()); if (effect->hasHeight()) newSubRegion.setHeight(subRegionBBox.height() * m_itemBox.height()); } else { if (!effect->hasX()) newSubRegion.setX(useBBox.x()); if (!effect->hasY()) newSubRegion.setY(useBBox.y()); if (!effect->hasWidth()) newSubRegion.setWidth(useBBox.width()); if (!effect->hasHeight()) newSubRegion.setHeight(useBBox.height()); } // clip every filter effect to the filter region newSubRegion.intersect(m_filterRect); effect->setSubRegion(newSubRegion); newSubRegion.scale(filterResolution().width(), filterResolution().height()); effect->setScaledSubRegion(newSubRegion); m_maxImageSize = m_maxImageSize.expandedTo(newSubRegion.size()); }
FloatRect screenAvailableRect(Widget* widget) { if (!widget) return FloatRect(); #if PLATFORM(X11) GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()); if (!container) return FloatRect(); if (!gtk_widget_get_realized(container)) return screenRect(widget); GdkDrawable* rootWindow = GDK_DRAWABLE(gtk_widget_get_root_window(container)); GdkDisplay* display = gdk_drawable_get_display(rootWindow); Atom xproperty = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WORKAREA"); Atom retType; int retFormat; long *workAreaPos = NULL; unsigned long retNItems; unsigned long retAfter; int xRes = XGetWindowProperty(GDK_DISPLAY_XDISPLAY(display), GDK_WINDOW_XWINDOW(rootWindow), xproperty, 0, 4, FALSE, XA_CARDINAL, &retType, &retFormat, &retNItems, &retAfter, (guchar**)&workAreaPos); FloatRect rect; if (xRes == Success && workAreaPos != NULL && retType == XA_CARDINAL && retNItems == 4 && retFormat == 32) { rect = FloatRect(workAreaPos[0], workAreaPos[1], workAreaPos[2], workAreaPos[3]); // rect contains the available space in the whole screen not just in the monitor // containing the widget, so we intersect it with the monitor rectangle. rect.intersect(screenRect(widget)); } else rect = screenRect(widget); if (workAreaPos) XFree(workAreaPos); return rect; #else return screenRect(widget); #endif }
void FEDropShadow::determineAbsolutePaintRect() { Filter* filter = this->filter(); ASSERT(filter); FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); FloatRect absoluteOffsetPaintRect(absolutePaintRect); absoluteOffsetPaintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); absolutePaintRect.unite(absoluteOffsetPaintRect); absolutePaintRect.intersect(maxEffectRect()); unsigned kernelSizeX = 0; unsigned kernelSizeY = 0; FEGaussianBlur::calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY); // We take the half kernel size and multiply it with three, because we run box blur three times. absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f); absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
void HTMLCanvasElement::didDraw(const FloatRect& rect) { clearCopiedImage(); FloatRect dirtyRect = rect; if (RenderBox* ro = renderBox()) { FloatRect destRect = ro->contentBoxRect(); // Inflate dirty rect to cover antialiasing on image buffers. if (drawingContext() && drawingContext()->shouldAntialias()) dirtyRect.inflate(1); FloatRect r = mapRect(dirtyRect, FloatRect(0, 0, size().width(), size().height()), destRect); r.intersect(destRect); if (r.isEmpty() || m_dirtyRect.contains(r)) return; m_dirtyRect.unite(r); ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } notifyObserversCanvasChanged(dirtyRect); }
FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBoundingBox) { if (m_maskBoundaries.isEmpty()) calculateMaskContentRepaintRect(); SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); if (!maskElement) return FloatRect(); FloatRect maskRect = m_maskBoundaries; if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { AffineTransform transform; transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); maskRect = transform.mapRect(maskRect); } maskRect.intersect(maskElement->maskBoundingBox(objectBoundingBox)); return maskRect; }
void StaticBitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum, ImageClampingMode clampMode) { ASSERT(dstRect.width() >= 0 && dstRect.height() >= 0); ASSERT(srcRect.width() >= 0 && srcRect.height() >= 0); FloatRect adjustedSrcRect = srcRect; adjustedSrcRect.intersect(FloatRect(0, 0, m_image->width(), m_image->height())); if (adjustedSrcRect.isEmpty() || dstRect.isEmpty()) return; // Nothing to draw. ASSERT(adjustedSrcRect.width() <= m_image->width() && adjustedSrcRect.height() <= m_image->height()); SkRect srcSkRect = adjustedSrcRect; canvas->drawImageRect(m_image.get(), srcSkRect, dstRect, &paint, WebCoreClampingModeToSkiaRectConstraint(clampMode)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); }
void SelectionOverlay::paintContents(const GraphicsLayer* layer, GraphicsContext& c, GraphicsLayerPaintingPhase, const IntRect& inClip) { if (!layer->platformLayer()->superlayer()) return; Selection::iterator it = m_selection.find(layer->platformLayer()->superlayer()->owner()); if (it == m_selection.end()) return; const Vector<WebCore::FloatQuad>& quads = it->value; GraphicsLayer* parent = it->key; IntRect clip(inClip); clip.move(parent->offsetFromRenderer().width(), parent->offsetFromRenderer().height()); c.save(); c.translate(-parent->offsetFromRenderer().width(), -parent->offsetFromRenderer().height()); Color color = RenderTheme::defaultTheme()->activeSelectionBackgroundColor(); c.setFillColor(color, ColorSpaceDeviceRGB); for (unsigned i = 0; i < quads.size(); ++i) { FloatRect rectToPaint = quads[i].boundingBox(); // Selection on non-composited sub-frames need to be adjusted. if (!m_page->focusedOrMainFrame()->contentRenderer()->isComposited()) { WebCore::IntPoint framePosition = m_page->frameOffset(m_page->focusedOrMainFrame()); rectToPaint.move(framePosition.x(), framePosition.y()); } rectToPaint.intersect(clip); if (rectToPaint.isEmpty()) continue; c.fillRect(rectToPaint); } c.restore(); }
FloatRect RenderSVGRoot::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const { // Apply our local transforms (except for x/y translation), then our shadow, // and then call RenderBox's method to handle all the normal CSS Box model bits FloatRect adjustedRect = m_localToBorderBoxTransform.mapRect(repaintRect); const SVGRenderStyle& svgStyle = style().svgStyle(); if (const ShadowData* shadow = svgStyle.shadow()) shadow->adjustRectForShadow(adjustedRect); // Apply initial viewport clip if (shouldApplyViewportClip()) adjustedRect.intersect(snappedIntRect(borderBoxRect())); if (m_hasBoxDecorations || hasRenderOverflow()) { // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect()); adjustedRect.unite(decoratedRepaintRect); } return RenderReplaced::computeRectForRepaint(enclosingIntRect(adjustedRect), repaintContainer, {fixed, false}); }
void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp) { FloatRect normDstRect = normalizeRect(dstRect); FloatRect normSrcRect = normalizeRect(srcRect); normSrcRect.intersect(FloatRect(0, 0, m_nativeImage.bitmap().width(), m_nativeImage.bitmap().height())); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. paintSkBitmap(ctxt->platformContext(), m_nativeImage, normSrcRect, normDstRect, WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); }
void FEDropShadow::determineAbsolutePaintRect() { Filter& filter = this->filter(); FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); FloatRect absoluteOffsetPaintRect(absolutePaintRect); absoluteOffsetPaintRect.move(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy)); absolutePaintRect.unite(absoluteOffsetPaintRect); IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY)); // We take the half kernel size and multiply it with three, because we run box blur three times. absolutePaintRect.inflateX(3 * kernelSize.width() * 0.5f); absolutePaintRect.inflateY(3 * kernelSize.height() * 0.5f); if (clipsToBounds()) absolutePaintRect.intersect(maxEffectRect()); else absolutePaintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
void FEGaussianBlur::determineAbsolutePaintRect() { IntSize kernelSize = calculateKernelSize(filter(), FloatPoint(m_stdX, m_stdY)); FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); // Edge modes other than 'none' do not inflate the affected paint rect. if (m_edgeMode != EDGEMODE_NONE) { setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); return; } // We take the half kernel size and multiply it with three, because we run box blur three times. absolutePaintRect.inflateX(3 * kernelSize.width() * 0.5f); absolutePaintRect.inflateY(3 * kernelSize.height() * 0.5f); if (clipsToBounds()) absolutePaintRect.intersect(maxEffectRect()); else absolutePaintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
FloatRect RenderSVGResourceMasker::resourceBoundingBox(const RenderObject& object) { FloatRect objectBoundingBox = object.objectBoundingBox(); FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(&maskElement(), maskElement().maskUnits(), objectBoundingBox); // Resource was not layouted yet. Give back clipping rect of the mask. if (selfNeedsLayout()) return maskBoundaries; if (m_maskContentBoundaries.isEmpty()) calculateMaskContentRepaintRect(); FloatRect maskRect = m_maskContentBoundaries; if (maskElement().maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { AffineTransform transform; transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); maskRect = transform.mapRect(maskRect); } maskRect.intersect(maskBoundaries); return maskRect; }
void HTMLCanvasElement::didDraw(const FloatRect& rect) { m_copiedImage.clear(); // Clear our image snapshot if we have one. if (RenderBox* ro = renderBox()) { FloatRect destRect = ro->contentBoxRect(); FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect); r.intersect(destRect); if (r.isEmpty() || m_dirtyRect.contains(r)) return; m_dirtyRect.unite(r); #if PLATFORM(ANDROID) // We handle invals ourselves and don't want webkit to repaint if we // have put the canvas on a layer if (!ro->hasLayer()) #endif ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } HashSet<CanvasObserver*>::iterator end = m_observers.end(); for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) (*it)->canvasChanged(this, rect); }
void TileGrid::setTileNeedsDisplayInRect(const TileIndex& tileIndex, TileInfo& tileInfo, const IntRect& repaintRectInTileCoords, const IntRect& coverageRectInTileCoords) { PlatformCALayer* tileLayer = tileInfo.layer.get(); IntRect tileRect = rectForTileIndex(tileIndex); FloatRect tileRepaintRect = tileRect; tileRepaintRect.intersect(repaintRectInTileCoords); if (tileRepaintRect.isEmpty()) return; tileRepaintRect.moveBy(-tileRect.location()); // We could test for intersection with the visible rect. This would reduce painting yet more, // but may make scrolling stale tiles into view more frequent. if (tileRect.intersects(coverageRectInTileCoords) && tileLayer->superlayer()) { tileLayer->setNeedsDisplayInRect(tileRepaintRect); if (m_controller.rootLayer().owner()->platformCALayerShowRepaintCounter(0)) { FloatRect indicatorRect(0, 0, 52, 27); tileLayer->setNeedsDisplayInRect(indicatorRect); } } else tileInfo.hasStaleContent = true; }
void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) { FloatRect objectBoundingBox = object->objectBoundingBox(); // Mask rect clipped with clippingBoundingBox and filterBoundingBox as long as they are present. maskerData->maskRect = object->repaintRectInLocalCoordinates(); if (maskerData->maskRect.isEmpty()) { maskerData->emptyMask = true; return; } if (m_maskBoundaries.isEmpty()) calculateMaskContentRepaintRect(); FloatRect repaintRect = m_maskBoundaries; AffineTransform contextTransform; // We need to scale repaintRect for objectBoundingBox to get the drawing area. if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); FloatPoint contextAdjustment = repaintRect.location(); repaintRect = contextTransform.mapRect(repaintRect); repaintRect.move(objectBoundingBox.x(), objectBoundingBox.y()); contextTransform.translate(-contextAdjustment.x(), -contextAdjustment.y()); } repaintRect.intersect(maskerData->maskRect); maskerData->maskRect = repaintRect; IntRect maskImageRect = enclosingIntRect(maskerData->maskRect); maskImageRect.setLocation(IntPoint()); // Don't create ImageBuffers with image size of 0 if (maskImageRect.isEmpty()) { maskerData->emptyMask = true; return; } // FIXME: This changes color space to linearRGB, the default color space // for masking operations in SVG. We need a switch for the other color-space // attribute values sRGB, inherit and auto. maskerData->maskImage = ImageBuffer::create(maskImageRect.size(), LinearRGB); if (!maskerData->maskImage) return; GraphicsContext* maskImageContext = maskerData->maskImage->context(); ASSERT(maskImageContext); maskImageContext->save(); if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) maskImageContext->translate(-maskerData->maskRect.x(), -maskerData->maskRect.y()); maskImageContext->concatCTM(contextTransform); // draw the content into the ImageBuffer for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) { RenderObject* renderer = node->renderer(); if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer) continue; RenderStyle* style = renderer->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) continue; renderSubtreeToImage(maskerData->maskImage.get(), renderer); } maskImageContext->restore(); // create the luminance mask RefPtr<ImageData> imageData(maskerData->maskImage->getUnmultipliedImageData(maskImageRect)); CanvasPixelArray* srcPixelArray(imageData->data()); for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) { unsigned char a = srcPixelArray->get(pixelOffset + 3); if (!a) continue; unsigned char r = srcPixelArray->get(pixelOffset); unsigned char g = srcPixelArray->get(pixelOffset + 1); unsigned char b = srcPixelArray->get(pixelOffset + 2); double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0); srcPixelArray->set(pixelOffset + 3, luma); } maskerData->maskImage->putUnmultipliedImageData(imageData.get(), maskImageRect, IntPoint()); }
FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect, SVGFilter* filter) { FloatRect uniteRect; FloatRect subregionBoundingBox = effect->effectBoundaries(); FloatRect subregion = subregionBoundingBox; if (effect->filterEffectType() != FilterEffectTypeTile) { // FETurbulence, FEImage and FEFlood don't have input effects, take the filter region as unite rect. if (unsigned numberOfInputEffects = effect->inputEffects().size()) { for (unsigned i = 0; i < numberOfInputEffects; ++i) uniteRect.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i), filter)); } else uniteRect = filter->filterRegionInUserSpace(); } else { determineFilterPrimitiveSubregion(effect->inputEffect(0), filter); uniteRect = filter->filterRegionInUserSpace(); } if (filter->effectBoundingBoxMode()) { subregion = uniteRect; // Avoid the calling of a virtual method several times. FloatRect targetBoundingBox = filter->targetBoundingBox(); if (effect->hasX()) subregion.setX(targetBoundingBox.x() + subregionBoundingBox.x() * targetBoundingBox.width()); if (effect->hasY()) subregion.setY(targetBoundingBox.y() + subregionBoundingBox.y() * targetBoundingBox.height()); if (effect->hasWidth()) subregion.setWidth(subregionBoundingBox.width() * targetBoundingBox.width()); if (effect->hasHeight()) subregion.setHeight(subregionBoundingBox.height() * targetBoundingBox.height()); } else { if (!effect->hasX()) subregion.setX(uniteRect.x()); if (!effect->hasY()) subregion.setY(uniteRect.y()); if (!effect->hasWidth()) subregion.setWidth(uniteRect.width()); if (!effect->hasHeight()) subregion.setHeight(uniteRect.height()); } effect->setFilterPrimitiveSubregion(subregion); FloatRect absoluteSubregion = filter->mapLocalRectToAbsoluteRect(subregion); FloatSize filterResolution = filter->filterResolution(); absoluteSubregion.scale(filterResolution.width(), filterResolution.height()); // FEImage needs the unclipped subregion in absolute coordinates to determine the correct // destination rect in combination with preserveAspectRatio. if (effect->filterEffectType() == FilterEffectTypeImage) reinterpret_cast<FEImage*>(effect)->setAbsoluteSubregion(absoluteSubregion); // Clip every filter effect to the filter region. FloatRect absoluteScaledFilterRegion = filter->filterRegion(); absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height()); absoluteSubregion.intersect(absoluteScaledFilterRegion); effect->setMaxEffectRect(enclosingIntRect(absoluteSubregion)); return subregion; }