IntRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return IntRect(); // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. IntRect r = unionRect(localSelectionRect(false), visualOverflowRect()); RenderView* v = view(); if (v) { // 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(v->layoutDelta()); } if (style()) { if (style()->hasAppearance()) // The theme may wish to inflate the rect used when repainting. theme()->adjustRepaintRect(this, r); if (v) r.inflate(style()->outlineSize()); } computeRectForRepaint(repaintContainer, r); return r; }
LayoutRect MultiColumnFragmentainerGroup::fragmentsBoundingBox(const LayoutRect& boundingBoxInFlowThread) const { // Find the start and end column intersected by the bounding box. LayoutRect flippedBoundingBoxInFlowThread(boundingBoxInFlowThread); LayoutFlowThread* flowThread = m_columnSet.flowThread(); flowThread->flipForWritingMode(flippedBoundingBoxInFlowThread); bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode(); LayoutUnit boundingBoxLogicalTop = isHorizontalWritingMode ? flippedBoundingBoxInFlowThread.y() : flippedBoundingBoxInFlowThread.x(); LayoutUnit boundingBoxLogicalBottom = isHorizontalWritingMode ? flippedBoundingBoxInFlowThread.maxY() : flippedBoundingBoxInFlowThread.maxX(); if (boundingBoxLogicalBottom <= logicalTopInFlowThread() || boundingBoxLogicalTop >= logicalBottomInFlowThread()) return LayoutRect(); // The bounding box doesn't intersect this fragmentainer group. unsigned startColumn; unsigned endColumn; columnIntervalForBlockRangeInFlowThread(boundingBoxLogicalTop, boundingBoxLogicalBottom, startColumn, endColumn); LayoutRect startColumnFlowThreadOverflowPortion = flowThreadPortionOverflowRectAt(startColumn); flowThread->flipForWritingMode(startColumnFlowThreadOverflowPortion); LayoutRect startColumnRect(boundingBoxInFlowThread); startColumnRect.intersect(startColumnFlowThreadOverflowPortion); startColumnRect.move(flowThreadTranslationAtOffset(logicalTopInFlowThreadAt(startColumn))); if (startColumn == endColumn) return startColumnRect; // It all takes place in one column. We're done. LayoutRect endColumnFlowThreadOverflowPortion = flowThreadPortionOverflowRectAt(endColumn); flowThread->flipForWritingMode(endColumnFlowThreadOverflowPortion); LayoutRect endColumnRect(boundingBoxInFlowThread); endColumnRect.intersect(endColumnFlowThreadOverflowPortion); endColumnRect.move(flowThreadTranslationAtOffset(logicalTopInFlowThreadAt(endColumn))); return unionRect(startColumnRect, endColumnRect); }
void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const { // Apply our local transforms (except for x/y translation), then our shadow, // and then call RenderBox's method to handle all the normal CSS Box model bits repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect); const SVGRenderStyle& svgStyle = style().svgStyle(); if (const ShadowData* shadow = svgStyle.shadow()) shadow->adjustRectForShadow(repaintRect); // Apply initial viewport clip if (shouldApplyViewportClip()) repaintRect.intersect(pixelSnappedBorderBoxRect()); if (m_hasBoxDecorations || hasRenderOverflow()) { // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect()); repaintRect.unite(decoratedRepaintRect); } LayoutRect rect = enclosingIntRect(repaintRect); RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed); repaintRect = rect; }
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 LayoutSVGRoot::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const { // This is an open-coded aggregate of SVGLayoutSupport::clippedOverflowRectForPaintInvalidation, // LayoutSVGRoot::mapToVisibleRectInContainerSpace and LayoutReplaced::clippedOverflowRectForPaintInvalidation. // The reason for this is to optimize/minimize the paint invalidation rect when the box is not "decorated" // (does not have background/border/etc.) // Return early for any cases where we don't actually paint. if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); // Compute the paint invalidation rect of the content of the SVG in the border-box coordinate space. FloatRect contentPaintInvalidationRect = paintInvalidationRectInLocalCoordinates(); contentPaintInvalidationRect = m_localToBorderBoxTransform.mapRect(contentPaintInvalidationRect); // Apply initial viewport clip, overflow:visible content is added to visualOverflow // but the most common case is that overflow is hidden, so always intersect. contentPaintInvalidationRect.intersect(pixelSnappedBorderBoxRect()); LayoutRect paintInvalidationRect = enclosingLayoutRect(contentPaintInvalidationRect); // If the box is decorated or is overflowing, extend it to include the border-box and overflow. if (m_hasBoxDecorationBackground || hasOverflowModel()) { // The selectionRect can project outside of the overflowRect, so take their union // for paint invalidation to avoid selection painting glitches. LayoutRect decoratedPaintInvalidationRect = unionRect(localSelectionRect(), visualOverflowRect()); paintInvalidationRect.unite(decoratedPaintInvalidationRect); } // Compute the paint invalidation rect in the parent coordinate space. LayoutRect rect(enclosingIntRect(paintInvalidationRect)); LayoutReplaced::mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, paintInvalidationState); return rect; }
FloatRect FEDropShadow::mapEffect(const FloatSize& stdDeviation, const FloatPoint& offset, const FloatRect& rect) { FloatRect offsetRect = rect; offsetRect.moveBy(offset); FloatRect blurredRect = FEGaussianBlur::mapEffect(stdDeviation, offsetRect); return unionRect(blurredRect, rect); }
FloatRect FEComposite::determineAbsolutePaintRect(const FloatRect& originalRequestedRect) { FloatRect requestedRect = originalRequestedRect; if (clipsToBounds()) requestedRect.intersect(maxEffectRect()); // We may be called multiple times if result is used more than once. Return // quickly if nothing new is required. if (absolutePaintRect().contains(enclosingIntRect(requestedRect))) return requestedRect; // No mapPaintRect required for FEComposite. FloatRect input1Rect = inputEffect(1)->determineAbsolutePaintRect(requestedRect); FloatRect affectedRect; switch (m_type) { case FECOMPOSITE_OPERATOR_IN: // 'in' has output only in the intersection of both inputs. affectedRect = intersection(input1Rect, inputEffect(0)->determineAbsolutePaintRect(input1Rect)); break; case FECOMPOSITE_OPERATOR_ATOP: // 'atop' has output only in the extents of the second input. // Make sure first input knows where it needs to produce output. inputEffect(0)->determineAbsolutePaintRect(input1Rect); affectedRect = input1Rect; break; case FECOMPOSITE_OPERATOR_ARITHMETIC: if (k4() > 0) { // Make sure first input knows where it needs to produce output. inputEffect(0)->determineAbsolutePaintRect(requestedRect); // Arithmetic with non-zero k4 may influnce the complete filter primitive // region. So we can't optimize the paint region here. affectedRect = requestedRect; break; } if (k2() <= 0) { // Input 0 does not appear where input 1 is not present. FloatRect input0Rect = inputEffect(0)->determineAbsolutePaintRect(input1Rect); if (k3() > 0) { affectedRect = input1Rect; } else { // Just k1 is positive. Use intersection. affectedRect = intersection(input1Rect, input0Rect); } break; } // else fall through to use union default: // Take the union of both input effects. affectedRect = unionRect(input1Rect, inputEffect(0)->determineAbsolutePaintRect(requestedRect)); break; } affectedRect.intersect(requestedRect); addAbsolutePaintRect(affectedRect); return affectedRect; }
FindIndicator::FindIndicator(const WebCore::FloatRect& selectionRectInWindowCoordinates, const Vector<WebCore::FloatRect>& textRectsInSelectionRectCoordinates, float contentImageScaleFactor, PassRefPtr<ShareableBitmap> contentImage) : m_selectionRectInWindowCoordinates(selectionRectInWindowCoordinates) , m_textRectsInSelectionRectCoordinates(textRectsInSelectionRectCoordinates) , m_contentImageScaleFactor(contentImageScaleFactor) , m_contentImage(contentImage) { if (findIndicatorsForTextRectsOverlap(m_textRectsInSelectionRectCoordinates)) { m_textRectsInSelectionRectCoordinates[0] = unionRect(m_textRectsInSelectionRectCoordinates); m_textRectsInSelectionRectCoordinates.shrink(1); } }
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 RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const { if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); FloatRect contentRepaintRect = m_localToBorderBoxTransform.mapRect(repaintRectInLocalCoordinates()); contentRepaintRect.intersect(snappedIntRect(borderBoxRect())); LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect); if (m_hasBoxDecorations || hasRenderOverflow()) repaintRect.unite(unionRect(localSelectionRect(false), visualOverflowRect())); return RenderReplaced::computeRectForRepaint(enclosingIntRect(repaintRect), repaintContainer); }
RectangleT QuadNode::calculateRect( QuadNode* n ) { if (n == NULL) { return RectangleT::Zero; } if (n->leaf_) { Chunk* ck = getSceneManager()->getTerrain()->getChunkFromTopology(n->xNumber_, n->zNumber_); n->rect_ = ck->getRect(); return n->rect_; } return unionRect(n); }
void PaintAggregator::invalidateRect(const IntRect& rect) { // Combine overlapping paints using smallest bounding box. for (size_t i = 0; i < m_update.paintRects.size(); ++i) { const IntRect& existingRect = m_update.paintRects[i]; if (existingRect.contains(rect)) // Optimize out redundancy. return; if (rect.intersects(existingRect) || sharesEdge(rect, existingRect)) { // Re-invalidate in case the union intersects other paint rects. IntRect combinedRect = unionRect(existingRect, rect); m_update.paintRects.remove(i); invalidateRect(combinedRect); return; } } // Add a non-overlapping paint. m_update.paintRects.append(rect); // If the new paint overlaps with a scroll, then it forces an invalidation of // the scroll. If the new paint is contained by a scroll, then trim off the // scroll damage to avoid redundant painting. if (!m_update.scrollRect.isEmpty()) { if (shouldInvalidateScrollRect(rect)) invalidateScrollRect(); else if (m_update.scrollRect.contains(rect)) { m_update.paintRects[m_update.paintRects.size() - 1] = subtractIntersection(rect, m_update.calculateScrollDamage()); if (m_update.paintRects[m_update.paintRects.size() - 1].isEmpty()) m_update.paintRects.remove(m_update.paintRects.size() - 1); } } if (m_update.paintRects.size() > maxPaintRects) combinePaintRects(); // Track how large the paintRects vector grows during an invalidation // sequence. Note: A subsequent invalidation may end up being combined // with all existing paints, which means that tracking the size of // paintRects at the time when popPendingUpdate() is called may mask // certain performance problems. Platform::current()->histogramCustomCounts("MPArch.RW_IntermediatePaintRectCount", m_update.paintRects.size(), 1, 100, 50); }
void CCDelegatedRendererLayerImpl::setRenderPasses(ScopedPtrVector<CCRenderPass>& renderPassesInDrawOrder) { FloatRect oldRootDamage; if (!m_renderPassesInDrawOrder.isEmpty()) oldRootDamage = m_renderPassesInDrawOrder.last()->damageRect(); clearRenderPasses(); for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) { m_renderPassesIndexById.insert(std::pair<CCRenderPass::Id, int>(renderPassesInDrawOrder[i]->id(), i)); m_renderPassesInDrawOrder.append(renderPassesInDrawOrder.take(i)); } renderPassesInDrawOrder.clear(); if (!m_renderPassesInDrawOrder.isEmpty()) { FloatRect newRootDamage = m_renderPassesInDrawOrder.last()->damageRect(); m_renderPassesInDrawOrder.last()->setDamageRect(unionRect(oldRootDamage, newRootDamage)); } }
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()); RenderView* v = view(); if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && v) { // 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(v->layoutDelta()); } if (style()) { if (v) r.inflate(style()->outlineSize()); } computeRectForRepaint(repaintContainer, r); return r; }
Path PathUtilities::pathWithShrinkWrappedRects(const Vector<FloatRect>& rects, float radius) { Path path; if (rects.isEmpty()) return path; if (rects.size() > 20) { path.addRoundedRect(unionRect(rects), FloatSize(radius, radius)); return path; } Vector<FloatRect> sortedRects = rects; std::sort(sortedRects.begin(), sortedRects.end(), [](FloatRect a, FloatRect b) { return b.y() > a.y(); }); FloatPointGraph graph; Vector<FloatPointGraph::Polygon> rectPolygons; rectPolygons.reserveInitialCapacity(sortedRects.size()); for (auto& rect : sortedRects) { bool isContained = false; for (auto& otherRect : sortedRects) { if (&rect == &otherRect) continue; if (otherRect.contains(rect)) { isContained = true; break; } } if (!isContained) rectPolygons.append(edgesForRect(rect, graph)); } Vector<FloatPointGraph::Polygon> polys = unitePolygons(rectPolygons, graph); if (polys.isEmpty()) { path.addRoundedRect(unionRect(sortedRects), FloatSize(radius, radius)); return path; } for (auto& poly : polys) { for (unsigned i = 0; i < poly.size(); i++) { FloatPointGraph::Edge& toEdge = poly[i]; // Connect the first edge to the last. FloatPointGraph::Edge& fromEdge = (i > 0) ? poly[i - 1] : poly[poly.size() - 1]; FloatPoint fromEdgeVec = toFloatPoint(*fromEdge.second - *fromEdge.first); FloatPoint toEdgeVec = toFloatPoint(*toEdge.second - *toEdge.first); // Clamp the radius to no more than half the length of either adjacent edge, // because we want a smooth curve and don't want unequal radii. float clampedRadius = std::min(radius, fabsf(fromEdgeVec.x() ? fromEdgeVec.x() : fromEdgeVec.y()) / 2); clampedRadius = std::min(clampedRadius, fabsf(toEdgeVec.x() ? toEdgeVec.x() : toEdgeVec.y()) / 2); FloatPoint fromEdgeNorm = fromEdgeVec; fromEdgeNorm.normalize(); FloatPoint toEdgeNorm = toEdgeVec; toEdgeNorm.normalize(); // Project the radius along the incoming and outgoing edge. FloatSize fromOffset = clampedRadius * toFloatSize(fromEdgeNorm); FloatSize toOffset = clampedRadius * toFloatSize(toEdgeNorm); if (!i) path.moveTo(*fromEdge.second - fromOffset); else path.addLineTo(*fromEdge.second - fromOffset); path.addArcTo(*fromEdge.second, *toEdge.first + toOffset, clampedRadius); } path.closeSubpath(); } return path; }