bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
    FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent);

    // Early exit if local point is not contained in clipped viewport area
    if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint))
        return false;

    return RenderBlock::nodeAtPoint(request, result, roundedLayoutPoint(localPoint), LayoutPoint(), hitTestAction);
}
bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->pointerEvents());
    bool isVisible = (style()->visibility() == VISIBLE);
    if (isVisible || !hitRules.requireVisible) {
        if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
            || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
            FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);

            if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
                return false;       

            HitTestLocation hitTestLocation(LayoutPoint(flooredIntPoint(localPoint)));
            return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), hitTestAction);
        }
    }

    return false;
}
Esempio n. 3
0
void RenderScrollbarPart::layout()
{
    setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
    if (m_scrollbar->orientation() == HorizontalScrollbar)
        layoutHorizontalPart();
    else
        layoutVerticalPart();

    setNeedsLayout(false);
}
Esempio n. 4
0
void RenderRegion::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // Delegate painting of content in region to RenderFlowThread.
    if (!m_flowThread || !isValid())
        return;

    setRegionBoxesRegionStyle();
    m_flowThread->paintIntoRegion(paintInfo, this, LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
    restoreRegionBoxesOriginalStyle();
}
Esempio n. 5
0
static LayoutPoint cornerPointOfRect(LayoutRect rect, Corner whichCorner) {
  switch (whichCorner) {
    case Corner::TopLeft:
      return rect.minXMinYCorner();
    case Corner::TopRight:
      return rect.maxXMinYCorner();
  }
  ASSERT_NOT_REACHED();
  return LayoutPoint();
}
Esempio n. 6
0
void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // An empty viewport disables rendering.
    if (pixelSnappedBorderBoxRect().isEmpty())
        return;

    // Don't paint, if the context explicitely disabled it.
    if (paintInfo.context->paintingDisabled())
        return;

    Page* page = 0;
    if (Frame* frame = this->frame())
        page = frame->page();

    // Don't paint if we don't have kids, except if we have filters we should paint those.
    if (!firstChild()) {
        SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
        if (!resources || !resources->filter()) {
            if (page && paintInfo.phase == PaintPhaseForeground)
                page->addRelevantUnpaintedObject(this, visualOverflowRect());
            return;
        }
    }

    if (page && paintInfo.phase == PaintPhaseForeground)
        page->addRelevantRepaintedObject(this, visualOverflowRect());

    // Make a copy of the PaintInfo because applyTransform will modify the damage rect.
    PaintInfo childPaintInfo(paintInfo);
    childPaintInfo.context->save();

    // Apply initial viewport clip - not affected by overflow handling
    childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion)));

    // Convert from container offsets (html renderers) to a relative transform (svg renderers).
    // Transform from our paint container's coordinate system to our local coords.
    IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
    childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y()) * localToBorderBoxTransform());

    // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context, because a filter may have
    // changed the context and it is only reverted when the SVGRenderingContext destructor finishes applying the filter.
    {
        SVGRenderingContext renderingContext;
        bool continueRendering = true;
        if (childPaintInfo.phase == PaintPhaseForeground) {
            renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
            continueRendering = renderingContext.isRenderingPrepared();
        }

        if (continueRendering)
            RenderBox::paint(childPaintInfo, LayoutPoint());
    }

    childPaintInfo.context->restore();
}
void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTreeBuilderContext& context)
{
    PaintPropertyTreeBuilderContext localContext(context);

    // TODO(pdr): Creating paint properties for FrameView here will not be
    // needed once settings()->rootLayerScrolls() is enabled.
    // TODO(pdr): Make this conditional on the rootLayerScrolls setting.

    TransformationMatrix frameTranslate;
    frameTranslate.translate(frameView.x(), frameView.y());
    // The frame owner applies paint offset already.
    // This assumption may change in the future.
    ASSERT(context.paintOffset == LayoutPoint());
    RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = TransformPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTransform);
    localContext.transformForFixedPositioned = newTransformNodeForPreTranslation.get();
    localContext.paintOffsetForFixedPositioned = LayoutPoint();

    FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSize()));
    RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyNode::create(newTransformNodeForPreTranslation.get(), contentClip, localContext.currentClip);
    localContext.currentClip = localContext.clipForOutOfFlowPositioned = localContext.clipForFixedPositioned = newClipNodeForContentClip.get();

    DoubleSize scrollOffset = frameView.scrollOffsetDouble();
    TransformationMatrix frameScroll;
    frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
    RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = TransformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeForPreTranslation);
    localContext.currentTransform = localContext.transformForOutOfFlowPositioned = newTransformNodeForScrollTranslation.get();
    localContext.paintOffset = localContext.paintOffsetForOutOfFlowPositioned = LayoutPoint();

    frameView.setPreTranslation(newTransformNodeForPreTranslation.release());
    frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release());
    frameView.setContentClip(newClipNodeForContentClip.release());

    if (LayoutView* layoutView = frameView.layoutView())
        walk(*layoutView, localContext);

    for (Frame* child = frameView.frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
        if (!child->isLocalFrame())
            continue;
        if (FrameView* childView = toLocalFrame(child)->view())
            walk(*childView, localContext);
    }
}
Esempio n. 8
0
static LayoutRect getShapeImageReplacedRect(const RenderBox& renderBox, const StyleImage& styleImage)
{
    if (renderBox.isRenderImage()) {
        const RenderImage& renderImage = *toRenderImage(&renderBox);
        return renderImage.replacedContentRect(renderBox.intrinsicSize());
    }

    ASSERT(styleImage.cachedImage());
    ASSERT(styleImage.cachedImage()->hasImage());
    return LayoutRect(LayoutPoint(), styleImage.cachedImage()->image()->size());
}
Esempio n. 9
0
void SVGTextPainter::paint(const PaintInfo& paintInfo)
{
    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)
        return;

    PaintInfo blockInfo(paintInfo);
    TransformRecorder transformRecorder(*blockInfo.context, m_renderSVGText.displayItemClient(), m_renderSVGText.localToParentTransform());

    // When transitioning from SVG to block painters we need to keep the PaintInfo rect up-to-date
    // because it can be used for clipping.
    m_renderSVGText.updatePaintInfoRect(blockInfo.rect);

    BlockPainter(m_renderSVGText).paint(blockInfo, LayoutPoint());

    // Paint the outlines, if any
    if (paintInfo.phase == PaintPhaseForeground) {
        blockInfo.phase = PaintPhaseSelfOutline;
        BlockPainter(m_renderSVGText).paint(blockInfo, LayoutPoint());
    }
}
Esempio n. 10
0
void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
    if (paintInfo.context->paintingDisabled())
        return;

    if (paintInfo.phase != PaintPhaseForeground
     && paintInfo.phase != PaintPhaseSelection)
         return;

    PaintInfo blockInfo(paintInfo);
    GraphicsContextStateSaver stateSaver(*blockInfo.context);
    blockInfo.applyTransform(localToParentTransform());
    RenderBlock::paint(blockInfo, LayoutPoint());

    // Paint the outlines, if any
    if (paintInfo.phase == PaintPhaseForeground) {
        blockInfo.phase = PaintPhaseSelfOutline;
        RenderBlock::paint(blockInfo, LayoutPoint());
    }
}
void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(
    const LayoutObject& object,
    PaintPropertyTreeBuilderContext& context) {
  if (object.isBoxModelObject() &&
      context.current.paintOffset != LayoutPoint()) {
    // TODO(trchen): Eliminate PaintLayer dependency.
    PaintLayer* layer = toLayoutBoxModelObject(object).layer();
    if (layer && layer->paintsWithTransform(GlobalPaintNormalPhase)) {
      // We should use the same subpixel paint offset values for snapping
      // regardless of whether a transform is present. If there is a transform
      // we round the paint offset but keep around the residual fractional
      // component for the transformed content to paint with.  In spv1 this was
      // called "subpixel accumulation". For more information, see
      // PaintLayer::subpixelAccumulation() and
      // PaintLayerPainter::paintFragmentByApplyingTransform.
      IntPoint roundedPaintOffset =
          roundedIntPoint(context.current.paintOffset);
      LayoutPoint fractionalPaintOffset =
          LayoutPoint(context.current.paintOffset - roundedPaintOffset);

      context.current.transform =
          object.getMutableForPainting()
              .ensurePaintProperties()
              .updatePaintOffsetTranslation(
                  context.current.transform,
                  TransformationMatrix().translate(roundedPaintOffset.x(),
                                                   roundedPaintOffset.y()),
                  FloatPoint3D(),
                  context.current.shouldFlattenInheritedTransform,
                  context.current.renderingContextID);
      context.current.paintOffset = fractionalPaintOffset;
      return;
    }
  }

  if (object.isLayoutView())
    return;

  if (auto* properties = object.getMutableForPainting().paintProperties())
    properties->clearPaintOffsetTranslation();
}
Esempio n. 12
0
void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // An empty viewport disables rendering.
    if (pixelSnappedBorderBoxRect().isEmpty())
        return;

    // Don't paint, if the context explicitly disabled it.
    if (paintInfo.context->paintingDisabled())
        return;

    // An empty viewBox also disables rendering.
    // (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute)
    SVGSVGElement* svg = toSVGSVGElement(node());
    ASSERT(svg);
    if (svg->hasEmptyViewBox())
        return;

    // Don't paint if we don't have kids, except if we have filters we should paint those.
    if (!firstChild()) {
        SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
        if (!resources || !resources->filter())
            return;
    }

    // Make a copy of the PaintInfo because applyTransform will modify the damage rect.
    PaintInfo childPaintInfo(paintInfo);
    childPaintInfo.context->save();

    // Apply initial viewport clip
    if (shouldApplyViewportClip())
        childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset)));

    // Convert from container offsets (html renderers) to a relative transform (svg renderers).
    // Transform from our paint container's coordinate system to our local coords.
    IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
    childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y()) * localToBorderBoxTransform());

    // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context, because a filter may have
    // changed the context and it is only reverted when the SVGRenderingContext destructor finishes applying the filter.
    {
        SVGRenderingContext renderingContext;
        bool continueRendering = true;
        if (childPaintInfo.phase == PaintPhaseForeground) {
            renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
            continueRendering = renderingContext.isRenderingPrepared();
        }

        if (continueRendering)
            RenderBox::paint(childPaintInfo, LayoutPoint());
    }

    childPaintInfo.context->restore();
}
Esempio n. 13
0
void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* region, const LayoutPoint& paintOffset)
{
    GraphicsContext* context = paintInfo.context;
    if (!context)
        return;

    // Adjust the clipping rect for the region.
    // paintOffset contains the offset where the painting should occur
    // adjusted with the region padding and border.
    LayoutRect regionRect(region->regionRect());
    LayoutRect regionOverflowRect(region->regionOverflowRect());
    LayoutRect regionClippingRect(paintOffset + (regionOverflowRect.location() - regionRect.location()), regionOverflowRect.size());

    PaintInfo info(paintInfo);
    info.rect.intersect(pixelSnappedIntRect(regionClippingRect));

    if (!info.rect.isEmpty()) {
        context->save();

        context->clip(regionClippingRect);

        // RenderFlowThread should start painting its content in a position that is offset
        // from the region rect's current position. The amount of offset is equal to the location of
        // region in flow coordinates.
        LayoutPoint renderFlowThreadOffset;
        if (style()->isFlippedBlocksWritingMode()) {
            LayoutRect flippedRegionRect(regionRect);
            flipForWritingMode(flippedRegionRect);
            renderFlowThreadOffset = LayoutPoint(paintOffset - flippedRegionRect.location());
        } else
            renderFlowThreadOffset = LayoutPoint(paintOffset - regionRect.location());

        context->translate(renderFlowThreadOffset.x(), renderFlowThreadOffset.y());
        info.rect.moveBy(-roundedIntPoint(renderFlowThreadOffset));
        
        layer()->paint(context, info.rect, 0, 0, region, RenderLayer::PaintLayerTemporaryClipRects);

        context->restore();
    }
}
LayoutPoint MultiColumnFragmentainerGroup::visualPointToFlowThreadPoint(const LayoutPoint& visualPoint) const
{
    unsigned columnIndex = columnIndexAtVisualPoint(visualPoint);
    LayoutRect columnRect = columnRectAt(columnIndex);
    LayoutPoint localPoint(visualPoint);
    localPoint.moveBy(-columnRect.location());
    // Before converting to a flow thread position, if the block direction coordinate is outside the
    // column, snap to the bounds of the column, and reset the inline direction coordinate to the
    // start position in the column. The effect of this is that if the block position is before the
    // column rectangle, we'll get to the beginning of this column, while if the block position is
    // after the column rectangle, we'll get to the beginning of the next column.
    if (!m_columnSet.isHorizontalWritingMode()) {
        LayoutUnit columnStart = m_columnSet.style()->isLeftToRightDirection() ? LayoutUnit() : columnRect.height();
        if (localPoint.x() < 0)
            localPoint = LayoutPoint(LayoutUnit(), columnStart);
        else if (localPoint.x() > logicalHeight())
            localPoint = LayoutPoint(logicalHeight(), columnStart);
        return LayoutPoint(localPoint.x() + logicalTopInFlowThreadAt(columnIndex), localPoint.y());
    }
    LayoutUnit columnStart = m_columnSet.style()->isLeftToRightDirection() ? LayoutUnit() : columnRect.width();
    if (localPoint.y() < 0)
        localPoint = LayoutPoint(columnStart, LayoutUnit());
    else if (localPoint.y() > logicalHeight())
        localPoint = LayoutPoint(columnStart, logicalHeight());
    return LayoutPoint(localPoint.x(), localPoint.y() + logicalTopInFlowThreadAt(columnIndex));
}
Esempio n. 15
0
void Element::paint(Canvas* canvas)
{
    if (!renderer() || !renderer()->isBox())
        return;
    RenderBox* box = toRenderBox(renderer());
    GraphicsContext context(canvas->skCanvas());

    // Very simplified painting to allow painting an arbitrary (layer-less) subtree.
    Vector<RenderBox*> layers;
    PaintInfo paintInfo(&context, box->absoluteBoundingBoxRect(), box);
    box->paint(paintInfo, LayoutPoint(), layers);
    // Note we're ignoring any layers encountered.
}
Esempio n. 16
0
void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
    ASSERT(!needsLayout());
    // RenderViews should never be called to paint with an offset not on device pixels.
    ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);

    // This avoids painting garbage between columns if there is a column gap.
    if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated)
        paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor(), ColorSpaceDeviceRGB);

    paintObject(paintInfo, paintOffset);
}
Esempio n. 17
0
bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
    // Embedded content is drawn in the foreground phase.
    if (hitTestAction != HitTestForeground)
        return false;

    AffineTransform localTransform = this->localTransform();
    if (!localTransform.isInvertible())
        return false;

    FloatPoint localPoint = localTransform.inverse().mapPoint(pointInParent);

    // Early exit if local point is not contained in clipped viewport area
    if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint))
        return false;

    // FOs establish a stacking context, so we need to hit-test all layers.
    HitTestLocation hitTestLocation(roundedLayoutPoint(localPoint));
    return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestForeground)
        || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestFloat)
        || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds);
}
static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
    bool shouldCreatePaintOffsetTranslationNode = false;
    if (object.isSVGRoot()) {
        // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary.
        shouldCreatePaintOffsetTranslationNode = true;
    } else if (object.isBoxModelObject()) {
        // TODO(trchen): Eliminate PaintLayer dependency.
        PaintLayer* layer = toLayoutBoxModelObject(object).layer();
        shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTransform(GlobalPaintNormalPhase);
    }

    if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslationNode)
        return nullptr;

    RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create(
        TransformationMatrix().translate(context.paintOffset.x(), context.paintOffset.y()),
        FloatPoint3D(), context.currentTransform);
    context.currentTransform = newTransformNodeForPaintOffsetTranslation.get();
    context.paintOffset = LayoutPoint();
    return newTransformNodeForPaintOffsetTranslation.release();
}
Esempio n. 19
0
void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, Vector<RenderBox*>& layers)
{
    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
    ASSERT(!needsLayout());
    // RenderViews should never be called to paint with an offset not on device pixels.
    ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);

    // This avoids painting garbage between columns if there is a column gap.
    if (m_frameView && style()->isOverflowPaged())
        paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor());

    paintObject(paintInfo, paintOffset, layers);
}
Esempio n. 20
0
bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->pointerEvents());
    bool isVisible = (style()->visibility() == VISIBLE);
    if (isVisible || !hitRules.requireVisible) {
        if ((hitRules.canHitBoundingBox && !objectBoundingBox().isEmpty())
            || (hitRules.canHitStroke && (style()->svgStyle().hasStroke() || !hitRules.requireStroke))
            || (hitRules.canHitFill && (style()->svgStyle().hasFill() || !hitRules.requireFill))) {
            FloatPoint localPoint;
            if (!SVGRenderSupport::transformToUserSpaceAndCheckClipping(this, localToParentTransform(), pointInParent, localPoint))
                return false;

            if (hitRules.canHitBoundingBox && !objectBoundingBox().contains(localPoint))
                return false;

            HitTestLocation hitTestLocation(LayoutPoint(flooredIntPoint(localPoint)));
            return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), hitTestAction);
        }
    }

    return false;
}
Esempio n. 21
0
LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
{
    if (checkWhetherSelected && !isSelected())
        return LayoutRect();

    if (!inlineBoxWrapper())
        // We're a block-level replaced element.  Just return our own dimensions.
        return LayoutRect(LayoutPoint(), size());

    RootInlineBox& root = inlineBoxWrapper()->root();
    LayoutUnit newLogicalTop = root.selectionTop() - inlineBoxWrapper()->logicalTop();
    return LayoutRect(0, newLogicalTop, width(), root.selectionHeight());
}
LayoutRect LayoutListMarker::localSelectionRect() const
{
    InlineBox* box = inlineBoxWrapper();
    if (!box)
        return LayoutRect(LayoutPoint(), size());
    RootInlineBox& root = inlineBoxWrapper()->root();
    const ComputedStyle* blockStyle = root.block().style();
    LayoutUnit newLogicalTop = blockStyle->isFlippedBlocksWritingMode()
        ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom()
        : root.selectionTop() - inlineBoxWrapper()->logicalTop();
    return blockStyle->isHorizontalWritingMode()
        ? LayoutRect(0, newLogicalTop, size().width(), root.selectionHeight())
        : LayoutRect(newLogicalTop, 0, root.selectionHeight(), size().height());
}
Esempio n. 23
0
const Shape& ShapeOutsideInfo::computedShape() const {
  if (Shape* shape = m_shape.get())
    return *shape;

  AutoReset<bool> isInComputingShape(&m_isComputingShape, true);

  const ComputedStyle& style = *m_layoutBox.style();
  ASSERT(m_layoutBox.containingBlock());
  const ComputedStyle& containingBlockStyle =
      *m_layoutBox.containingBlock()->style();

  WritingMode writingMode = containingBlockStyle.getWritingMode();
  // Make sure contentWidth is not negative. This can happen when containing
  // block has a vertical scrollbar and its content is smaller than the
  // scrollbar width.
  LayoutUnit maximumValue =
      m_layoutBox.containingBlock()
          ? std::max(LayoutUnit(),
                     m_layoutBox.containingBlock()->contentWidth())
          : LayoutUnit();
  float margin = floatValueForLength(m_layoutBox.style()->shapeMargin(),
                                     maximumValue.toFloat());

  float shapeImageThreshold = style.shapeImageThreshold();
  ASSERT(style.shapeOutside());
  const ShapeValue& shapeValue = *style.shapeOutside();

  switch (shapeValue.type()) {
    case ShapeValue::Shape:
      ASSERT(shapeValue.shape());
      m_shape = Shape::createShape(
          shapeValue.shape(), m_referenceBoxLogicalSize, writingMode, margin);
      break;
    case ShapeValue::Image:
      ASSERT(shapeValue.isImageValid());
      m_shape = createShapeForImage(shapeValue.image(), shapeImageThreshold,
                                    writingMode, margin);
      break;
    case ShapeValue::Box: {
      const FloatRoundedRect& shapeRect = style.getRoundedBorderFor(
          LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize),
          m_layoutBox.view());
      m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin);
      break;
    }
  }

  ASSERT(m_shape);
  return *m_shape;
}
Esempio n. 24
0
void ViewPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
    ASSERT(!m_layoutView.needsLayout());
    // LayoutViews should never be called to paint with an offset not on device pixels.
    ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);

    const FrameView* frameView = m_layoutView.frameView();
    if (frameView->shouldThrottleRendering())
        return;

    m_layoutView.paintObject(paintInfo, paintOffset);
    BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOffset);
}
Esempio n. 25
0
std::unique_ptr<Shape> ShapeOutsideInfo::createShapeForImage(StyleImage* styleImage, float shapeImageThreshold, WritingMode writingMode, float margin) const
{
    LayoutSize imageSize = m_renderer.calculateImageIntrinsicDimensions(styleImage, m_referenceBoxLogicalSize, RenderImage::ScaleByEffectiveZoom);
    styleImage->setContainerSizeForRenderer(&m_renderer, imageSize, m_renderer.style().effectiveZoom());

    const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referenceBoxLogicalSize);
    const LayoutRect& imageRect = is<RenderImage>(m_renderer)
        ? downcast<RenderImage>(m_renderer).replacedContentRect(m_renderer.intrinsicSize())
        : LayoutRect(LayoutPoint(), imageSize);

    ASSERT(!styleImage->isPendingImage());
    RefPtr<Image> image = styleImage->image(const_cast<RenderBox*>(&m_renderer), imageSize);
    return Shape::createRasterShape(image.get(), shapeImageThreshold, imageRect, marginRect, writingMode, margin);
}
Esempio n. 26
0
LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
{
    if (checkWhetherSelected && !isSelected())
        return LayoutRect();

    if (!m_inlineBoxWrapper)
        // We're a block-level replaced element.  Just return our own dimensions.
        return LayoutRect(LayoutPoint(), size());
    
    const RootInlineBox& rootBox = m_inlineBoxWrapper->root();
    LayoutUnit newLogicalTop = rootBox.blockFlow().style().isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - rootBox.selectionBottom() : rootBox.selectionTop() - m_inlineBoxWrapper->logicalTop();
    if (rootBox.blockFlow().style().isHorizontalWritingMode())
        return LayoutRect(0, newLogicalTop, width(), rootBox.selectionHeight());
    return LayoutRect(newLogicalTop, 0, rootBox.selectionHeight(), height());
}
Esempio n. 27
0
bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction hitTestAction)
{
    LayoutPoint adjustedLocation = accumulatedOffset + LayoutPoint(topLeft());

    // Hit test the markup box.
    if (InlineBox* markupBox = this->markupBox()) {
        const RenderStyle& lineStyle = this->lineStyle();
        LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x();
        LayoutUnit mty = adjustedLocation.y() + lineStyle.fontMetrics().ascent() - (markupBox->y() + markupBox->lineStyle().fontMetrics().ascent());
        if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom, hitTestAction)) {
            blockFlow().updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
            return true;
        }
    }

    LayoutRect boundsRect(adjustedLocation, LayoutSize(m_logicalWidth, m_height));
    if (visibleToHitTesting() && boundsRect.intersects(HitTestLocation::rectForPoint(locationInContainer.point(), 0, 0, 0, 0))) {
        blockFlow().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
        if (!result.addNodeToRectBasedTestResult(blockFlow().element(), request, locationInContainer, boundsRect))
            return true;
    }

    return false;
}
Esempio n. 28
0
PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInContents)
{
    RootInlineBox* rootBox = firstRootBox();
    if (!rootBox)
        return createPositionWithAffinity(0, DOWNSTREAM);

    ASSERT(!rootBox->nextRootBox());
    ASSERT(childrenInline());

    InlineBox* closestBox = toSVGRootInlineBox(rootBox)->closestLeafChildForPosition(pointInContents);
    if (!closestBox)
        return createPositionWithAffinity(0, DOWNSTREAM);

    return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
}
Esempio n. 29
0
void ViewPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
    ASSERT(!m_renderView.needsLayout());
    // RenderViews should never be called to paint with an offset not on device pixels.
    ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);

    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderView);

    // This avoids painting garbage between columns if there is a column gap.
    if (m_renderView.frameView() && m_renderView.style()->isOverflowPaged())
        paintInfo.context->fillRect(paintInfo.rect, m_renderView.frameView()->baseBackgroundColor());

    m_renderView.paintObject(paintInfo, paintOffset);
}
// Hit Testing
bool RenderRegion::hitTestFlowThreadContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
    if (!isValid() || action != HitTestForeground)
        return false;

    LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
    boundsRect.moveBy(accumulatedOffset);
    if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
        if (m_flowThread->hitTestFlowThreadPortionInRegion(this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), request, result,
            locationInContainer, LayoutPoint(accumulatedOffset.x() + borderLeft() + paddingLeft(), accumulatedOffset.y() + borderTop() + paddingTop())))
            return true;
    }

    return false;
}