Esempio n. 1
0
static FloatRect toNormalizedRect(const FloatRect& absoluteRect, const LayoutObject* layoutObject, const LayoutBlock* container)
{
    ASSERT(layoutObject);

    ASSERT(container || layoutObject->isLayoutView());
    if (!container)
        return FloatRect();

    // We want to normalize by the max layout overflow size instead of only the visible bounding box.
    // Quads and their enclosing bounding boxes need to be used in order to keep results transform-friendly.
    FloatPoint scrolledOrigin;

    // For overflow:scroll we need to get where the actual origin is independently of the scroll.
    if (container->hasOverflowClip())
        scrolledOrigin = -IntPoint(container->scrolledContentOffset());

    FloatRect overflowRect(scrolledOrigin, FloatSize(container->maxLayoutOverflow()));
    FloatRect containerRect = container->localToAbsoluteQuad(FloatQuad(overflowRect)).enclosingBoundingBox();

    if (containerRect.isEmpty())
        return FloatRect();

    // Make the coordinates relative to the container enclosing bounding box.
    // Since we work with rects enclosing quad unions this is still transform-friendly.
    FloatRect normalizedRect = absoluteRect;
    normalizedRect.moveBy(-containerRect.location());

    // Fixed positions do not make sense in this coordinate system, but need to leave consistent tickmarks.
    // So, use their position when the view is not scrolled, like an absolute position.
    if (layoutObject->style()->position() == FixedPosition && container->isLayoutView())
        normalizedRect.moveBy(-toLayoutView(container)->frameView()->scrollPosition());

    normalizedRect.scale(1 / containerRect.width(), 1 / containerRect.height());
    return normalizedRect;
}
Esempio n. 2
0
WebAXObject WebDocument::accessibilityObject() const {
  const Document* document = constUnwrap<Document>();
  AXObjectCacheImpl* cache = toAXObjectCacheImpl(document->axObjectCache());
  return cache ? WebAXObject(cache->getOrCreate(
                     toLayoutView(LayoutAPIShim::layoutObjectFrom(
                         document->layoutViewItem()))))
               : WebAXObject();
}
Esempio n. 3
0
AXObject* WebPagePopupImpl::rootAXObject() {
  if (!m_page || !m_page->mainFrame())
    return 0;
  Document* document = toLocalFrame(m_page->mainFrame())->document();
  if (!document)
    return 0;
  AXObjectCache* cache = document->axObjectCache();
  DCHECK(cache);
  return toAXObjectCacheImpl(cache)->getOrCreate(toLayoutView(
      LayoutAPIShim::layoutObjectFrom(document->layoutViewItem())));
}
Esempio n. 4
0
void PaintLayerClipper::calculateRects(const ClipRectsContext& context, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
    ClipRect& backgroundRect, ClipRect& foregroundRect, const LayoutPoint* offsetFromRoot) const
{
    bool isClippingRoot = m_layoutObject.layer() == context.rootLayer;

    if (!isClippingRoot && m_layoutObject.layer()->parent()) {
        backgroundRect = backgroundClipRect(context);
        backgroundRect.move(context.subPixelAccumulation);
        backgroundRect.intersect(paintDirtyRect);
    } else {
        backgroundRect = paintDirtyRect;
    }

    foregroundRect = backgroundRect;

    LayoutPoint offset;
    if (offsetFromRoot)
        offset = *offsetFromRoot;
    else
        m_layoutObject.layer()->convertToLayerCoords(context.rootLayer, offset);
    layerBounds = LayoutRect(offset, LayoutSize(m_layoutObject.layer()->size()));

    // Update the clip rects that will be passed to child layers.
    if (m_layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context)) {
        foregroundRect.intersect(toLayoutBox(m_layoutObject).overflowClipRect(offset, context.scrollbarRelevancy));
        if (m_layoutObject.style()->hasBorderRadius())
            foregroundRect.setHasRadius(true);

        // FIXME: Does not do the right thing with columns yet, since we don't yet factor in the
        // individual column boxes as overflow.

        // The LayoutView is special since its overflow clipping rect may be larger than its box rect (crbug.com/492871).
        LayoutRect layerBoundsWithVisualOverflow = m_layoutObject.isLayoutView() ? toLayoutView(m_layoutObject).viewRect() : toLayoutBox(m_layoutObject).visualOverflowRect();
        toLayoutBox(m_layoutObject).flipForWritingMode(layerBoundsWithVisualOverflow); // PaintLayer are in physical coordinates, so the overflow has to be flipped.
        layerBoundsWithVisualOverflow.moveBy(offset);
        backgroundRect.intersect(layerBoundsWithVisualOverflow);
    }

    // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
    if (m_layoutObject.hasClip()) {
        // Clip applies to *us* as well, so go ahead and update the damageRect.
        LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset);
        backgroundRect.intersect(newPosClip);
        backgroundRect.setIsClippedByClipCss();
        foregroundRect.intersect(newPosClip);
        foregroundRect.setIsClippedByClipCss();
    }
}
void IntersectionObservation::clipToFrameView(IntersectionGeometry& geometry)
{
    Node* rootNode = m_observer->root();
    LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
    if (rootLayoutObject->isLayoutView()) {
        geometry.rootRect = LayoutRect(toLayoutView(rootLayoutObject)->frameView()->visibleContentRect());
        m_observer->applyRootMargin(geometry.rootRect);
        geometry.intersectionRect.intersect(geometry.rootRect);
    } else {
        if (rootLayoutObject->isBox())
            geometry.rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->absoluteContentBox());
        else
            geometry.rootRect = LayoutRect(rootLayoutObject->absoluteBoundingBoxRect());
        m_observer->applyRootMargin(geometry.rootRect);
    }

    LayoutPoint scrollPosition(rootNode->document().view()->scrollPosition());
    geometry.targetRect.moveBy(-scrollPosition);
    geometry.intersectionRect.moveBy(-scrollPosition);
    geometry.rootRect.moveBy(-scrollPosition);
}
Esempio 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));
}
Esempio n. 7
0
PaintLayerPainter::PaintResult PaintLayerPainter::paintLayer(GraphicsContext& context, const PaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
    // https://code.google.com/p/chromium/issues/detail?id=343772
    DisableCompositingQueryAsserts disabler;

    if (m_paintLayer.compositingState() != NotComposited) {
        if (paintingInfo.globalPaintFlags() & GlobalPaintFlattenCompositingLayers) {
            // FIXME: ok, but what about GlobalPaintFlattenCompositingLayers? That's for printing and drag-image.
            // FIXME: why isn't the code here global, as opposed to being set on each paintLayer() call?
            paintFlags |= PaintLayerUncachedClipRects;
        }
    }

    // Non self-painting layers without self-painting descendants don't need to be painted as their
    // layoutObject() should properly paint itself.
    if (!m_paintLayer.isSelfPaintingLayer() && !m_paintLayer.hasSelfPaintingLayerDescendant())
        return FullyPainted;

    if (shouldSuppressPaintingLayer(&m_paintLayer))
        return FullyPainted;

    if (m_paintLayer.layoutObject()->isLayoutView() && toLayoutView(m_paintLayer.layoutObject())->frameView()->shouldThrottleRendering())
        return FullyPainted;

    // If this layer is totally invisible then there is nothing to paint.
    if (!m_paintLayer.layoutObject()->opacity() && !m_paintLayer.layoutObject()->hasBackdropFilter())
        return FullyPainted;

    if (m_paintLayer.paintsWithTransparency(paintingInfo.globalPaintFlags()))
        paintFlags |= PaintLayerHaveTransparency;

    LayerFixedPositionRecorder fixedPositionRecorder(context, *m_paintLayer.layoutObject());

    // PaintLayerAppliedTransform is used in LayoutReplica, to avoid applying the transform twice.
    if (m_paintLayer.paintsWithTransform(paintingInfo.globalPaintFlags()) && !(paintFlags & PaintLayerAppliedTransform))
        return paintLayerWithTransform(context, paintingInfo, paintFlags);

    return paintLayerContentsAndReflection(context, paintingInfo, paintFlags);
}
Esempio n. 8
0
PaintLayerPainter::PaintResult PaintLayerPainter::paintLayerContents(GraphicsContext& context, const PaintLayerPaintingInfo& paintingInfoArg, PaintLayerFlags paintFlags, FragmentPolicy fragmentPolicy)
{
    ASSERT(m_paintLayer.isSelfPaintingLayer() || m_paintLayer.hasSelfPaintingLayerDescendant());
    ASSERT(!(paintFlags & PaintLayerAppliedTransform));

    bool isSelfPaintingLayer = m_paintLayer.isSelfPaintingLayer();
    bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
    bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositingScrollingPhase;
    bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingCompositingForegroundPhase;
    bool isPaintingCompositedBackground = paintFlags & PaintLayerPaintingCompositingBackgroundPhase;
    bool isPaintingOverflowContents = paintFlags & PaintLayerPaintingOverflowContents;
    // Outline always needs to be painted even if we have no visible content. Also,
    // the outline is painted in the background phase during composited scrolling.
    // If it were painted in the foreground phase, it would move with the scrolled
    // content. When not composited scrolling, the outline is painted in the
    // foreground phase. Since scrolled contents are moved by paint invalidation in this
    // case, the outline won't get 'dragged along'.
    bool shouldPaintSelfOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars
        && ((isPaintingScrollingContent && isPaintingCompositedBackground)
            || (!isPaintingScrollingContent && isPaintingCompositedForeground))
        && m_paintLayer.layoutObject()->styleRef().hasOutline();
    bool shouldPaintContent = m_paintLayer.hasVisibleContent() && isSelfPaintingLayer && !isPaintingOverlayScrollbars;

    PaintResult result = FullyPainted;

    if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !m_paintLayer.layoutObject()->isLayoutView() && !m_paintLayer.layoutObject()->isDocumentElement())
        return result;

    if (m_paintLayer.layoutObject()->isLayoutView() && toLayoutView(m_paintLayer.layoutObject())->frameView()->shouldThrottleRendering())
        return result;

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

    LayoutSize subpixelAccumulation = m_paintLayer.compositingState() == PaintsIntoOwnBacking ? m_paintLayer.subpixelAccumulation() : paintingInfoArg.subPixelAccumulation;
    ShouldRespectOverflowClip respectOverflowClip = shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject());

    Optional<SubsequenceRecorder> subsequenceRecorder;
    if (shouldCreateSubsequence(m_paintLayer, context, paintingInfoArg, paintFlags)) {
        if (!shouldRepaintSubsequence(m_paintLayer, paintingInfoArg, respectOverflowClip, subpixelAccumulation)
            && SubsequenceRecorder::useCachedSubsequenceIfPossible(context, m_paintLayer))
            return result;
        subsequenceRecorder.emplace(context, m_paintLayer);
    }

    PaintLayerPaintingInfo paintingInfo = paintingInfoArg;

    LayoutPoint offsetFromRoot;
    m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
    offsetFromRoot.move(subpixelAccumulation);

    LayoutRect bounds = m_paintLayer.physicalBoundingBox(offsetFromRoot);
    if (!paintingInfo.paintDirtyRect.contains(bounds))
        result = MayBeClippedByPaintDirtyRect;

    LayoutRect rootRelativeBounds;
    bool rootRelativeBoundsComputed = false;

    if (paintingInfo.ancestorHasClipPathClipping && m_paintLayer.layoutObject()->isPositioned())
        UseCounter::count(m_paintLayer.layoutObject()->document(), UseCounter::ClipPathOfPositionedElement);

    // These helpers output clip and compositing operations using a RAII pattern. Stack-allocated-varibles are destructed in the reverse order of construction,
    // so they are nested properly.
    ClipPathHelper clipPathHelper(context, m_paintLayer, paintingInfo, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags);

    Optional<CompositingRecorder> compositingRecorder;
    // Blending operations must be performed only with the nearest ancestor stacking context.
    // Note that there is no need to composite if we're painting the root.
    // FIXME: this should be unified further into PaintLayer::paintsWithTransparency().
    bool shouldCompositeForBlendMode = (!m_paintLayer.layoutObject()->isDocumentElement() || m_paintLayer.layoutObject()->isSVGRoot()) && m_paintLayer.stackingNode()->isStackingContext() && m_paintLayer.hasNonIsolatedDescendantWithBlendMode();
    if (shouldCompositeForBlendMode || m_paintLayer.paintsWithTransparency(paintingInfo.globalPaintFlags())) {
        FloatRect compositingBounds = FloatRect(m_paintLayer.paintingExtent(paintingInfo.rootLayer, paintingInfo.subPixelAccumulation, paintingInfo.globalPaintFlags()));
        compositingRecorder.emplace(context, *m_paintLayer.layoutObject(),
            WebCoreCompositeToSkiaComposite(CompositeSourceOver, m_paintLayer.layoutObject()->style()->blendMode()),
            m_paintLayer.layoutObject()->opacity(), &compositingBounds);
    }

    PaintLayerPaintingInfo localPaintingInfo(paintingInfo);
    localPaintingInfo.subPixelAccumulation = subpixelAccumulation;

    PaintLayerFragments layerFragments;
    if (shouldPaintContent || shouldPaintSelfOutline || isPaintingOverlayScrollbars) {
        // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment.
        ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) ? UncachedClipRects : PaintingClipRects;
        if (fragmentPolicy == ForceSingleFragment)
            m_paintLayer.appendSingleFragmentIgnoringPagination(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
        else
            m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
        if (shouldPaintContent) {
            // TODO(wangxianzhu): This is for old slow scrolling. Implement similar optimization for slimming paint v2.
            shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
            if (!shouldPaintContent)
                result = MayBeClippedByPaintDirtyRect;
        }
    }

    bool selectionOnly = localPaintingInfo.globalPaintFlags() & GlobalPaintSelectionOnly;

    { // Begin block for the lifetime of any filter.
        FilterPainter filterPainter(m_paintLayer, context, offsetFromRoot, layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect, localPaintingInfo, paintFlags,
            rootRelativeBounds, rootRelativeBoundsComputed);

        Optional<ScopedPaintChunkProperties> scopedPaintChunkProperties;
        if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
            if (const auto* objectProperties = m_paintLayer.layoutObject()->objectPaintProperties()) {
                PaintChunkProperties properties(context.paintController().currentPaintChunkProperties());
                if (TransformPaintPropertyNode* transform = objectProperties->transformForLayerContents())
                    properties.transform = transform;
                if (EffectPaintPropertyNode* effect = objectProperties->effect())
                    properties.effect = effect;
                scopedPaintChunkProperties.emplace(context.paintController(), properties);
            }
        }

        bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly;
        bool shouldPaintNegZOrderList = (isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground);
        bool shouldPaintOwnContents = isPaintingCompositedForeground && shouldPaintContent;
        bool shouldPaintNormalFlowAndPosZOrderLists = isPaintingCompositedForeground;
        bool shouldPaintOverlayScrollbars = isPaintingOverlayScrollbars;

        if (shouldPaintBackground) {
            paintBackgroundForFragments(layerFragments, context, paintingInfo.paintDirtyRect,
                localPaintingInfo, paintFlags);
        }

        if (shouldPaintNegZOrderList) {
            if (paintChildren(NegativeZOrderChildren, context, paintingInfo, paintFlags) == MayBeClippedByPaintDirtyRect)
                result = MayBeClippedByPaintDirtyRect;
        }

        if (shouldPaintOwnContents) {
            paintForegroundForFragments(layerFragments, context, paintingInfo.paintDirtyRect,
                localPaintingInfo, selectionOnly, paintFlags);
        }

        if (shouldPaintSelfOutline)
            paintSelfOutlineForFragments(layerFragments, context, localPaintingInfo, paintFlags);

        if (shouldPaintNormalFlowAndPosZOrderLists) {
            if (paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, paintingInfo, paintFlags) == MayBeClippedByPaintDirtyRect)
                result = MayBeClippedByPaintDirtyRect;
        }

        if (shouldPaintOverlayScrollbars)
            paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags);
    } // FilterPainter block

    bool shouldPaintMask = (paintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && !selectionOnly;
    bool shouldPaintClippingMask = (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly;

    if (shouldPaintMask)
        paintMaskForFragments(layerFragments, context, localPaintingInfo, paintFlags);
    if (shouldPaintClippingMask) {
        // Paint the border radius mask for the fragments.
        paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintFlags);
    }

    if (subsequenceRecorder)
        m_paintLayer.setPreviousPaintResult(result);
    return result;
}