Ejemplo n.º 1
0
FilterPainter::FilterPainter(DeprecatedPaintLayer& layer, GraphicsContext* context, const LayoutPoint& offsetFromRoot, const ClipRect& clipRect, DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags,
    LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed)
    : m_filterInProgress(false)
    , m_context(context)
    , m_layoutObject(layer.layoutObject())
{
    if (!layer.filterEffectBuilder() || !layer.paintsWithFilters())
        return;

    ASSERT(layer.filterInfo());

    SkiaImageFilterBuilder builder;
    RefPtrWillBeRawPtr<FilterEffect> lastEffect = layer.filterEffectBuilder()->lastEffect();
    lastEffect->determineFilterPrimitiveSubregion(MapRectForward);
    RefPtr<SkImageFilter> imageFilter = builder.build(lastEffect.get(), ColorSpaceDeviceRGB);
    if (!imageFilter)
        return;

    if (!rootRelativeBoundsComputed) {
        rootRelativeBounds = layer.physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
        rootRelativeBoundsComputed = true;
    }

    // We'll handle clipping to the dirty rect before filter rasterization.
    // Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets.
    // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.

    // Subsequent code should not clip to the dirty rect, since we've already
    // done it above, and doing it later will defeat the outsets.
    paintingInfo.clipToDirtyRect = false;

    if (clipRect.rect() != paintingInfo.paintDirtyRect || clipRect.hasRadius()) {
        m_clipRecorder = adoptPtr(new LayerClipRecorder(*context, *layer.layoutObject(), DisplayItem::ClipLayerFilter, clipRect, &paintingInfo, LayoutPoint(), paintFlags));
    }

    ASSERT(m_layoutObject);
    if (RuntimeEnabledFeatures::slimmingPaintEnabled()) {
        ASSERT(context->displayItemList());
        if (!context->displayItemList()->displayItemConstructionIsDisabled()) {
            FilterOperations filterOperations(layer.computeFilterOperations(m_layoutObject->styleRef()));
            OwnPtr<WebFilterOperations> webFilterOperations = adoptPtr(Platform::current()->compositorSupport()->createFilterOperations());
            builder.buildFilterOperations(filterOperations, webFilterOperations.get());
            // FIXME: It's possible to have empty WebFilterOperations here even
            // though the SkImageFilter produced above is non-null, since the
            // layer's FilterEffectBuilder can have a stale representation of
            // the layer's filter. See crbug.com/502026.
            if (webFilterOperations->isEmpty())
                return;
            context->displayItemList()->createAndAppend<BeginFilterDisplayItem>(*m_layoutObject, imageFilter, rootRelativeBounds, webFilterOperations.release());
        }
    } else {
        BeginFilterDisplayItem filterDisplayItem(*m_layoutObject, imageFilter, rootRelativeBounds);
        filterDisplayItem.replay(*context);
    }

    m_filterInProgress = true;
}
Ejemplo n.º 2
0
LayerClipRecorder::LayerClipRecorder(GraphicsContext& graphicsContext, const LayoutBoxModelObject& layoutObject, DisplayItem::Type clipType, const ClipRect& clipRect,
                                     const PaintLayerPaintingInfo* localPaintingInfo, const LayoutPoint& fragmentOffset, PaintLayerFlags paintFlags, BorderRadiusClippingRule rule)
    : m_graphicsContext(graphicsContext)
    , m_layoutObject(layoutObject)
    , m_clipType(clipType)
{
    IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect());
    Vector<FloatRoundedRect> roundedRects;
    if (localPaintingInfo && clipRect.hasRadius()) {
        collectRoundedRectClips(*layoutObject.layer(), *localPaintingInfo, graphicsContext, fragmentOffset, paintFlags, rule, roundedRects);
    }

    m_graphicsContext.paintController().createAndAppend<ClipDisplayItem>(layoutObject, m_clipType, snappedClipRect, roundedRects);
}
Ejemplo n.º 3
0
void RenderTreeAsText::writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* layer,
    const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
{
    // FIXME: Apply overflow to the root layer to not break every test. Complete hack. Sigh.
    LayoutRect paintDirtyRect(paintRect);
    if (rootLayer == layer) {
        paintDirtyRect.setWidth(max<LayoutUnit>(paintDirtyRect.width(), rootLayer->renderer()->layoutOverflowRect().maxX()));
        paintDirtyRect.setHeight(max<LayoutUnit>(paintDirtyRect.height(), rootLayer->renderer()->layoutOverflowRect().maxY()));
    }

    // Calculate the clip rects we should use.
    LayoutRect layerBounds;
    ClipRect damageRect;
    layer->clipper().calculateRects(ClipRectsContext(rootLayer, UncachedClipRects), paintDirtyRect, layerBounds, damageRect);

    // FIXME: Apply overflow to the root layer to not break every test. Complete hack. Sigh.
    if (rootLayer == layer)
        layerBounds.setSize(layer->size().expandedTo(pixelSnappedIntSize(layer->renderer()->maxLayoutOverflow(), LayoutPoint(0, 0))));

    // Ensure our lists are up-to-date.
    layer->stackingNode()->updateLayerListsIfNeeded();

    bool shouldPaint = (behavior & RenderAsTextShowAllLayers) ? true : layer->intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);

    if (shouldPaint)
        write(ts, *layer, layerBounds, damageRect.rect(), indent, behavior);

    if (Vector<RenderLayerStackingNode*>* normalFlowList = layer->stackingNode()->normalFlowList()) {
        int currIndent = indent;
        if (behavior & RenderAsTextShowLayerNesting) {
            writeIndent(ts, indent);
            ts << " normal flow list(" << normalFlowList->size() << ")\n";
            ++currIndent;
        }
        for (unsigned i = 0; i != normalFlowList->size(); ++i)
            writeLayers(ts, rootLayer, normalFlowList->at(i)->layer(), paintDirtyRect, currIndent, behavior);
    }

    if (Vector<RenderLayerStackingNode*>* posList = layer->stackingNode()->zOrderList()) {
        int currIndent = indent;
        if (behavior & RenderAsTextShowLayerNesting) {
            writeIndent(ts, indent);
            ts << " positive z-order list(" << posList->size() << ")\n";
            ++currIndent;
        }
        for (unsigned i = 0; i != posList->size(); ++i)
            writeLayers(ts, rootLayer, posList->at(i)->layer(), paintDirtyRect, currIndent, behavior);
    }
}
Ejemplo n.º 4
0
LayoutRect RenderLayerClipper::localClipRect() const
{
    // FIXME: border-radius not accounted for.
    RenderLayer* clippingRootLayer = clippingRootForPainting();
    LayoutRect layerBounds;
    ClipRect backgroundRect;
    ClipRectsContext context(clippingRootLayer, PaintingClipRects);
    calculateRects(context, PaintInfo::infiniteRect(), layerBounds, backgroundRect);

    LayoutRect clipRect = backgroundRect.rect();
    if (clipRect == PaintInfo::infiniteRect())
        return clipRect;

    LayoutPoint clippingRootOffset;
    m_renderer.layer()->convertToLayerCoords(clippingRootLayer, clippingRootOffset);
    clipRect.moveBy(-clippingRootOffset);

    return clipRect;
}
Ejemplo n.º 5
0
LayoutRect PaintLayerClipper::localClipRect(
    const PaintLayer* clippingRootLayer) const {
  ClipRectsContext context(clippingRootLayer, PaintingClipRects);
  if (m_geometryMapper) {
    ClipRect clipRect = applyOverflowClipToBackgroundRectWithGeometryMapper(
        context, clipRectWithGeometryMapper(context, false));

    // The rect now needs to be transformed to the local space of this
    // PaintLayer.
    bool success = false;
    FloatRect clippedRectInLocalSpace =
        m_geometryMapper->mapRectToDestinationSpace(
            FloatRect(clipRect.rect()), clippingRootLayer->layoutObject()
                                            ->paintProperties()
                                            ->localBorderBoxProperties()
                                            ->propertyTreeState,
            m_layer.layoutObject()
                ->paintProperties()
                ->localBorderBoxProperties()
                ->propertyTreeState,
            success);
    DCHECK(success);

    return LayoutRect(clippedRectInLocalSpace);
  }

  LayoutRect layerBounds;
  ClipRect backgroundRect, foregroundRect;
  calculateRects(context, LayoutRect(LayoutRect::infiniteIntRect()),
                 layerBounds, backgroundRect, foregroundRect);

  LayoutRect clipRect = backgroundRect.rect();
  // TODO(chrishtr): avoid converting to IntRect and back.
  if (clipRect == LayoutRect(LayoutRect::infiniteIntRect()))
    return clipRect;

  LayoutPoint clippingRootOffset;
  m_layer.convertToLayerCoords(clippingRootLayer, clippingRootOffset);
  clipRect.moveBy(-clippingRootOffset);

  return clipRect;
}
Ejemplo n.º 6
0
ClipRect PaintLayerClipper::applyOverflowClipToBackgroundRectWithGeometryMapper(
    const ClipRectsContext& context,
    const ClipRect& clip) const {
  const LayoutObject& layoutObject = *m_layer.layoutObject();
  FloatRect clipRect(clip.rect());
  if (shouldClipOverflow(context)) {
    LayoutRect layerBoundsWithVisualOverflow =
        layoutObject.isLayoutView()
            ? toLayoutView(layoutObject).viewRect()
            : toLayoutBox(layoutObject).visualOverflowRect();
    toLayoutBox(layoutObject)
        .flipForWritingMode(
            // PaintLayer are in physical coordinates, so the overflow has to be
            // flipped.
            layerBoundsWithVisualOverflow);
    mapLocalToRootWithGeometryMapper(context, layerBoundsWithVisualOverflow);
    clipRect.intersect(FloatRect(layerBoundsWithVisualOverflow));
  }

  return ClipRect(LayoutRect(clipRect));
}
Ejemplo n.º 7
0
void PaintLayerPainter::paintFragmentWithPhase(PaintPhase phase, const PaintLayerFragment& fragment, GraphicsContext& context, const ClipRect& clipRect, const PaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, ClipState clipState)
{
    ASSERT(m_paintLayer.isSelfPaintingLayer());

    Optional<LayerClipRecorder> clipRecorder;
    if (clipState != HasClipped && paintingInfo.clipToDirtyRect && needsToClip(paintingInfo, clipRect)) {
        DisplayItem::Type clipType = DisplayItem::paintPhaseToClipLayerFragmentType(phase);
        LayerClipRecorder::BorderRadiusClippingRule clippingRule;
        switch (phase) {
        case PaintPhaseSelfBlockBackgroundOnly: // Background painting will handle clipping to self.
        case PaintPhaseSelfOutlineOnly:
        case PaintPhaseMask: // Mask painting will handle clipping to self.
            clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
            break;
        default:
            clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
            break;
        }

        clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, clipRect, &paintingInfo, fragment.paginationOffset, paintFlags, clippingRule);
    }

    LayoutRect newCullRect(clipRect.rect());
    Optional<ScrollRecorder> scrollRecorder;
    LayoutPoint paintOffset = toPoint(fragment.layerBounds.location() - m_paintLayer.layoutBoxLocation());
    if (!paintingInfo.scrollOffsetAccumulation.isZero()) {
        // As a descendant of the root layer, m_paintLayer's painting is not controlled by the ScrollRecorders
        // created by BlockPainter of the ancestor layers up to the root layer, so we need to issue ScrollRecorder
        // for this layer seperately, with the scroll offset accumulated from the root layer to the parent of this
        // layer, to get the same result as ScrollRecorder in BlockPainter.
        paintOffset += paintingInfo.scrollOffsetAccumulation;

        newCullRect.move(paintingInfo.scrollOffsetAccumulation);
        scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase, paintingInfo.scrollOffsetAccumulation);
    }
    PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase,
        paintingInfo.globalPaintFlags(), paintFlags, paintingInfo.rootLayer->layoutObject());

    m_paintLayer.layoutObject()->paint(paintInfo, paintOffset);
}
Ejemplo n.º 8
0
bool PaintLayerPainter::needsToClip(const PaintLayerPaintingInfo& localPaintingInfo, const ClipRect& clipRect)
{
    return clipRect.rect() != localPaintingInfo.paintDirtyRect || clipRect.hasRadius();
}