static void write(QTextStream &ts, RenderLayer &l, const QRect& layerBounds, const QRect& backgroundClipRect, const QRect& clipRect, int layerType = 0, int indent = 0) { writeIndent(ts, indent); ts << "layer"; ts << " " << layerBounds; if (layerBounds != layerBounds.intersect(backgroundClipRect)) ts << " backgroundClip " << backgroundClipRect; if (layerBounds != layerBounds.intersect(clipRect)) ts << " clip " << clipRect; if (l.renderer()->hasOverflowClip()) { if (l.scrollXOffset()) ts << " scrollX " << l.scrollXOffset(); if (l.scrollYOffset()) ts << " scrollY " << l.scrollYOffset(); if (l.renderer()->clientWidth() != l.scrollWidth()) ts << " scrollWidth " << l.scrollWidth(); if (l.renderer()->clientHeight() != l.scrollHeight()) ts << " scrollHeight " << l.scrollHeight(); } if (layerType == -1) ts << " layerType: background only"; else if (layerType == 1) ts << " layerType: foreground only"; ts << "\n"; if (layerType != -1) write(ts, *l.renderer(), indent + 1); }
static void write(TextStream& ts, RenderLayer& l, const LayoutRect& layerBounds, const LayoutRect& backgroundClipRect, const LayoutRect& clipRect, const LayoutRect& outlineClipRect, LayerPaintPhase paintPhase = LayerPaintPhaseAll, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal) { IntRect adjustedLayoutBounds = pixelSnappedIntRect(layerBounds); IntRect adjustedBackgroundClipRect = pixelSnappedIntRect(backgroundClipRect); IntRect adjustedClipRect = pixelSnappedIntRect(clipRect); IntRect adjustedOutlineClipRect = pixelSnappedIntRect(outlineClipRect); writeIndent(ts, indent); ts << "layer "; if (behavior & RenderAsTextShowAddresses) ts << static_cast<const void*>(&l) << " "; ts << adjustedLayoutBounds; if (!adjustedLayoutBounds.isEmpty()) { if (!adjustedBackgroundClipRect.contains(adjustedLayoutBounds)) ts << " backgroundClip " << adjustedBackgroundClipRect; if (!adjustedClipRect.contains(adjustedLayoutBounds)) ts << " clip " << adjustedClipRect; if (!adjustedOutlineClipRect.contains(adjustedLayoutBounds)) ts << " outlineClip " << adjustedOutlineClipRect; } if (l.renderer()->hasOverflowClip()) { if (l.scrollXOffset()) ts << " scrollX " << l.scrollXOffset(); if (l.scrollYOffset()) ts << " scrollY " << l.scrollYOffset(); if (l.renderBox() && l.renderBox()->pixelSnappedClientWidth() != l.scrollWidth()) ts << " scrollWidth " << l.scrollWidth(); if (l.renderBox() && l.renderBox()->pixelSnappedClientHeight() != l.scrollHeight()) ts << " scrollHeight " << l.scrollHeight(); } if (paintPhase == LayerPaintPhaseBackground) ts << " layerType: background only"; else if (paintPhase == LayerPaintPhaseForeground) ts << " layerType: foreground only"; #if USE(ACCELERATED_COMPOSITING) if (behavior & RenderAsTextShowCompositedLayers) { if (l.isComposited()) ts << " (composited, bounds=" << l.backing()->compositedBounds() << ", drawsContent=" << l.backing()->graphicsLayer()->drawsContent() << ", paints into ancestor=" << l.backing()->paintsIntoCompositedAncestor() << ")"; } #else UNUSED_PARAM(behavior); #endif ts << "\n"; if (paintPhase != LayerPaintPhaseBackground) write(ts, *l.renderer(), indent + 1, behavior); }
static void write(TextStream& ts, RenderLayer& l, const IntRect& layerBounds, const IntRect& backgroundClipRect, const IntRect& clipRect, const IntRect& outlineClipRect, LayerPaintPhase paintPhase = LayerPaintPhaseAll, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal) { writeIndent(ts, indent); ts << "layer "; if (behavior & RenderAsTextShowAddresses) ts << static_cast<const void*>(&l) << " "; ts << layerBounds; if (!layerBounds.isEmpty()) { if (!backgroundClipRect.contains(layerBounds)) ts << " backgroundClip " << backgroundClipRect; if (!clipRect.contains(layerBounds)) ts << " clip " << clipRect; if (!outlineClipRect.contains(layerBounds)) ts << " outlineClip " << outlineClipRect; } if (l.renderer()->hasOverflowClip()) { if (l.scrollXOffset()) ts << " scrollX " << l.scrollXOffset(); if (l.scrollYOffset()) ts << " scrollY " << l.scrollYOffset(); if (l.renderBox() && l.renderBox()->clientWidth() != l.scrollWidth()) ts << " scrollWidth " << l.scrollWidth(); if (l.renderBox() && l.renderBox()->clientHeight() != l.scrollHeight()) ts << " scrollHeight " << l.scrollHeight(); } if (paintPhase == LayerPaintPhaseBackground) ts << " layerType: background only"; else if (paintPhase == LayerPaintPhaseForeground) ts << " layerType: foreground only"; #if USE(ACCELERATED_COMPOSITING) if (behavior & RenderAsTextShowCompositedLayers) { if (l.isComposited()) ts << " (composited, bounds " << l.backing()->compositedBounds() << ")"; } #else UNUSED_PARAM(behavior); #endif ts << "\n"; if (paintPhase != LayerPaintPhaseBackground) write(ts, *l.renderer(), indent + 1, behavior); }
void TouchEventHandler::drawTapHighlight() { Element* elementUnderFatFinger = m_lastFatFingersResult.nodeAsElementIfApplicable(); if (!elementUnderFatFinger) return; Element* element = elementForTapHighlight(elementUnderFatFinger); if (!element) return; // Get the element bounding rect in transformed coordinates so we can extract // the focus ring relative position each rect. RenderObject* renderer = element->renderer(); ASSERT(renderer); Frame* elementFrame = element->document()->frame(); ASSERT(elementFrame); FrameView* elementFrameView = elementFrame->view(); if (!elementFrameView) return; // Tell the client if the element is either in a scrollable container or in a fixed positioned container. // On the client side, this info is being used to hide the tap highlight window on scroll. RenderLayer* layer = m_webPage->enclosingFixedPositionedAncestorOrSelfIfFixedPositioned(renderer->enclosingLayer()); bool shouldHideTapHighlightRightAfterScrolling = !layer->renderer()->isRenderView(); shouldHideTapHighlightRightAfterScrolling |= !!m_webPage->m_inRegionScroller->d->node(); IntPoint framePos(m_webPage->frameOffset(elementFrame)); // FIXME: We can get more precise on the <map> case by calculating the rect with HTMLAreaElement::computeRect(). IntRect absoluteRect(renderer->absoluteClippedOverflowRect()); absoluteRect.move(framePos.x(), framePos.y()); IntRect clippingRect; if (elementFrame == m_webPage->mainFrame()) clippingRect = IntRect(IntPoint(0, 0), elementFrameView->contentsSize()); else clippingRect = m_webPage->mainFrame()->view()->windowToContents(m_webPage->getRecursiveVisibleWindowRect(elementFrameView, true /*noClipToMainFrame*/)); clippingRect = intersection(absoluteRect, clippingRect); Vector<FloatQuad> focusRingQuads; renderer->absoluteFocusRingQuads(focusRingQuads); Platform::IntRectRegion region; for (size_t i = 0; i < focusRingQuads.size(); ++i) { IntRect rect = focusRingQuads[i].enclosingBoundingBox(); rect.move(framePos.x(), framePos.y()); IntRect clippedRect = intersection(clippingRect, rect); clippedRect.inflate(2); region = unionRegions(region, Platform::IntRect(clippedRect)); } Color highlightColor = element->renderStyle()->tapHighlightColor(); m_webPage->m_tapHighlight->draw(region, highlightColor.red(), highlightColor.green(), highlightColor.blue(), highlightColor.alpha(), shouldHideTapHighlightRightAfterScrolling); }
static bool shouldAppendLayer(const RenderLayer& layer) { if (!RuntimeEnabledFeatures::overlayFullscreenVideoEnabled()) return true; Node* node = layer.renderer()->node(); if (node && isHTMLMediaElement(*node) && toHTMLMediaElement(node)->isFullscreen()) return false; return true; }
LayoutRect RenderLayerClipper::selfClipRect() const { // FIXME: border-radius not accounted for. RenderView* renderView = m_renderer->view(); RenderLayer* clippingRootLayer = clippingRootForPainting(); LayoutRect layerBounds; ClipRect backgroundRect, foregroundRect, outlineRect; ClipRectsContext clipRectsContext(clippingRootLayer, PaintingClipRects); calculateRects(clipRectsContext, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox(); }
RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const { for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) { if (curr->isStackingContext()) return 0; if (curr->renderer()->hasOverflowClip() || layer->renderer()->hasClip()) return curr; } return 0; }
LayoutRect RenderLayerClipper::childrenClipRect() const { // FIXME: border-radius not accounted for. // FIXME: Regions not accounted for. RenderLayer* clippingRootLayer = clippingRootForPainting(); LayoutRect layerBounds; ClipRect backgroundRect, foregroundRect, outlineRect; // Need to use uncached clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>). ClipRectsContext context(clippingRootLayer, UncachedClipRects); calculateRects(context, m_renderer.view()->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox(); }
RenderLayer* LinkHighlight::computeEnclosingCompositingLayer() { if (!m_node || !m_node->renderer()) return 0; RenderLayer* renderLayer = m_node->renderer()->enclosingLayer(); // Find the nearest enclosing composited layer and attach to it. We may need to cross frame boundaries // to find a suitable layer. while (renderLayer && !renderLayer->isComposited()) { if (!renderLayer->parent()) { // See if we've reached the root in an enclosed frame. if (renderLayer->renderer()->frame()->ownerRenderer()) renderLayer = renderLayer->renderer()->frame()->ownerRenderer()->enclosingLayer(); else renderLayer = 0; } else renderLayer = renderLayer->parent(); } if (!renderLayer || !renderLayer->isComposited()) return 0; GraphicsLayerChromium* newGraphicsLayer = static_cast<GraphicsLayerChromium*>(renderLayer->backing()->graphicsLayer()); m_clipLayer->setSublayerTransform(SkMatrix44()); if (!newGraphicsLayer->drawsContent()) { m_clipLayer->setSublayerTransform(newGraphicsLayer->platformLayer()->transform()); newGraphicsLayer = static_cast<GraphicsLayerChromium*>(m_owningWebViewImpl->nonCompositedContentHost()->topLevelRootLayer()); } if (m_currentGraphicsLayer != newGraphicsLayer) { if (m_currentGraphicsLayer) clearGraphicsLayerLinkHighlightPointer(); m_currentGraphicsLayer = newGraphicsLayer; m_currentGraphicsLayer->setLinkHighlight(this); } return renderLayer; }
static void write(TextStream& ts, RenderLayer& l, const IntRect& layerBounds, const IntRect& backgroundClipRect, const IntRect& clipRect, const IntRect& outlineClipRect, int layerType = 0, int indent = 0) { writeIndent(ts, indent); ts << "layer " << layerBounds; if (!layerBounds.isEmpty()) { if (!backgroundClipRect.contains(layerBounds)) ts << " backgroundClip " << backgroundClipRect; if (!clipRect.contains(layerBounds)) ts << " clip " << clipRect; if (!outlineClipRect.contains(layerBounds)) ts << " outlineClip " << outlineClipRect; } if (l.renderer()->hasOverflowClip()) { if (l.scrollXOffset()) ts << " scrollX " << l.scrollXOffset(); if (l.scrollYOffset()) ts << " scrollY " << l.scrollYOffset(); if (l.renderer()->clientWidth() != l.scrollWidth()) ts << " scrollWidth " << l.scrollWidth(); if (l.renderer()->clientHeight() != l.scrollHeight()) ts << " scrollHeight " << l.scrollHeight(); } if (layerType == -1) ts << " layerType: background only"; else if (layerType == 1) ts << " layerType: foreground only"; ts << "\n"; if (layerType != -1) write(ts, *l.renderer(), indent + 1); }
void GraphicsLayerAndroid::updateFixedPosition() { RenderLayer* renderLayer = renderLayerFromClient(m_client); if (!renderLayer) return; RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); if (!view) return; // We will need the Iframe flag in the LayerAndroid tree for fixed position if (view->isRenderIFrame()) m_contentLayer->setIsIframe(true); // If we are a fixed position layer, just set it if (view->isPositioned() && view->style()->position() == FixedPosition) { // We need to get the passed CSS properties for the element SkLength left, top, right, bottom; left = convertLength(view->style()->left()); top = convertLength(view->style()->top()); right = convertLength(view->style()->right()); bottom = convertLength(view->style()->bottom()); // We also need to get the margin... SkLength marginLeft, marginTop, marginRight, marginBottom; marginLeft = convertLength(view->style()->marginLeft()); marginTop = convertLength(view->style()->marginTop()); marginRight = convertLength(view->style()->marginRight()); marginBottom = convertLength(view->style()->marginBottom()); // In order to compute the fixed element's position, we need the width // and height of the element when bottom or right is defined. // And here we should use the non-overflowed value, that means, the // overflowed content (e.g. outset shadow) will not be counted into the // width and height. int w = view->width(); int h = view->height(); int paintingOffsetX = - offsetFromRenderer().width(); int paintingOffsetY = - offsetFromRenderer().height(); SkRect viewRect; viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h); IntPoint renderLayerPos(renderLayer->x(), renderLayer->y()); m_contentLayer->setFixedPosition(left, top, right, bottom, marginLeft, marginTop, marginRight, marginBottom, renderLayerPos, viewRect); } }
static void write(TextStream& ts, RenderLayer& l, const LayoutRect& layerBounds, const LayoutRect& backgroundClipRect, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal) { IntRect adjustedLayoutBounds = pixelSnappedIntRect(layerBounds); IntRect adjustedBackgroundClipRect = pixelSnappedIntRect(backgroundClipRect); writeIndent(ts, indent); ts << "layer "; if (behavior & RenderAsTextShowAddresses) ts << static_cast<const void*>(&l) << " "; ts << adjustedLayoutBounds; if (!adjustedLayoutBounds.isEmpty()) { if (!adjustedBackgroundClipRect.contains(adjustedLayoutBounds)) ts << " backgroundClip " << adjustedBackgroundClipRect; } ts << "\n"; write(ts, *l.renderer(), indent + 1, behavior); }
bool RenderEmbeddedObject::isReplacementObscured() const { // Return whether or not the replacement content for blocked plugins is accessible to the user. // Check the opacity of each layer containing the element or its ancestors. float opacity = 1.0; for (RenderLayer* layer = enclosingLayer(); layer; layer = layer->parent()) { opacity *= layer->renderer().style().opacity(); if (opacity < 0.1) return true; } // Calculate the absolute rect for the blocked plugin replacement text. IntRect absoluteBoundingBox = absoluteBoundingBoxRect(); LayoutPoint absoluteLocation(absoluteBoundingBox.location()); LayoutRect rect = unavailablePluginIndicatorBounds(absoluteLocation); if (rect.isEmpty()) return true; RenderView* rootRenderView = document().topDocument().renderView(); ASSERT(rootRenderView); if (!rootRenderView) return true; IntRect rootViewRect = view().frameView().convertToRootView(snappedIntRect(rect)); HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent); HitTestResult result; HitTestLocation location; LayoutUnit x = rootViewRect.x(); LayoutUnit y = rootViewRect.y(); LayoutUnit width = rootViewRect.width(); LayoutUnit height = rootViewRect.height(); // Hit test the center and near the corners of the replacement text to ensure // it is visible and is not masked by other elements. bool hit = false; location = LayoutPoint(x + width / 2, y + height / 2); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x, y); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x + width, y); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x + width, y + height); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x, y + height); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; return false; }
bool CompositingReasonFinder::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason, bool* needToRecomputeCompositingRequirements) const { // position:fixed elements that create their own stacking context (e.g. have an explicit z-index, // opacity, transform) can get their own composited layer. A stacking context is required otherwise // z-index and clipping will be broken. if (!renderer->isPositioned()) return false; EPosition position = renderer->style()->position(); bool isFixed = renderer->isOutOfFlowPositioned() && position == FixedPosition; // FIXME: The isStackingContainer check here is redundant. Fixed position elements are always stacking contexts. if (isFixed && !layer->stackingNode()->isStackingContainer()) return false; bool isSticky = renderer->isInFlowPositioned() && position == StickyPosition; if (!isFixed && !isSticky) return false; // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled(). if (Settings* settings = m_renderView.document().settings()) { if (!settings->acceleratedCompositingForFixedPositionEnabled()) return false; } if (isSticky) return isViewportConstrainedFixedOrStickyLayer(layer); RenderObject* container = renderer->container(); // If the renderer is not hooked up yet then we have to wait until it is. if (!container) { *needToRecomputeCompositingRequirements = true; return false; } // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements. // They will stay fixed wrt the container rather than the enclosing frame. if (container != &m_renderView) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer; return false; } // If the fixed-position element does not have any scrollable ancestor between it and // its container, then we do not need to spend compositor resources for it. Start by // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below. bool hasScrollableAncestor = false; // The FrameView has the scrollbars associated with the top level viewport, so we have to // check the FrameView in addition to the hierarchy of ancestors. FrameView* frameView = m_renderView.frameView(); if (frameView && frameView->isScrollable()) hasScrollableAncestor = true; RenderLayer* ancestor = layer->parent(); while (ancestor && !hasScrollableAncestor) { if (frameView->containsScrollableArea(ancestor->scrollableArea())) hasScrollableAncestor = true; if (ancestor->renderer() == &m_renderView) break; ancestor = ancestor->parent(); } if (!hasScrollableAncestor) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors; return false; } // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done. if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean) { *needToRecomputeCompositingRequirements = true; return layer->hasCompositedLayerMapping(); } bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant(); if (!paintsContent) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent; return false; } // Fixed position elements that are invisible in the current view don't get their own layer. if (FrameView* frameView = m_renderView.frameView()) { LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect(); LayoutRect layerBounds = layer->calculateLayerBounds(layer->compositor()->rootRenderLayer(), 0, RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants | RenderLayer::PretendLayerHasOwnBacking); if (!viewBounds.intersects(enclosingIntRect(layerBounds))) { if (viewportConstrainedNotCompositedReason) { *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView; *needToRecomputeCompositingRequirements = true; } return false; } } return true; }
void GraphicsLayerAndroid::updateScrollingLayers() { #if ENABLE(ANDROID_OVERFLOW_SCROLL) RenderLayer* layer = renderLayerFromClient(m_client); if (!layer || !m_haveContents) return; bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable(); bool layerNeedsOverflow = layer->hasOverflowScroll(); bool iframeNeedsOverflow = layer->isRootLayer() && layer->renderer()->frame()->ownerRenderer() && layer->renderer()->frame()->view()->hasOverflowScroll(); if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) { // Already has overflow layers. return; } if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) { // Does not need overflow layers. return; } if (layerNeedsOverflow || iframeNeedsOverflow) { ASSERT(!hasOverflowScroll); if (layerNeedsOverflow) { ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); m_foregroundLayer = new ScrollableLayerAndroid(layer); m_foregroundClipLayer = new LayerAndroid(layer); m_foregroundClipLayer->setMasksToBounds(true); m_foregroundClipLayer->addChild(m_foregroundLayer); m_contentLayer->addChild(m_foregroundClipLayer); m_contentLayer->setHasOverflowChildren(true); } else { ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); // No need to copy the children as they will be removed and synced. m_contentLayer->removeChildren(); // Replace the content layer with a scrollable layer. LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); m_contentLayer->unref(); m_contentLayer = layer; if (m_parent) { // The content layer has changed so the parent needs to sync // children. static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; } } // Need to rebuild our children based on the new structure. m_needsSyncChildren = true; } else { ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow); ASSERT(m_contentLayer); // Remove the foreground layers. if (m_foregroundLayer) { m_foregroundLayer->unref(); m_foregroundLayer = 0; m_foregroundClipLayer->unref(); m_foregroundClipLayer = 0; } // No need to copy over children. m_contentLayer->removeChildren(); LayerAndroid* layer = new LayerAndroid(*m_contentLayer); m_contentLayer->unref(); m_contentLayer = layer; if (m_parent) { // The content layer has changed so the parent needs to sync // children. static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; } // Children are all re-parented. m_needsSyncChildren = true; } #endif }
bool RenderEmbeddedObject::isReplacementObscured() const { // Return whether or not the replacement content for blocked plugins is accessible to the user. // Check the opacity of each layer containing the element or its ancestors. float opacity = 1.0; for (RenderLayer* layer = enclosingLayer(); layer; layer = layer->parent()) { RenderLayerModelObject* renderer = layer->renderer(); RenderStyle* style = renderer->style(); opacity *= style->opacity(); if (opacity < 0.1) return true; } // Calculate the absolute rect for the blocked plugin replacement text. IntRect absoluteBoundingBox = absoluteBoundingBoxRect(); LayoutPoint absoluteLocation(absoluteBoundingBox.location()); LayoutRect rect = replacementTextRect(absoluteLocation); if (rect.isEmpty()) return true; RenderView* docRenderer = document()->renderView(); ASSERT(docRenderer); if (!docRenderer) return true; HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); HitTestResult result; HitTestLocation location; LayoutUnit x = rect.x(); LayoutUnit y = rect.y(); LayoutUnit width = rect.width(); LayoutUnit height = rect.height(); // Hit test the center and near the corners of the replacement text to ensure // it is visible and is not masked by other elements. bool hit = false; location = LayoutPoint(x + width / 2, y + height / 2); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x, y); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x + width, y); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x + width, y + height); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x, y + height); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; return false; }
bool GraphicsLayerAndroid::repaint() { LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", this, gPaused, m_needsRepaint, m_haveContents); if (!gPaused && m_haveContents && m_needsRepaint && !m_image) { // with SkPicture, we request the entire layer's content. IntRect layerBounds(0, 0, m_size.width(), m_size.height()); RenderLayer* layer = renderLayerFromClient(m_client); if (!layer) return false; if (m_foregroundLayer) { PaintingPhase phase(this); // Paint the background into a separate context. phase.set(GraphicsLayerPaintBackground); if (!paintContext(m_contentLayer->recordContext(), layerBounds)) return false; m_contentLayer->checkTextPresence(); // Construct the foreground layer and draw. RenderBox* box = layer->renderBox(); int outline = box->view()->maximalOutlineSize(); IntRect contentsRect(0, 0, box->borderLeft() + box->borderRight() + layer->scrollWidth(), box->borderTop() + box->borderBottom() + layer->scrollHeight()); contentsRect.inflate(outline); // Update the foreground layer size. m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); // Paint everything else into the main recording canvas. phase.clear(GraphicsLayerPaintBackground); // Paint at 0,0. IntSize scroll = layer->scrolledContentOffset(); layer->scrollToOffset(0, 0); // At this point, it doesn't matter if painting failed. (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); m_foregroundLayer->checkTextPresence(); layer->scrollToOffset(scroll.width(), scroll.height()); // Construct the clip layer for masking the contents. IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); // absoluteBoundingBoxRect does not include the outline so we need // to offset the position. int x = box->borderLeft() + outline; int y = box->borderTop() + outline; int width = clip.width() - box->borderLeft() - box->borderRight(); int height = clip.height() - box->borderTop() - box->borderBottom(); m_foregroundClipLayer->setPosition(x, y); m_foregroundClipLayer->setSize(width, height); // Need to offset the foreground layer by the clip layer in order // for the contents to be in the correct position. m_foregroundLayer->setPosition(-x, -y); // Set the scrollable bounds of the layer. m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height()); // Invalidate the entire layer for now, as webkit will only send the // setNeedsDisplayInRect() for the visible (clipped) scrollable area, // offsetting the invals by the scroll position would not be enough. // TODO: have webkit send us invals even for non visible area SkRegion region; region.setRect(0, 0, contentsRect.width(), contentsRect.height()); m_foregroundLayer->markAsDirty(region); m_foregroundLayer->needsRepaint(); } else { // If there is no contents clip, we can draw everything into one // picture. if (!paintContext(m_contentLayer->recordContext(), layerBounds)) return false; m_contentLayer->checkTextPresence(); // Check for a scrollable iframe and report the scrolling // limits based on the view size. if (m_contentLayer->contentIsScrollable()) { FrameView* view = layer->renderer()->frame()->view(); static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits( m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight()); } } LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", this, m_size.width(), m_size.height(), m_contentLayer->getPosition().fX, m_contentLayer->getPosition().fY, m_contentLayer->getSize().width(), m_contentLayer->getSize().height()); m_contentLayer->markAsDirty(m_dirtyRegion); m_dirtyRegion.setEmpty(); m_contentLayer->needsRepaint(); m_needsRepaint = false; return true; } if (m_needsRepaint && m_image && m_newImage) { // We need to tell the GL thread that we will need to repaint the // texture. Only do so if we effectively have a new image! m_contentLayer->markAsDirty(m_dirtyRegion); m_dirtyRegion.setEmpty(); m_contentLayer->needsRepaint(); m_newImage = false; m_needsRepaint = false; return true; } return false; }
void GraphicsLayerTreeBuilder::rebuild(RenderLayer& layer, GraphicsLayerVector& childLayersOfEnclosingLayer) { // Make the layer compositing if necessary, and set up clipping and content layers. // Note that we can only do work here that is independent of whether the descendant layers // have been processed. computeCompositingRequirements() will already have done the repaint if necessary. layer.stackingNode()->updateLayerListsIfNeeded(); const bool hasCompositedLayerMapping = layer.hasCompositedLayerMapping(); CompositedLayerMappingPtr currentCompositedLayerMapping = layer.compositedLayerMapping(); // If this layer has a compositedLayerMapping, then that is where we place subsequent children GraphicsLayers. // Otherwise children continue to append to the child list of the enclosing layer. GraphicsLayerVector layerChildren; GraphicsLayerVector& childList = hasCompositedLayerMapping ? layerChildren : childLayersOfEnclosingLayer; #if !ASSERT_DISABLED LayerListMutationDetector mutationChecker(layer.stackingNode()); #endif if (layer.stackingNode()->isStackingContext()) { RenderLayerStackingNodeIterator iterator(*layer.stackingNode(), NegativeZOrderChildren); while (RenderLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), childList); // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. if (hasCompositedLayerMapping && currentCompositedLayerMapping->foregroundLayer()) childList.append(currentCompositedLayerMapping->foregroundLayer()); } RenderLayerStackingNodeIterator iterator(*layer.stackingNode(), NormalFlowChildren | PositiveZOrderChildren); while (RenderLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), childList); if (hasCompositedLayerMapping) { bool parented = false; if (layer.renderer()->isRenderPart()) parented = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(layer.renderer())); if (!parented) currentCompositedLayerMapping->parentForSublayers()->setChildren(layerChildren); // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer. // Otherwise, the overflow control layers are normal children. if (!currentCompositedLayerMapping->hasClippingLayer() && !currentCompositedLayerMapping->hasScrollingLayer()) { if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForHorizontalScrollbar()) { overflowControlLayer->removeFromParent(); currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer); } if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForVerticalScrollbar()) { overflowControlLayer->removeFromParent(); currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer); } if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForScrollCorner()) { overflowControlLayer->removeFromParent(); currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer); } } if (shouldAppendLayer(layer)) childLayersOfEnclosingLayer.append(currentCompositedLayerMapping->childForSuperlayers()); } }
bool CompositingReasonFinder::requiresCompositingForPositionFixed(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason, bool* needToRecomputeCompositingRequirements) const { if (!(m_compositingTriggers & ViewportConstrainedPositionedTrigger)) return false; if (renderer->style()->position() != FixedPosition) return false; RenderObject* container = renderer->container(); // If the renderer is not hooked up yet then we have to wait until it is. if (!container) { ASSERT(m_renderView.document().lifecycle().state() < DocumentLifecycle::InCompositingUpdate); // FIXME: Remove this and ASSERT(container) once we get rid of the incremental // allocateOrClearCompositedLayerMapping compositing update. This happens when // adding the renderer to the tree because we setStyle before addChild in // createRendererForElementIfNeeded. *needToRecomputeCompositingRequirements = true; return false; } // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements. // They will stay fixed wrt the container rather than the enclosing frame. if (container != &m_renderView) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer; return false; } // If the fixed-position element does not have any scrollable ancestor between it and // its container, then we do not need to spend compositor resources for it. Start by // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below. bool hasScrollableAncestor = false; // The FrameView has the scrollbars associated with the top level viewport, so we have to // check the FrameView in addition to the hierarchy of ancestors. FrameView* frameView = m_renderView.frameView(); if (frameView && frameView->isScrollable()) hasScrollableAncestor = true; RenderLayer* ancestor = layer->parent(); while (ancestor && !hasScrollableAncestor) { if (ancestor->scrollsOverflow()) hasScrollableAncestor = true; if (ancestor->renderer() == &m_renderView) break; ancestor = ancestor->parent(); } if (!hasScrollableAncestor) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors; return false; } // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done. // FIXME: Get rid of this codepath once we get rid of the incremental compositing update in RenderLayer::styleChanged. if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean) { *needToRecomputeCompositingRequirements = true; return layer->hasCompositedLayerMapping(); } bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant(); if (!paintsContent) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent; return false; } // Fixed position elements that are invisible in the current view don't get their own layer. if (FrameView* frameView = m_renderView.frameView()) { ASSERT(m_renderView.document().lifecycle().state() == DocumentLifecycle::InCompositingUpdate); LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect(); LayoutRect layerBounds = layer->boundingBoxForCompositing(layer->compositor()->rootRenderLayer(), RenderLayer::ApplyBoundsChickenEggHacks); if (!viewBounds.intersects(enclosingIntRect(layerBounds))) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView; return false; } } return true; }