Пример #1
0
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;
}
Пример #2
0
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();
}
Пример #3
0
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);
}
Пример #4
0
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));
}
Пример #5
0
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);
}
Пример #7
0
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);
}
Пример #8
0
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));
}
Пример #9
0
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;
}
Пример #10
0
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);
}
Пример #11
0
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);
}
Пример #12
0
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;
}
Пример #13
0
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);
}
Пример #14
0
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;
}
Пример #15
0
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
}
Пример #17
0
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));
}
Пример #18
0
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;
}
Пример #20
0
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);
}
Пример #21
0
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();
}
Пример #22
0
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});
}
Пример #23
0
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);
}
Пример #24
0
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));
}
Пример #25
0
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));
}
Пример #26
0
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);
}
Пример #28
0
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;
}