Example #1
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 #2
0
LayoutRect RenderTextLineBoxes::selectionRectForRange(unsigned start, unsigned end)
{
    LayoutRect rect;
    for (auto box = m_first; box; box = box->nextTextBox()) {
        rect.unite(box->localSelectionRect(start, end));
        rect.unite(ellipsisRectForBox(*box, start, end));
    }
    return rect;
}
Example #3
0
void RenderTextLineBoxes::collectSelectionRectsForRange(unsigned start, unsigned end, Vector<LayoutRect>& rects)
{
    for (auto box = m_first; box; box = box->nextTextBox()) {
        LayoutRect rect;
        rect.unite(box->localSelectionRect(start, end));
        rect.unite(ellipsisRectForBox(*box, start, end));
        if (!rect.size().isEmpty())
            rects.append(rect);
    }
}
Example #4
0
IntRect RenderView::selectionBounds() const
{
    typedef WillBeHeapHashMap<RawPtrWillBeMember<RenderObject>, OwnPtrWillBeMember<RenderSelectionInfo> > SelectionMap;
    SelectionMap selectedObjects;

    RenderObject* os = m_selectionStart;
    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
    while (os && os != stop) {
        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
            selectedObjects.set(os, adoptPtrWillBeNoop(new RenderSelectionInfo(os)));
            RenderBlock* cb = os->containingBlock();
            while (cb && !cb->isRenderView()) {
                OwnPtrWillBeMember<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).storedValue->value;
                if (blockInfo)
                    break;
                blockInfo = adoptPtrWillBeNoop(new RenderSelectionInfo(cb));
                cb = cb->containingBlock();
            }
        }

        os = os->nextInPreOrder();
    }

    // Now create a single bounding box rect that encloses the whole selection.
    LayoutRect selRect;
    SelectionMap::iterator end = selectedObjects.end();
    for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i)
        selRect.unite(i->value->absoluteSelectionRect());

    return pixelSnappedIntRect(selRect);
}
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;
}
LayoutRect LayoutMultiColumnSet::fragmentsBoundingBox(const LayoutRect& boundingBoxInFlowThread) const
{
    LayoutRect result;
    for (const auto& group : m_fragmentainerGroups)
        result.unite(group.fragmentsBoundingBox(boundingBoxInFlowThread));
    return result;
}
Example #7
0
LayoutRect unionRect(const Vector<LayoutRect>& rects) {
  LayoutRect result;

  size_t count = rects.size();
  for (size_t i = 0; i < count; ++i)
    result.unite(rects[i]);

  return result;
}
Example #8
0
LayoutRect SVGInlineFlowBox::calculateBoundaries() const
{
    LayoutRect childRect;
    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
        if (!child->isSVGInlineTextBox() && !child->isSVGInlineFlowBox())
            continue;
        childRect.unite(child->calculateBoundaries());
    }
    return childRect;
}
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;
}
Example #10
0
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 SVGInlineTextBox::calculateBoundaries() const
{
    LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->lineLayoutItem());
    float scalingFactor = lineLayoutItem.scalingFactor();
    ASSERT(scalingFactor);
    LayoutUnit baseline = lineLayoutItem.scaledFont().fontMetrics().floatAscent() / scalingFactor;

    LayoutRect textBoundingRect;
    for (const SVGTextFragment& fragment : m_textFragments)
        textBoundingRect.unite(LayoutRect(fragment.overflowBoundingBox(baseline)));

    return textBoundingRect;
}
LayoutRect InlinePainter::outlinePaintRect(const Vector<LayoutRect>& outlineRects, const LayoutPoint& paintOffset) const
{
    int outlineOutset = m_layoutInline.styleRef().outlineOutsetExtent();
    LayoutRect outlineRect;
    for (const LayoutRect& rect : outlineRects) {
        LayoutRect inflatedRect(rect);
        // Inflate the individual rects instead of the union, to avoid losing
        // rects which have degenerate width/height (== isEmpty() true.)
        inflatedRect.inflate(outlineOutset);
        outlineRect.unite(inflatedRect);
    }
    outlineRect.moveBy(paintOffset);
    return outlineRect;
}
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);
}
LayoutRect LayoutFlowThread::fragmentsBoundingBox(const LayoutRect& layerBoundingBox) const
{
    ASSERT(!m_columnSetsInvalidated);

    LayoutRect result;
    for (auto* columnSet : m_multiColumnSetList) {
        DeprecatedPaintLayerFragments fragments;
        columnSet->collectLayerFragments(fragments, layerBoundingBox, LayoutRect(LayoutRect::infiniteIntRect()));
        for (const auto& fragment : fragments) {
            LayoutRect fragmentRect(layerBoundingBox);
            fragmentRect.intersect(fragment.paginationClip);
            fragmentRect.moveBy(fragment.paginationOffset);
            result.unite(fragmentRect);
        }
    }

    return result;
}
Example #16
0
LayoutRect SVGInlineTextBox::calculateBoundaries() const {
  LineLayoutSVGInlineText lineLayoutItem =
      LineLayoutSVGInlineText(this->getLineLayoutItem());
  const SimpleFontData* fontData = lineLayoutItem.scaledFont().primaryFont();
  DCHECK(fontData);
  if (!fontData)
    return LayoutRect();

  float scalingFactor = lineLayoutItem.scalingFactor();
  ASSERT(scalingFactor);
  LayoutUnit baseline(fontData->getFontMetrics().floatAscent() / scalingFactor);

  LayoutRect textBoundingRect;
  for (const SVGTextFragment& fragment : m_textFragments)
    textBoundingRect.unite(LayoutRect(fragment.overflowBoundingBox(baseline)));

  return textBoundingRect;
}
Example #17
0
// FIXME: This doesn't work for writing modes.
LayoutRect RenderRegion::layoutOverflowRectForBoxForPropagation(const RenderBox* box)
{
    // Only propagate interior layout overflow if we don't clip it.
    LayoutRect rect = box->borderBoxRectInRegion(this);
    rect = rectFlowPortionForBox(box, rect);
    if (!box->hasOverflowClip())
        rect.unite(layoutOverflowRectForBox(box));

    bool hasTransform = box->hasLayer() && box->layer()->transform();
    if (box->isInFlowPositioned() || hasTransform) {
        if (hasTransform)
            rect = box->layer()->currentTransform().mapRect(rect);

        if (box->isInFlowPositioned())
            rect.move(box->offsetForInFlowPosition());
    }

    return rect;
}
Example #18
0
IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
{
    document()->updateStyleIfNeeded();

    typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectionMap;
    SelectionMap selectedObjects;

    RenderObject* os = m_selectionStart;
    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
    while (os && os != stop) {
        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
            selectedObjects.set(os, new RenderSelectionInfo(os, clipToVisibleContent));
            RenderBlock* cb = os->containingBlock();
            while (cb && !cb->isRenderView()) {
                RenderSelectionInfo* blockInfo = selectedObjects.get(cb);
                if (blockInfo)
                    break;
                selectedObjects.set(cb, new RenderSelectionInfo(cb, clipToVisibleContent));
                cb = cb->containingBlock();
            }
        }

        os = os->nextInPreOrder();
    }

    // Now create a single bounding box rect that encloses the whole selection.
    LayoutRect selRect;
    SelectionMap::iterator end = selectedObjects.end();
    for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
        RenderSelectionInfo* info = i->second;
        // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
        LayoutRect currRect = info->rect();
        if (RenderBoxModelObject* repaintContainer = info->repaintContainer()) {
            FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
            currRect = absQuad.enclosingBoundingBox(); 
        }
        selRect.unite(currRect);
        delete info;
    }
    return pixelSnappedIntRect(selRect);
}
LayoutRect RenderFlowThread::fragmentsBoundingBox(const LayoutRect& layerBoundingBox)
{
    ASSERT(!m_regionsInvalidated);

    LayoutRect result;
    for (RenderMultiColumnSetList::const_iterator iter = m_multiColumnSetList.begin(); iter != m_multiColumnSetList.end(); ++iter) {
        RenderMultiColumnSet* columnSet = *iter;
        LayerFragments fragments;
        columnSet->collectLayerFragments(fragments, layerBoundingBox, PaintInfo::infiniteRect());
        for (size_t i = 0; i < fragments.size(); ++i) {
            const LayerFragment& fragment = fragments.at(i);
            LayoutRect fragmentRect(layerBoundingBox);
            fragmentRect.intersect(fragment.paginationClip);
            fragmentRect.moveBy(fragment.paginationOffset);
            result.unite(fragmentRect);
        }
    }

    return result;
}
LayoutRect AccessibilityObject::boundingBoxForQuads(RenderObject* obj, const Vector<FloatQuad>& quads)
{
    ASSERT(obj);
    if (!obj)
        return LayoutRect();
    
    size_t count = quads.size();
    if (!count)
        return LayoutRect();
    
    LayoutRect result;
    for (size_t i = 0; i < count; ++i) {
        LayoutRect r = quads[i].enclosingBoundingBox();
        if (!r.isEmpty()) {
            if (obj->style()->hasAppearance())
                obj->theme()->adjustRepaintRect(obj, r);
            result.unite(r);
        }
    }
    return result;
}
Example #21
0
IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
{
    typedef HashMap<RawPtr<RenderObject>, OwnPtr<RenderSelectionInfo> > SelectionMap;
    SelectionMap selectedObjects;

    RenderObject* os = m_selectionStart;
    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
    while (os && os != stop) {
        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
            selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
            RenderBlock* cb = os->containingBlock();
            while (cb && !cb->isRenderView()) {
                OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).storedValue->value;
                if (blockInfo)
                    break;
                blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
                cb = cb->containingBlock();
            }
        }

        os = os->nextInPreOrder();
    }

    // Now create a single bounding box rect that encloses the whole selection.
    LayoutRect selRect;
    SelectionMap::iterator end = selectedObjects.end();
    for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
        RenderSelectionInfo* info = i->value.get();
        // RenderSelectionInfo::rect() is in the coordinates of the paintInvalidationContainer, so map to page coordinates.
        LayoutRect currRect = info->rect();
        if (const RenderLayerModelObject* paintInvalidationContainer = info->paintInvalidationContainer()) {
            FloatQuad absQuad = paintInvalidationContainer->localToAbsoluteQuad(FloatRect(currRect));
            currRect = absQuad.enclosingBoundingBox();
        }
        selRect.unite(currRect);
    }
    return pixelSnappedIntRect(selRect);
}
Example #22
0
LayoutRect SVGInlineTextBox::calculateBoundaries() const
{
    LayoutRect textRect;

    LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(this->layoutObject());

    float scalingFactor = textLayoutObject.scalingFactor();
    ASSERT(scalingFactor);

    LayoutUnit baseline = textLayoutObject.scaledFont().fontMetrics().floatAscent() / scalingFactor;

    AffineTransform fragmentTransform;
    unsigned textFragmentsSize = m_textFragments.size();
    for (unsigned i = 0; i < textFragmentsSize; ++i) {
        const SVGTextFragment& fragment = m_textFragments.at(i);
        FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
        fragment.buildFragmentTransform(fragmentTransform);
        fragmentRect = fragmentTransform.mapRect(fragmentRect);

        textRect.unite(LayoutRect(fragmentRect));
    }

    return textRect;
}
Example #23
0
// Bounds of the LayoutObject relative to the scroller's visible content rect.
static LayoutRect relativeBounds(const LayoutObject* layoutObject,
                                 const ScrollableArea* scroller) {
  LayoutRect localBounds;
  if (layoutObject->isBox()) {
    localBounds = toLayoutBox(layoutObject)->borderBoxRect();
    if (!layoutObject->hasOverflowClip()) {
      // borderBoxRect doesn't include overflow content and floats.
      LayoutUnit maxHeight =
          std::max(localBounds.height(),
                   toLayoutBox(layoutObject)->layoutOverflowRect().height());
      if (layoutObject->isLayoutBlockFlow() &&
          toLayoutBlockFlow(layoutObject)->containsFloats()) {
        // Note that lowestFloatLogicalBottom doesn't include floating
        // grandchildren.
        maxHeight = std::max(
            maxHeight,
            toLayoutBlockFlow(layoutObject)->lowestFloatLogicalBottom());
      }
      localBounds.setHeight(maxHeight);
    }
  } else if (layoutObject->isText()) {
    // TODO(skobes): Use first and last InlineTextBox only?
    for (InlineTextBox* box = toLayoutText(layoutObject)->firstTextBox(); box;
         box = box->nextTextBox())
      localBounds.unite(box->frameRect());
  } else {
    // Only LayoutBox and LayoutText are supported.
    ASSERT_NOT_REACHED();
  }

  LayoutRect relativeBounds = LayoutRect(
      scroller->localToVisibleContentQuad(FloatRect(localBounds), layoutObject)
          .boundingBox());

  return relativeBounds;
}
Example #24
0
void InlinePainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    const ComputedStyle& styleToUse = m_layoutInline.styleRef();
    if (!styleToUse.hasOutline())
        return;

    if (styleToUse.outlineStyleIsAuto()) {
        if (LayoutTheme::theme().shouldDrawDefaultFocusRing(&m_layoutInline)) {
            Vector<LayoutRect> focusRingRects;
            m_layoutInline.addFocusRingRects(focusRingRects, paintOffset);
            LayoutRect focusRingBoundingRect;
            for (const auto& rect : focusRingRects)
                focusRingBoundingRect.unite(rect);

            LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutInline, paintInfo.phase, focusRingBoundingRect);
            if (recorder.canUseCachedDrawing())
                return;

            // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
            ObjectPainter(m_layoutInline).paintFocusRing(paintInfo, styleToUse, focusRingRects);
        }
        return;
    }

    if (styleToUse.outlineStyle() == BNONE)
        return;

    Vector<LayoutRect> rects;

    rects.append(LayoutRect());
    for (InlineFlowBox* curr = m_layoutInline.firstLineBox(); curr; curr = curr->nextLineBox()) {
        RootInlineBox& root = curr->root();
        LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop());
        LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom());
        rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
    }
    rects.append(LayoutRect());

    Color outlineColor = m_layoutInline.resolveColor(styleToUse, CSSPropertyOutlineColor);
    bool useTransparencyLayer = outlineColor.hasAlpha();

    int outlineWidth = styleToUse.outlineWidth();
    LayoutRect bounds;
    for (const auto& rect : rects) {
        LayoutRect rectCopy(rect);
        rectCopy.expand(LayoutSize(outlineWidth, outlineWidth));
        bounds.unite(rectCopy);
    }
    bounds.moveBy(paintOffset);

    LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutInline, paintInfo.phase, bounds);
    if (recorder.canUseCachedDrawing())
        return;

    GraphicsContext* graphicsContext = paintInfo.context;
    if (useTransparencyLayer) {
        graphicsContext->beginLayer(static_cast<float>(outlineColor.alpha()) / 255);
        outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
    }

    for (unsigned i = 1; i < rects.size() - 1; i++)
        paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);

    if (useTransparencyLayer)
        graphicsContext->endLayer();
}