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);
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
0
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);
}
Example #7
0
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);
    }
}
Example #9
0
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);
}
Example #11
0
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);
}
Example #12
0
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);
}
Example #13
0
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;
}
Example #15
0
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;
}