TEST_F(VisualRectMappingTest, LayoutInline) { document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); setBodyInnerHTML( "<style>body { margin: 0; }</style>" "<div id='container' style='overflow: scroll; width: 50px; height: 50px'>" " <span><img style='width: 20px; height: 100px'></span>" " <span id=leaf></span></div>"); LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container")); LayoutObject* leaf = container->lastChild(); container->setScrollTop(LayoutUnit(50)); LayoutRect originalRect(0, 60, 20, 80); LayoutRect rect = originalRect; EXPECT_TRUE(leaf->mapToVisualRectInAncestorSpace(container, rect)); rect.move(-container->scrolledContentOffset()); EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80)); rect = originalRect; EXPECT_TRUE(leaf->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(rect, LayoutRect(0, 10, 20, 40)); checkPaintInvalidationStateRectMapping(rect, originalRect, *leaf, layoutView(), layoutView()); rect = LayoutRect(0, 60, 80, 0); EXPECT_TRUE( leaf->mapToVisualRectInAncestorSpace(container, rect, EdgeInclusive)); rect.move(-container->scrolledContentOffset()); EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0)); }
TEST_F(VisualRectMappingTest, LayoutText) { setBodyInnerHTML( "<style>body { margin: 0; }</style>" "<div id='container' style='overflow: scroll; width: 50px; height: 50px'>" " <span><img style='width: 20px; height: 100px'></span>" " text text text text text text text" "</div>"); LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container")); LayoutText* text = toLayoutText(container->lastChild()); container->setScrollTop(LayoutUnit(50)); LayoutRect originalRect(0, 60, 20, 80); LayoutRect rect = originalRect; EXPECT_TRUE(text->mapToVisualRectInAncestorSpace(container, rect)); rect.move(-container->scrolledContentOffset()); EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80)); rect = originalRect; EXPECT_TRUE(text->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(rect, LayoutRect(0, 10, 20, 40)); checkPaintInvalidationStateRectMapping(rect, originalRect, *text, layoutView(), layoutView()); rect = LayoutRect(0, 60, 80, 0); EXPECT_TRUE( text->mapToVisualRectInAncestorSpace(container, rect, EdgeInclusive)); rect.move(-container->scrolledContentOffset()); EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0)); }
void FieldsetPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (m_layoutFieldset.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; LayoutRect paintRect = LayoutRect(paintOffset, m_layoutFieldset.size()); LayoutBox* legend = m_layoutFieldset.findInFlowLegend(); if (!legend) return BoxPainter(m_layoutFieldset).paintMask(paintInfo, paintOffset); if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutFieldset, paintInfo.phase, paintOffset)) return; // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (m_layoutFieldset.style()->isHorizontalWritingMode()) { LayoutUnit yOff = (legend->location().y() > LayoutUnit()) ? LayoutUnit() : (legend->size().height() - m_layoutFieldset.borderTop()) / 2; paintRect.expand(LayoutUnit(), -yOff); paintRect.move(LayoutUnit(), yOff); } else { LayoutUnit xOff = (legend->location().x() > LayoutUnit()) ? LayoutUnit() : (legend->size().width() - m_layoutFieldset.borderLeft()) / 2; paintRect.expand(-xOff, LayoutUnit()); paintRect.move(xOff, LayoutUnit()); } LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutFieldset, paintInfo.phase, paintRect, paintOffset); BoxPainter(m_layoutFieldset).paintMaskImages(paintInfo, paintRect); }
IntRect RenderVideo::videoBox() const { if (m_cachedImageSize.isEmpty() && videoElement()->shouldDisplayPosterImage()) return IntRect(); LayoutSize elementSize; if (videoElement()->shouldDisplayPosterImage()) elementSize = m_cachedImageSize; else elementSize = intrinsicSize(); IntRect contentRect = pixelSnappedIntRect(contentBoxRect()); if (elementSize.isEmpty() || contentRect.isEmpty()) return IntRect(); LayoutRect renderBox = contentRect; LayoutUnit ratio = renderBox.width() * elementSize.height() - renderBox.height() * elementSize.width(); if (ratio > 0) { LayoutUnit newWidth = renderBox.height() * elementSize.width() / elementSize.height(); // Just fill the whole area if the difference is one pixel or less (in both sides) if (renderBox.width() - newWidth > 2) renderBox.setWidth(newWidth); renderBox.move((contentRect.width() - renderBox.width()) / 2, 0); } else if (ratio < 0) { LayoutUnit newHeight = renderBox.width() * elementSize.height() / elementSize.width(); if (renderBox.height() - newHeight > 2) renderBox.setHeight(newHeight); renderBox.move(0, (contentRect.height() - renderBox.height()) / 2); } return pixelSnappedIntRect(renderBox); }
void AccessibilityObject::scrollToGlobalPoint(const IntPoint& globalPoint) const { // Search up the parent chain and create a vector of all scrollable parent objects // and ending with this object itself. Vector<const AccessibilityObject*> objects; AccessibilityObject* parentObject; for (parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) { if (parentObject->getScrollableAreaIfScrollable()) objects.prepend(parentObject); } objects.append(this); // Start with the outermost scrollable (the main window) and try to scroll the // next innermost object to the given point. int offsetX = 0, offsetY = 0; IntPoint point = globalPoint; size_t levels = objects.size() - 1; for (size_t i = 0; i < levels; i++) { const AccessibilityObject* outer = objects[i]; const AccessibilityObject* inner = objects[i + 1]; ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable(); LayoutRect innerRect = inner->isAccessibilityScrollView() ? inner->parentObject()->elementRect() : inner->elementRect(); LayoutRect objectRect = innerRect; IntPoint scrollPosition = scrollableArea->scrollPosition(); // Convert the object rect into local coordinates. objectRect.move(offsetX, offsetY); if (!outer->isAccessibilityScrollView()) objectRect.move(scrollPosition.x(), scrollPosition.y()); int desiredX = computeBestScrollOffset( 0, objectRect.x(), objectRect.maxX(), objectRect.x(), objectRect.maxX(), point.x(), point.x()); int desiredY = computeBestScrollOffset( 0, objectRect.y(), objectRect.maxY(), objectRect.y(), objectRect.maxY(), point.y(), point.y()); outer->scrollTo(IntPoint(desiredX, desiredY)); if (outer->isAccessibilityScrollView() && !inner->isAccessibilityScrollView()) { // If outer object we just scrolled is a scroll view (main window or iframe) but the // inner object is not, keep track of the coordinate transformation to apply to // future nested calculations. scrollPosition = scrollableArea->scrollPosition(); offsetX -= (scrollPosition.x() + point.x()); offsetY -= (scrollPosition.y() + point.y()); point.move(scrollPosition.x() - innerRect.x(), scrollPosition.y() - innerRect.y()); } else if (inner->isAccessibilityScrollView()) { // Otherwise, if the inner object is a scroll view, reset the coordinate transformation. offsetX = 0; offsetY = 0; } } }
void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; LayoutRect paintRect = LayoutRect(paintOffset, size()); RenderBox* legend = findLegend(); if (!legend) return RenderBlockFlow::paintMask(paintInfo, paintOffset); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style().isHorizontalWritingMode()) { LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2; paintRect.expand(0, -yOff); paintRect.move(0, yOff); } else { LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2; paintRect.expand(-xOff, 0); paintRect.move(xOff, 0); } paintMaskImages(paintInfo, paintRect); }
IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const { // Compute an offset between the part renderer and the input renderer. LayoutSize offsetFromInputRenderer = -partRenderer->offsetFromAncestorContainer(inputRenderer); // Move the rect into partRenderer's coords. partRect.move(offsetFromInputRenderer); // Account for the local drawing offset. partRect.move(localOffset.x(), localOffset.y()); return pixelSnappedIntRect(partRect); }
void RenderView::adjustViewportConstrainedOffset(LayoutRect& rect, ViewportConstrainedPosition viewportConstraint) const { if (viewportConstraint != IsFixedPosition) return; if (m_frameView) { rect.move(m_frameView->scrollOffsetForFixedPosition()); // If we have a pending scroll, invalidate the previous scroll position. if (!m_frameView->pendingScrollDelta().isZero()) rect.move(-LayoutSize(m_frameView->pendingScrollDelta())); } }
static LayoutRect rectToAbsoluteCoordinates(Frame* initialFrame, const LayoutRect& initialRect) { LayoutRect rect = initialRect; for (Frame* frame = initialFrame; frame; frame = frame->tree().parent()) { if (Element* element = frame->ownerElement()) { do { rect.move(element->offsetLeft(), element->offsetTop()); } while ((element = element->offsetParent())); rect.move((-frame->view()->scrollOffset())); } } return rect; }
void FontCascade::adjustSelectionRectForComplexText(const TextRun& run, LayoutRect& selectionRect, int from, int to) const { UniscribeController it(this, run); it.advance(from); float beforeWidth = it.runWidthSoFar(); it.advance(to); float afterWidth = it.runWidthSoFar(); if (run.rtl()) { it.advance(run.length()); selectionRect.move(it.runWidthSoFar() - afterWidth, 0); } else selectionRect.move(beforeWidth, 0); selectionRect.setWidth(afterWidth - beforeWidth); }
void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { IntPoint contentPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location()); // Tell the widget to paint now. This is the only time the widget is allowed // to paint itself. That way it will composite properly with z-indexed layers. LayoutRect paintRect = paintInfo.rect; IntPoint widgetLocation = m_widget->frameRect().location(); IntSize widgetPaintOffset = contentPaintOffset - widgetLocation; // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer, // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing. if (!widgetPaintOffset.isZero()) { paintInfo.context().translate(widgetPaintOffset); paintRect.move(-widgetPaintOffset); } // FIXME: Remove repaintrect encolsing/integral snapping when RenderWidget becomes device pixel snapped. m_widget->paint(paintInfo.context(), snappedIntRect(paintRect)); if (!widgetPaintOffset.isZero()) paintInfo.context().translate(-widgetPaintOffset); if (is<FrameView>(*m_widget)) { FrameView& frameView = downcast<FrameView>(*m_widget); bool runOverlapTests = !frameView.useSlowRepaintsIfNotOverlapped(); if (paintInfo.overlapTestRequests && runOverlapTests) { ASSERT(!paintInfo.overlapTestRequests->contains(this)); paintInfo.overlapTestRequests->set(this, m_widget->frameRect()); } } }
void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint adjustedPaintOffset = paintOffset + location(); // Tell the widget to paint now. This is the only time the widget is allowed // to paint itself. That way it will composite properly with z-indexed layers. IntPoint widgetLocation = m_widget->frameRect().location(); IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()), roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop())); LayoutRect paintRect = paintInfo.rect; LayoutSize widgetPaintOffset = paintLocation - widgetLocation; // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer, // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing. if (!widgetPaintOffset.isZero()) { paintInfo.context->translate(widgetPaintOffset); paintRect.move(-widgetPaintOffset); } m_widget->paint(paintInfo.context, pixelSnappedIntRect(paintRect)); if (!widgetPaintOffset.isZero()) paintInfo.context->translate(-widgetPaintOffset); if (m_widget->isFrameView()) { FrameView* frameView = toFrameView(m_widget.get()); bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContentIncludingDescendants(); if (paintInfo.overlapTestRequests && runOverlapTests) { ASSERT(!paintInfo.overlapTestRequests->contains(this)); paintInfo.overlapTestRequests->set(this, m_widget->frameRect()); } } }
void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& rect, bool fixed) const { // If a container was specified, and was not 0 or the RenderView, // then we should have found it by now. ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this); if (printing()) return; if (style()->isFlippedBlocksWritingMode()) { // We have to flip by hand since the view's logical height has not been determined. We // can use the viewport width and height. if (style()->isHorizontalWritingMode()) rect.setY(viewHeight() - rect.maxY()); else rect.setX(viewWidth() - rect.maxX()); } if (fixed && m_frameView) rect.move(m_frameView->scrollOffsetForFixedPosition()); // Apply our transform if we have one (because of full page zooming). if (!repaintContainer && m_layer && m_layer->transform()) rect = m_layer->transform()->mapRect(rect); }
LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize) const { LayoutRect contentRect = contentBoxRect(); ObjectFit objectFit = style().objectFit(); if (objectFit == ObjectFitFill) return contentRect; if (!intrinsicSize.width() || !intrinsicSize.height()) return contentRect; LayoutRect finalRect = contentRect; switch (objectFit) { case ObjectFitContain: case ObjectFitScaleDown: case ObjectFitCover: finalRect.setSize(finalRect.size().fitToAspectRatio(intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow : AspectRatioFitShrink)); if (objectFit != ObjectFitScaleDown || finalRect.width() <= intrinsicSize.width()) break; // fall through case ObjectFitNone: finalRect.setSize(intrinsicSize); break; case ObjectFitFill: ASSERT_NOT_REACHED(); } // FIXME: This is where object-position should be taken into account, but since it's not // implemented yet, assume the initial value of "50% 50%". LayoutUnit xOffset = (contentRect.width() - finalRect.width()) / 2; LayoutUnit yOffset = (contentRect.height() - finalRect.height()) / 2; finalRect.move(xOffset, yOffset); return finalRect; }
bool BlockPainter::intersectsPaintRect( const PaintInfo& paintInfo, const LayoutPoint& adjustedPaintOffset) const { LayoutRect overflowRect; if (paintInfo.isPrinting() && m_layoutBlock.isAnonymousBlock() && m_layoutBlock.childrenInline()) { // For case <a href="..."><div>...</div></a>, when m_layoutBlock is the // anonymous container of <a>, the anonymous container's visual overflow is // empty, but we need to continue painting to output <a>'s PDF URL rect // which covers the continuations, as if we included <a>'s PDF URL rect into // m_layoutBlock's visual overflow. Vector<LayoutRect> rects; m_layoutBlock.addElementVisualOverflowRects(rects, LayoutPoint()); overflowRect = unionRect(rects); } overflowRect.unite(m_layoutBlock.visualOverflowRect()); bool usesCompositedScrolling = m_layoutBlock.hasOverflowModel() && m_layoutBlock.usesCompositedScrolling(); if (usesCompositedScrolling) { LayoutRect layoutOverflowRect = m_layoutBlock.layoutOverflowRect(); overflowRect.unite(layoutOverflowRect); } m_layoutBlock.flipForWritingMode(overflowRect); // Scrolling is applied in physical space, which is why it is after the flip // above. if (usesCompositedScrolling) { overflowRect.move(-m_layoutBlock.scrolledContentOffset()); } overflowRect.moveBy(adjustedPaintOffset); return paintInfo.cullRect().intersectsCullRect(overflowRect); }
LayoutRect SVGRenderSupport::clippedOverflowRectForPaintInvalidation(const RenderObject* object, const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) { // Return early for any cases where we don't actually paint if (object->style()->visibility() != VISIBLE && !object->enclosingLayer()->hasVisibleContent()) return LayoutRect(); // Pass our local paint rect to computeRectForPaintInvalidation() which will // map to parent coords and recurse up the parent chain. FloatRect paintInvalidationRect = object->paintInvalidationRectInLocalCoordinates(); paintInvalidationRect.inflate(object->style()->outlineWidth()); if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer)) { // Compute accumulated SVG transform and apply to local paint rect. AffineTransform transform = paintInvalidationState->svgTransform() * object->localToParentTransform(); paintInvalidationRect = transform.mapRect(paintInvalidationRect); // FIXME: These are quirks carried forward from the old paint invalidation infrastructure. LayoutRect rect = enclosingIntRectIfNotEmpty(paintInvalidationRect); // Offset by SVG root paint offset and apply clipping as needed. rect.move(paintInvalidationState->paintOffset()); if (paintInvalidationState->isClipped()) rect.intersect(paintInvalidationState->clipRect()); return rect; } LayoutRect rect; const RenderSVGRoot& svgRoot = mapRectToSVGRootForPaintInvalidation(object, paintInvalidationRect, rect); svgRoot.mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, paintInvalidationState); return rect; }
void RenderBlockFlow::invalidatePaintForOverflow() { // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines // it had to lay out. We wouldn't need the hasOverflowClip() hack in that case either. LayoutUnit paintInvalidationLogicalLeft = logicalLeftVisualOverflow(); LayoutUnit paintInvalidationLogicalRight = logicalRightVisualOverflow(); if (hasOverflowClip()) { // If we have clipped overflow, we should use layout overflow as well, since visual overflow from lines didn't propagate to our block's overflow. // Note the old code did this as well but even for overflow:visible. The addition of hasOverflowClip() at least tightens up the hack a bit. // layoutInlineChildren should be patched to compute the entire paint invalidation rect. paintInvalidationLogicalLeft = std::min(paintInvalidationLogicalLeft, logicalLeftLayoutOverflow()); paintInvalidationLogicalRight = std::max(paintInvalidationLogicalRight, logicalRightLayoutOverflow()); } LayoutRect paintInvalidationRect = LayoutRect(paintInvalidationLogicalLeft, m_paintInvalidationLogicalTop, paintInvalidationLogicalRight - paintInvalidationLogicalLeft, m_paintInvalidationLogicalBottom - m_paintInvalidationLogicalTop); if (hasOverflowClip()) { // Adjust the paint invalidation rect for scroll offset paintInvalidationRect.move(-scrolledContentOffset()); // Don't allow this rect to spill out of our overflow box. paintInvalidationRect.intersect(LayoutRect(LayoutPoint(), size())); } // Make sure the rect is still non-empty after intersecting for overflow above if (!paintInvalidationRect.isEmpty()) { // Hits in media/event-attributes.html DisableCompositingQueryAsserts disabler; invalidatePaintRectangle(paintInvalidationRect); // We need to do a partial paint invalidation of our content. } m_paintInvalidationLogicalTop = 0; m_paintInvalidationLogicalBottom = 0; }
LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize) const { LayoutRect contentRect = contentBoxRect(); if (intrinsicSize.isEmpty()) return contentRect; ObjectFit objectFit = style().objectFit(); LayoutRect finalRect = contentRect; switch (objectFit) { case ObjectFitContain: case ObjectFitScaleDown: case ObjectFitCover: finalRect.setSize(finalRect.size().fitToAspectRatio(intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow : AspectRatioFitShrink)); if (objectFit != ObjectFitScaleDown || finalRect.width() <= intrinsicSize.width()) break; FALLTHROUGH; case ObjectFitNone: finalRect.setSize(intrinsicSize); break; case ObjectFitFill: break; } LengthPoint objectPosition = style().objectPosition(); LayoutUnit xOffset = minimumValueForLength(objectPosition.x(), contentRect.width() - finalRect.width()); LayoutUnit yOffset = minimumValueForLength(objectPosition.y(), contentRect.height() - finalRect.height()); finalRect.move(xOffset, yOffset); return finalRect; }
static LayoutRect rectToAbsoluteCoordinates(LocalFrame* initialFrame, const LayoutRect& initialRect) { LayoutRect rect = initialRect; for (Frame* frame = initialFrame; frame; frame = frame->tree().parent()) { if (!frame->isLocalFrame()) continue; // FIXME: Spatial navigation is broken for OOPI. if (Element* element = frame->deprecatedLocalOwner()) { do { rect.move(element->offsetLeft(), element->offsetTop()); } while ((element = element->offsetParent())); rect.move((-toLocalFrame(frame)->view()->scrollOffset())); } } return rect; }
BoxClipper::BoxClipper(const LayoutBox& box, const PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset, ContentsClipBehavior contentsClipBehavior) : m_box(box) , m_paintInfo(paintInfo) , m_clipType(DisplayItem::UninitializedType) { ASSERT(m_paintInfo.phase != PaintPhaseSelfBlockBackgroundOnly && m_paintInfo.phase != PaintPhaseSelfOutlineOnly); if (m_paintInfo.phase == PaintPhaseMask) return; if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { const auto* objectProperties = m_box.objectPaintProperties(); if (objectProperties && objectProperties->overflowClip()) { PaintChunkProperties properties(paintInfo.context.getPaintController().currentPaintChunkProperties()); properties.clip = objectProperties->overflowClip(); m_scopedClipProperty.emplace(paintInfo.context.getPaintController(), properties); } return; } bool isControlClip = m_box.hasControlClip(); bool isOverflowOrContainmentClip = (m_box.hasOverflowClip() && !m_box.layer()->isSelfPaintingLayer()) || m_box.style()->containsPaint(); if (!isControlClip && !isOverflowOrContainmentClip) return; LayoutRect clipRect = isControlClip ? m_box.controlClipRect(accumulatedOffset) : m_box.overflowClipRect(accumulatedOffset); FloatRoundedRect clipRoundedRect(0, 0, 0, 0); bool hasBorderRadius = m_box.style()->hasBorderRadius(); if (hasBorderRadius) clipRoundedRect = m_box.style()->getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, m_box.size())); // Selection does not affect visual overflow, so this optimization is invalid if selection // is present. if (contentsClipBehavior == SkipContentsClipIfPossible && box.getSelectionState() == SelectionNone) { LayoutRect contentsVisualOverflow = m_box.contentsVisualOverflowRect(); if (contentsVisualOverflow.isEmpty()) return; LayoutRect conservativeClipRect = clipRect; if (hasBorderRadius) conservativeClipRect.intersect(LayoutRect(clipRoundedRect.radiusCenterRect())); conservativeClipRect.moveBy(-accumulatedOffset); if (m_box.hasLayer()) conservativeClipRect.move(m_box.scrolledContentOffset()); if (conservativeClipRect.contains(contentsVisualOverflow)) return; } if (!m_paintInfo.context.getPaintController().displayItemConstructionIsDisabled()) { m_clipType = m_paintInfo.displayItemTypeForClipping(); Vector<FloatRoundedRect> roundedRects; if (hasBorderRadius) roundedRects.append(clipRoundedRect); m_paintInfo.context.getPaintController().createAndAppend<ClipDisplayItem>(m_box, m_clipType, pixelSnappedIntRect(clipRect), roundedRects); } }
void InlineTextBox::move(const LayoutSize& delta) { InlineBox::move(delta); if (!knownToHaveNoOverflow()) { LayoutRect logicalOverflowRect = this->logicalOverflowRect(); logicalOverflowRect.move(isHorizontal() ? delta : delta.transposedSize()); setLogicalOverflowRect(logicalOverflowRect); } }
LayoutRect BlockPainter::overflowRectForPaintRejection() const { LayoutRect overflowRect = m_layoutBlock.visualOverflowRect(); if (!m_layoutBlock.hasOverflowModel() || !m_layoutBlock.usesCompositedScrolling()) return overflowRect; overflowRect.unite(m_layoutBlock.layoutOverflowRect()); overflowRect.move(-m_layoutBlock.scrolledContentOffset()); return overflowRect; }
bool BlockPainter::intersectsPaintRect(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const { LayoutRect overflowRect = m_layoutBlock.visualOverflowRect(); if (m_layoutBlock.hasOverflowModel() && m_layoutBlock.usesCompositedScrolling()) { overflowRect.unite(m_layoutBlock.layoutOverflowRect()); overflowRect.move(-m_layoutBlock.scrolledContentOffset()); } m_layoutBlock.flipForWritingMode(overflowRect); overflowRect.moveBy(paintOffset + m_layoutBlock.location()); return paintInfo.cullRect().intersectsCullRect(overflowRect); }
void LayoutMultiColumnSet::addOverflowFromChildren() { LayoutRect overflowRect; for (const auto& group : m_fragmentainerGroups) { LayoutRect rect = group.calculateOverflow(); rect.move(group.offsetFromColumnSet()); overflowRect.unite(rect); } addLayoutOverflow(overflowRect); addContentsVisualOverflow(overflowRect); }
LayoutRect AccessibilityScrollView::elementRect() const { if (!m_scrollView) return LayoutRect(); LayoutRect rect = m_scrollView->frameRect(); float topContentInset = m_scrollView->topContentInset(); // Top content inset pushes the frame down and shrinks it. rect.move(0, topContentInset); rect.contract(0, topContentInset); return rect; }
void ShadowData::adjustRectForShadow(LayoutRect& rect, int additionalOutlineSize) const { int shadowLeft = 0; int shadowRight = 0; int shadowTop = 0; int shadowBottom = 0; calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom); rect.move(shadowLeft, shadowTop); rect.setWidth(rect.width() - shadowLeft + shadowRight); rect.setHeight(rect.height() - shadowTop + shadowBottom); }
static PassRefPtr<InspectorObject> buildObjectForRegionHighlight(FrameView* mainView, RenderRegion* region) { FrameView* containingView = region->frame().view(); if (!containingView) return nullptr; RenderBlockFlow* regionContainer = toRenderBlockFlow(region->parent()); LayoutRect borderBox = regionContainer->borderBoxRect(); borderBox.setWidth(borderBox.width() + regionContainer->verticalScrollbarWidth()); borderBox.setHeight(borderBox.height() + regionContainer->horizontalScrollbarHeight()); // Create incoming and outgoing boxes that we use to chain the regions toghether. const LayoutSize linkBoxSize(10, 10); const LayoutSize linkBoxMidpoint(linkBoxSize.width() / 2, linkBoxSize.height() / 2); LayoutRect incomingRectBox = LayoutRect(borderBox.location() - linkBoxMidpoint, linkBoxSize); LayoutRect outgoingRectBox = LayoutRect(borderBox.location() - linkBoxMidpoint + borderBox.size(), linkBoxSize); // Move the link boxes slightly inside the region border box. LayoutUnit maxUsableHeight = std::max(LayoutUnit(), borderBox.height() - linkBoxMidpoint.height()); LayoutUnit linkBoxVerticalOffset = std::min(LayoutUnit::fromPixel(15), maxUsableHeight); incomingRectBox.move(0, linkBoxVerticalOffset); outgoingRectBox.move(0, -linkBoxVerticalOffset); FloatQuad borderRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(borderBox)); FloatQuad incomingRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(incomingRectBox)); FloatQuad outgoingRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(outgoingRectBox)); contentsQuadToPage(mainView, containingView, borderRectQuad); contentsQuadToPage(mainView, containingView, incomingRectQuad); contentsQuadToPage(mainView, containingView, outgoingRectQuad); RefPtr<InspectorObject> regionObject = InspectorObject::create(); regionObject->setArray("borderQuad", buildArrayForQuad(borderRectQuad)); regionObject->setArray("incomingQuad", buildArrayForQuad(incomingRectQuad)); regionObject->setArray("outgoingQuad", buildArrayForQuad(outgoingRectQuad)); return regionObject.release(); }
LayoutRect RenderReplaced::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const { if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. LayoutRect r = unionRect(localSelectionRect(false), visualOverflowRect()); // FIXME: layoutDelta needs to be applied in parts before/after transforms and // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308 r.move(view().layoutDelta()); return computeRectForRepaint(r, repaintContainer); }
LayoutRect RenderNamedFlowFragment::flowThreadPortionRectForClipping(bool isFirstRegionInRange, bool isLastRegionInRange) const { // Elements flowed into a region should not be painted past the region's content box // if they continue to flow into another region in that direction. // If they do not continue into another region in that direction, they should be // painted all the way to the region's border box. // Regions with overflow:hidden will apply clip at the border box, not the content box. LayoutRect clippingRect = flowThreadPortionRect(); RenderBlockFlow& container = fragmentContainer(); if (container.style().hasPadding()) { if (isFirstRegionInRange) { if (flowThread()->isHorizontalWritingMode()) { clippingRect.move(0, -container.paddingBefore()); clippingRect.expand(0, container.paddingBefore()); } else { clippingRect.move(-container.paddingBefore(), 0); clippingRect.expand(container.paddingBefore(), 0); } } if (isLastRegionInRange) { if (flowThread()->isHorizontalWritingMode()) clippingRect.expand(0, container.paddingAfter()); else clippingRect.expand(container.paddingAfter(), 0); } if (flowThread()->isHorizontalWritingMode()) { clippingRect.move(-container.paddingStart(), 0); clippingRect.expand(container.paddingStart() + container.paddingEnd(), 0); } else { clippingRect.move(0, -container.paddingStart()); clippingRect.expand(0, container.paddingStart() + container.paddingEnd()); } } return clippingRect; }
LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect) { // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect". LayoutRect rectForRepaint = dirtyRect; if (hasFilterThatMovesPixels()) { // Note that the outsets are reversed here because we are going backwards -> we have the dirty rect and // need to find out what is the rectangle that might influence the result inside that dirty rect. rectForRepaint.move(-m_outsets.right(), -m_outsets.bottom()); rectForRepaint.expand(m_outsets.left() + m_outsets.right(), m_outsets.top() + m_outsets.bottom()); } rectForRepaint.intersect(filterBoxRect); return rectForRepaint; }