PaintInvalidationState::PaintInvalidationState(PaintInvalidationState& next, LayoutBoxModelObject& layoutObject, const LayoutBoxModelObject& paintInvalidationContainer)
    : m_clipped(false)
    , m_cachedOffsetsEnabled(true)
    , m_forcedSubtreeInvalidationWithinContainer(next.m_forcedSubtreeInvalidationWithinContainer)
    , m_forcedSubtreeInvalidationRectUpdateWithinContainer(next.m_forcedSubtreeInvalidationRectUpdateWithinContainer)
    , m_viewClippingAndScrollOffsetDisabled(false)
    , m_paintInvalidationContainer(paintInvalidationContainer)
    , m_pendingDelayedPaintInvalidations(next.pendingDelayedPaintInvalidationTargets())
    , m_enclosingSelfPaintingLayer(next.enclosingSelfPaintingLayer(layoutObject))
{
    // FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054
    bool establishesPaintInvalidationContainer = layoutObject == m_paintInvalidationContainer;
    bool fixed = layoutObject.style()->position() == FixedPosition;

    if (!layoutObject.supportsPaintInvalidationStateCachedOffsets() || !next.m_cachedOffsetsEnabled)
        m_cachedOffsetsEnabled = false;
    if (establishesPaintInvalidationContainer) {
        // When we hit a new paint invalidation container, we don't need to
        // continue forcing a check for paint invalidation, since we're
        // descending into a different invalidation container. (For instance if
        // our parents were moved, the entire container will just move.)
        m_forcedSubtreeInvalidationWithinContainer = false;
    } else {
        if (m_cachedOffsetsEnabled) {
            if (fixed) {
                FloatPoint fixedOffset = layoutObject.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
                m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y());
            } else {
                LayoutSize offset = layoutObject.isBox() && !layoutObject.isTableRow() ? toLayoutBox(layoutObject).locationOffset() : LayoutSize();
                m_paintOffset = next.m_paintOffset + offset;
            }

            if (layoutObject.isOutOfFlowPositioned() && !fixed) {
                if (LayoutObject* container = layoutObject.container()) {
                    if (container->style()->hasInFlowPosition() && container->isLayoutInline())
                        m_paintOffset += toLayoutInline(container)->offsetForInFlowPositionedInline(toLayoutBox(layoutObject));
                }
            }

            if (layoutObject.style()->hasInFlowPosition() && layoutObject.hasLayer())
                m_paintOffset += layoutObject.layer()->offsetForInFlowPosition();
        }

        m_clipped = !fixed && next.m_clipped;
        if (m_clipped)
            m_clipRect = next.m_clipRect;
    }

    if (m_cachedOffsetsEnabled && layoutObject.isSVGRoot()) {
        const LayoutSVGRoot& svgRoot = toLayoutSVGRoot(layoutObject);
        m_svgTransform = AffineTransform(svgRoot.localToBorderBoxTransform());
        if (svgRoot.shouldApplyViewportClip())
            addClipRectRelativeToPaintOffset(LayoutSize(svgRoot.pixelSnappedSize()));
    }

    applyClipIfNeeded(layoutObject);

    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
Ejemplo n.º 2
0
static void applyClipRects(const ClipRectsContext& context,
                           const LayoutBoxModelObject& layoutObject,
                           LayoutPoint offset,
                           ClipRects& clipRects) {
  DCHECK(layoutObject.hasClipRelatedProperty() ||
         (layoutObject.isSVGRoot() &&
          toLayoutSVGRoot(&layoutObject)->shouldApplyViewportClip()));
  LayoutView* view = layoutObject.view();
  DCHECK(view);
  if (clipRects.fixed() && context.rootLayer->layoutObject() == view)
    offset -= LayoutSize(view->frameView()->scrollOffset());
  if (layoutObject.hasOverflowClip() ||
      (layoutObject.isSVGRoot() &&
       toLayoutSVGRoot(&layoutObject)->shouldApplyViewportClip()) ||
      (layoutObject.styleRef().containsPaint() && layoutObject.isBox())) {
    ClipRect newOverflowClip =
        toLayoutBox(layoutObject)
            .overflowClipRect(offset, context.overlayScrollbarClipBehavior);
    newOverflowClip.setHasRadius(layoutObject.styleRef().hasBorderRadius());
    clipRects.setOverflowClipRect(
        intersection(newOverflowClip, clipRects.overflowClipRect()));
    if (layoutObject.isPositioned())
      clipRects.setPosClipRect(
          intersection(newOverflowClip, clipRects.posClipRect()));
    if (layoutObject.isLayoutView())
      clipRects.setFixedClipRect(
          intersection(newOverflowClip, clipRects.fixedClipRect()));
    if (layoutObject.styleRef().containsPaint()) {
      clipRects.setPosClipRect(
          intersection(newOverflowClip, clipRects.posClipRect()));
      clipRects.setFixedClipRect(
          intersection(newOverflowClip, clipRects.fixedClipRect()));
    }
  }
  if (layoutObject.hasClip()) {
    LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset);
    clipRects.setPosClipRect(
        intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss());
    clipRects.setOverflowClipRect(
        intersection(newClip, clipRects.overflowClipRect())
            .setIsClippedByClipCss());
    clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect())
                                   .setIsClippedByClipCss());
  }
}
void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPropertyTreeBuilderContext& context)
{
    ASSERT(object.isBox() != object.isLayoutInline()); // Either or.

    PaintPropertyTreeBuilderContext localContext(context);

    deriveBorderBoxFromContainerContext(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext);
    RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext);
    updateOutOfFlowContext(object, localContext);

    if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) {
        OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create(
            newTransformNodeForPaintOffsetTranslation.release(),
            newTransformNodeForTransform.release(),
            newEffectNode.release(),
            newTransformNodeForPerspective.release(),
            newTransformNodeForScrollTranslation.release());
        object.setObjectPaintProperties(updatedPaintProperties.release());
    } else {
        object.clearObjectPaintProperties();
    }

    // TODO(trchen): Walk subframes for LayoutFrame.

    // TODO(trchen): Implement SVG walk.
    if (object.isSVGRoot()) {
        return;
    }

    for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) {
        if (child->isText())
            continue;
        walk(toLayoutBoxModelObject(*child), localContext);
    }
}