예제 #1
0
LayerClipRecorder::LayerClipRecorder(GraphicsContext& graphicsContext, const LayoutBoxModelObject& layoutObject, DisplayItem::Type clipType, const ClipRect& clipRect,
    const PaintLayerPaintingInfo* localPaintingInfo, const LayoutPoint& fragmentOffset, PaintLayerFlags paintFlags, BorderRadiusClippingRule rule)
    : m_graphicsContext(graphicsContext)
    , m_layoutObject(layoutObject)
    , m_clipType(clipType)
{
    IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect());
    Vector<FloatRoundedRect> roundedRects;
    if (localPaintingInfo && clipRect.hasRadius()) {
        collectRoundedRectClips(*layoutObject.layer(), *localPaintingInfo, graphicsContext, fragmentOffset, paintFlags, rule, roundedRects);
    }

    ASSERT(m_graphicsContext.displayItemList());
    m_graphicsContext.displayItemList()->createAndAppend<ClipDisplayItem>(layoutObject, m_clipType, snappedClipRect, roundedRects);
}
예제 #2
0
void RenderLayerClipper::calculateClipRects(const ClipRectsContext& context, ClipRects& clipRects) const
{
    if (!m_renderer.layer()->parent()) {
        // The root layer's clip rect is always infinite.
        clipRects.reset(PaintInfo::infiniteRect());
        return;
    }

    bool isClippingRoot = m_renderer.layer() == context.rootLayer;

    // For transformed layers, the root layer was shifted to be us, so there is no need to
    // examine the parent. We want to cache clip rects with us as the root.
    RenderLayer* parentLayer = !isClippingRoot ? m_renderer.layer()->parent() : 0;

    // Ensure that our parent's clip has been calculated so that we can examine the values.
    if (parentLayer) {
        // FIXME: Why don't we just call getClipRects here?
        if (context.usesCache() && parentLayer->clipper().cachedClipRects(context)) {
            clipRects = *parentLayer->clipper().cachedClipRects(context);
        } else {
            parentLayer->clipper().calculateClipRects(context, clipRects);
        }
    } else {
        clipRects.reset(PaintInfo::infiniteRect());
    }

    if (m_renderer.style()->position() == AbsolutePosition) {
        clipRects.setOverflowClipRect(clipRects.posClipRect());
    }

    // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
    // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
    // clipRects are needed in view space.
    LayoutPoint offset = roundedLayoutPoint(m_renderer.localToContainerPoint(FloatPoint(), context.rootLayer->renderer()));
    if (m_renderer.hasOverflowClip()) {
        ClipRect newOverflowClip = m_renderer.overflowClipRect(offset);
        newOverflowClip.setHasRadius(m_renderer.style()->hasBorderRadius());
        clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
        if (m_renderer.isPositioned())
            clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
    }

    if (m_renderer.hasClip()) {
        LayoutRect newClip = m_renderer.clipRect(offset);
        clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()));
        clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()));
    }
}
예제 #3
0
void RenderLayerClipper::calculateRects(const ClipRectsContext& context, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
    ClipRect& backgroundRect, const LayoutPoint* offsetFromRoot) const
{
    bool isClippingRoot = m_renderer.layer() == context.rootLayer;

    if (!isClippingRoot && m_renderer.layer()->parent()) {
        backgroundRect = backgroundClipRect(context);
        backgroundRect.move(roundedIntSize(context.subPixelAccumulation));
        backgroundRect.intersect(paintDirtyRect);
    } else {
        backgroundRect = paintDirtyRect;
    }

    LayoutPoint offset;
    if (offsetFromRoot)
        offset = *offsetFromRoot;
    else
        m_renderer.layer()->convertToLayerCoords(context.rootLayer, offset);
    layerBounds = LayoutRect(offset, m_renderer.layer()->size());

    // Update the clip rects that will be passed to child layers.
    if (m_renderer.hasOverflowClip()) {
        // If we establish an overflow clip at all, then go ahead and make sure our background
        // rect is intersected with our layer's bounds including our visual overflow,
        // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
        if (m_renderer.hasVisualOverflow()) {
            // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though
            //        we may need to inflate our clip specifically for shadows or outsets.
            // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
            // individual region boxes as overflow.
            LayoutRect layerBoundsWithVisualOverflow = m_renderer.visualOverflowRect();
            layerBoundsWithVisualOverflow.moveBy(offset);
            backgroundRect.intersect(layerBoundsWithVisualOverflow);
        } else {
            LayoutRect bounds = m_renderer.borderBoxRect();
            bounds.moveBy(offset);
            backgroundRect.intersect(bounds);
        }
    }

    // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
    if (m_renderer.hasClip()) {
        // Clip applies to *us* as well, so go ahead and update the damageRect.
        LayoutRect newPosClip = m_renderer.clipRect(offset);
        backgroundRect.intersect(newPosClip);
    }
}
예제 #4
0
static void applyClipRects(const ClipRectsContext& context,
                           const LayoutBoxModelObject& layoutObject,
                           LayoutPoint offset,
                           ClipRects& clipRects) {
  DCHECK(layoutObject.hasClipRelatedProperty() ||
         (layoutObject.isSVGRoot() &&
          toLayoutSVGRoot(&layoutObject)->shouldApplyViewportClip()));
  LayoutView* view = layoutObject.view();
  DCHECK(view);
  if (clipRects.fixed() && context.rootLayer->layoutObject() == view)
    offset -= LayoutSize(view->frameView()->scrollOffset());
  if (layoutObject.hasOverflowClip() ||
      (layoutObject.isSVGRoot() &&
       toLayoutSVGRoot(&layoutObject)->shouldApplyViewportClip()) ||
      (layoutObject.styleRef().containsPaint() && layoutObject.isBox())) {
    ClipRect newOverflowClip =
        toLayoutBox(layoutObject)
            .overflowClipRect(offset, context.overlayScrollbarClipBehavior);
    newOverflowClip.setHasRadius(layoutObject.styleRef().hasBorderRadius());
    clipRects.setOverflowClipRect(
        intersection(newOverflowClip, clipRects.overflowClipRect()));
    if (layoutObject.isPositioned())
      clipRects.setPosClipRect(
          intersection(newOverflowClip, clipRects.posClipRect()));
    if (layoutObject.isLayoutView())
      clipRects.setFixedClipRect(
          intersection(newOverflowClip, clipRects.fixedClipRect()));
    if (layoutObject.styleRef().containsPaint()) {
      clipRects.setPosClipRect(
          intersection(newOverflowClip, clipRects.posClipRect()));
      clipRects.setFixedClipRect(
          intersection(newOverflowClip, clipRects.fixedClipRect()));
    }
  }
  if (layoutObject.hasClip()) {
    LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset);
    clipRects.setPosClipRect(
        intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss());
    clipRects.setOverflowClipRect(
        intersection(newClip, clipRects.overflowClipRect())
            .setIsClippedByClipCss());
    clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect())
                                   .setIsClippedByClipCss());
  }
}
예제 #5
0
static void applyClipRects(const ClipRectsContext& context, RenderObject& renderer, LayoutPoint offset, ClipRects& clipRects)
{
    ASSERT(renderer.hasOverflowClip() || renderer.hasClip());

    if (renderer.hasOverflowClip()) {
        ClipRect newOverflowClip = toRenderBox(renderer).overflowClipRect(offset);
        newOverflowClip.setHasRadius(renderer.style()->hasBorderRadius());
        clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
        if (renderer.isPositioned())
            clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
    }

    if (renderer.hasClip()) {
        LayoutRect newClip = toRenderBox(renderer).clipRect(offset);
        clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()));
        clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()));
    }
}
예제 #6
0
LayoutRect RenderLayerClipper::localClipRect() const
{
    // FIXME: border-radius not accounted for.
    RenderLayer* clippingRootLayer = clippingRootForPainting();
    LayoutRect layerBounds;
    ClipRect backgroundRect;
    ClipRectsContext context(clippingRootLayer, PaintingClipRects);
    calculateRects(context, PaintInfo::infiniteRect(), layerBounds, backgroundRect);

    LayoutRect clipRect = backgroundRect.rect();
    if (clipRect == PaintInfo::infiniteRect())
        return clipRect;

    LayoutPoint clippingRootOffset;
    m_renderer.layer()->convertToLayerCoords(clippingRootLayer, clippingRootOffset);
    clipRect.moveBy(-clippingRootOffset);

    return clipRect;
}
예제 #7
0
ClipRect PaintLayerClipper::backgroundClipRect(const ClipRectsContext& context) const
{
    ASSERT(m_layoutObject.layer()->parent());
    ASSERT(m_layoutObject.view());

    RefPtr<ClipRects> parentClipRects = ClipRects::create();
    if (m_layoutObject.layer() == context.rootLayer)
        parentClipRects->reset(LayoutRect(LayoutRect::infiniteIntRect()));
    else
        m_layoutObject.layer()->parent()->clipper().getOrCalculateClipRects(context, *parentClipRects);

    ClipRect result = backgroundClipRectForPosition(*parentClipRects, m_layoutObject.style()->position());

    // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
    if (parentClipRects->fixed() && context.rootLayer->layoutObject() == m_layoutObject.view() && result != LayoutRect(LayoutRect::infiniteIntRect()))
        result.move(toIntSize(m_layoutObject.view()->frameView()->scrollPosition()));

    return result;
}
예제 #8
0
ClipRect RenderLayerClipper::backgroundClipRect(const ClipRectsContext& context) const
{
    ASSERT(m_renderer.layer()->parent());
    ASSERT(m_renderer.view());

    ClipRects parentClipRects;
    if (m_renderer.layer() == context.rootLayer)
        parentClipRects.reset(PaintInfo::infiniteRect());
    else
        m_renderer.layer()->parent()->clipper().getOrCalculateClipRects(context, parentClipRects);

    ClipRect result = backgroundClipRectForPosition(parentClipRects, m_renderer.style()->position());

    // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
    if (parentClipRects.fixed() && context.rootLayer->renderer() == m_renderer.view() && result != PaintInfo::infiniteRect())
        result.move(m_renderer.view()->frameView()->scrollOffsetForFixedPosition());

    return result;
}
예제 #9
0
void PaintLayerClipper::calculateRects(const ClipRectsContext& context, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
    ClipRect& backgroundRect, ClipRect& foregroundRect, const LayoutPoint* offsetFromRoot) const
{
    bool isClippingRoot = m_layoutObject.layer() == context.rootLayer;

    if (!isClippingRoot && m_layoutObject.layer()->parent()) {
        backgroundRect = backgroundClipRect(context);
        backgroundRect.move(context.subPixelAccumulation);
        backgroundRect.intersect(paintDirtyRect);
    } else {
        backgroundRect = paintDirtyRect;
    }

    foregroundRect = backgroundRect;

    LayoutPoint offset;
    if (offsetFromRoot)
        offset = *offsetFromRoot;
    else
        m_layoutObject.layer()->convertToLayerCoords(context.rootLayer, offset);
    layerBounds = LayoutRect(offset, LayoutSize(m_layoutObject.layer()->size()));

    // Update the clip rects that will be passed to child layers.
    if (m_layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context)) {
        foregroundRect.intersect(toLayoutBox(m_layoutObject).overflowClipRect(offset, context.scrollbarRelevancy));
        if (m_layoutObject.style()->hasBorderRadius())
            foregroundRect.setHasRadius(true);

        // FIXME: Does not do the right thing with columns yet, since we don't yet factor in the
        // individual column boxes as overflow.

        // The LayoutView is special since its overflow clipping rect may be larger than its box rect (crbug.com/492871).
        LayoutRect layerBoundsWithVisualOverflow = m_layoutObject.isLayoutView() ? toLayoutView(m_layoutObject).viewRect() : toLayoutBox(m_layoutObject).visualOverflowRect();
        toLayoutBox(m_layoutObject).flipForWritingMode(layerBoundsWithVisualOverflow); // PaintLayer are in physical coordinates, so the overflow has to be flipped.
        layerBoundsWithVisualOverflow.moveBy(offset);
        backgroundRect.intersect(layerBoundsWithVisualOverflow);
    }

    // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
    if (m_layoutObject.hasClip()) {
        // Clip applies to *us* as well, so go ahead and update the damageRect.
        LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset);
        backgroundRect.intersect(newPosClip);
        backgroundRect.setIsClippedByClipCss();
        foregroundRect.intersect(newPosClip);
        foregroundRect.setIsClippedByClipCss();
    }
}
예제 #10
0
LayoutRect PaintLayerClipper::localClipRect(
    const PaintLayer* clippingRootLayer) const {
  ClipRectsContext context(clippingRootLayer, PaintingClipRects);
  if (m_geometryMapper) {
    ClipRect clipRect = applyOverflowClipToBackgroundRectWithGeometryMapper(
        context, clipRectWithGeometryMapper(context, false));

    // The rect now needs to be transformed to the local space of this
    // PaintLayer.
    bool success = false;
    FloatRect clippedRectInLocalSpace =
        m_geometryMapper->mapRectToDestinationSpace(
            FloatRect(clipRect.rect()), clippingRootLayer->layoutObject()
                                            ->paintProperties()
                                            ->localBorderBoxProperties()
                                            ->propertyTreeState,
            m_layer.layoutObject()
                ->paintProperties()
                ->localBorderBoxProperties()
                ->propertyTreeState,
            success);
    DCHECK(success);

    return LayoutRect(clippedRectInLocalSpace);
  }

  LayoutRect layerBounds;
  ClipRect backgroundRect, foregroundRect;
  calculateRects(context, LayoutRect(LayoutRect::infiniteIntRect()),
                 layerBounds, backgroundRect, foregroundRect);

  LayoutRect clipRect = backgroundRect.rect();
  // TODO(chrishtr): avoid converting to IntRect and back.
  if (clipRect == LayoutRect(LayoutRect::infiniteIntRect()))
    return clipRect;

  LayoutPoint clippingRootOffset;
  m_layer.convertToLayerCoords(clippingRootLayer, clippingRootOffset);
  clipRect.moveBy(-clippingRootOffset);

  return clipRect;
}
예제 #11
0
static void applyClipRects(const ClipRectsContext& context, const LayoutObject& layoutObject, LayoutPoint offset, ClipRects& clipRects)
{
    ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip());
    LayoutView* view = layoutObject.view();
    ASSERT(view);
    if (clipRects.fixed() && context.rootLayer->layoutObject() == view)
        offset -= toIntSize(view->frameView()->scrollPosition());
    if (layoutObject.hasOverflowClip()) {
        ClipRect newOverflowClip = toLayoutBox(layoutObject).overflowClipRect(offset, context.scrollbarRelevancy);
        newOverflowClip.setHasRadius(layoutObject.style()->hasBorderRadius());
        clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
        if (layoutObject.isPositioned())
            clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
        if (layoutObject.isLayoutView())
            clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.fixedClipRect()));
    }
    if (layoutObject.hasClip()) {
        LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset);
        clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss());
        clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()).setIsClippedByClipCss());
        clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()).setIsClippedByClipCss());

    }
}
예제 #12
0
static void applyClipRects(const ClipRectsContext& context, RenderObject& renderer, LayoutPoint offset, ClipRects& clipRects)
{
    ASSERT(renderer.hasOverflowClip() || renderer.hasClip());

    RenderView* view = renderer.view();
    ASSERT(view);
    if (clipRects.fixed() && context.rootLayer->renderer() == view)
        offset -= view->frameView()->scrollOffsetForFixedPosition();

    if (renderer.hasOverflowClip()) {
        ClipRect newOverflowClip = toRenderBox(renderer).overflowClipRect(offset, context.scrollbarRelevancy);
        newOverflowClip.setHasRadius(renderer.style()->hasBorderRadius());
        clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
        if (renderer.isPositioned())
            clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
    }

    if (renderer.hasClip()) {
        LayoutRect newClip = toRenderBox(renderer).clipRect(offset);
        clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()));
        clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()));
        clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()));
    }
}
예제 #13
0
ClipRect PaintLayerClipper::applyOverflowClipToBackgroundRectWithGeometryMapper(
    const ClipRectsContext& context,
    const ClipRect& clip) const {
  const LayoutObject& layoutObject = *m_layer.layoutObject();
  FloatRect clipRect(clip.rect());
  if (shouldClipOverflow(context)) {
    LayoutRect layerBoundsWithVisualOverflow =
        layoutObject.isLayoutView()
            ? toLayoutView(layoutObject).viewRect()
            : toLayoutBox(layoutObject).visualOverflowRect();
    toLayoutBox(layoutObject)
        .flipForWritingMode(
            // PaintLayer are in physical coordinates, so the overflow has to be
            // flipped.
            layerBoundsWithVisualOverflow);
    mapLocalToRootWithGeometryMapper(context, layerBoundsWithVisualOverflow);
    clipRect.intersect(FloatRect(layerBoundsWithVisualOverflow));
  }

  return ClipRect(LayoutRect(clipRect));
}
예제 #14
0
void PaintLayerPainter::paintFragmentWithPhase(PaintPhase phase, const PaintLayerFragment& fragment, GraphicsContext& context, const ClipRect& clipRect, const PaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, ClipState clipState)
{
    ASSERT(m_paintLayer.isSelfPaintingLayer());

    Optional<LayerClipRecorder> clipRecorder;
    if (clipState != HasClipped && paintingInfo.clipToDirtyRect && needsToClip(paintingInfo, clipRect)) {
        DisplayItem::Type clipType = DisplayItem::paintPhaseToClipLayerFragmentType(phase);
        LayerClipRecorder::BorderRadiusClippingRule clippingRule;
        switch (phase) {
        case PaintPhaseSelfBlockBackgroundOnly: // Background painting will handle clipping to self.
        case PaintPhaseSelfOutlineOnly:
        case PaintPhaseMask: // Mask painting will handle clipping to self.
            clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
            break;
        default:
            clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
            break;
        }

        clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, clipRect, &paintingInfo, fragment.paginationOffset, paintFlags, clippingRule);
    }

    LayoutRect newCullRect(clipRect.rect());
    Optional<ScrollRecorder> scrollRecorder;
    LayoutPoint paintOffset = toPoint(fragment.layerBounds.location() - m_paintLayer.layoutBoxLocation());
    if (!paintingInfo.scrollOffsetAccumulation.isZero()) {
        // As a descendant of the root layer, m_paintLayer's painting is not controlled by the ScrollRecorders
        // created by BlockPainter of the ancestor layers up to the root layer, so we need to issue ScrollRecorder
        // for this layer seperately, with the scroll offset accumulated from the root layer to the parent of this
        // layer, to get the same result as ScrollRecorder in BlockPainter.
        paintOffset += paintingInfo.scrollOffsetAccumulation;

        newCullRect.move(paintingInfo.scrollOffsetAccumulation);
        scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase, paintingInfo.scrollOffsetAccumulation);
    }
    PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase,
        paintingInfo.globalPaintFlags(), paintFlags, paintingInfo.rootLayer->layoutObject());

    m_paintLayer.layoutObject()->paint(paintInfo, paintOffset);
}
예제 #15
0
void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
    if (!m_renderer->layer()->parent()) {
        // The root layer's clip rect is always infinite.
        clipRects.reset(PaintInfo::infiniteRect());
        return;
    }

    ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
    bool useCached = clipRectsType != TemporaryClipRects;

    // For transformed layers, the root layer was shifted to be us, so there is no need to
    // examine the parent. We want to cache clip rects with us as the root.
    RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0;

    // Ensure that our parent's clip has been calculated so that we can examine the values.
    if (parentLayer) {
        if (useCached && parentLayer->clipper().clipRects(clipRectsContext)) {
            clipRects = *parentLayer->clipper().clipRects(clipRectsContext);
        } else {
            ClipRectsContext parentContext(clipRectsContext);
            parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize; // FIXME: why?
            parentLayer->clipper().calculateClipRects(parentContext, clipRects);
        }
    } else {
        clipRects.reset(PaintInfo::infiniteRect());
    }

    // A fixed object is essentially the root of its containing block hierarchy, so when
    // we encounter such an object, we reset our clip rects to the fixedClipRect.
    if (m_renderer->style()->position() == FixedPosition) {
        clipRects.setPosClipRect(clipRects.fixedClipRect());
        clipRects.setOverflowClipRect(clipRects.fixedClipRect());
        clipRects.setFixed(true);
    } else if (m_renderer->style()->hasInFlowPosition()) {
        clipRects.setPosClipRect(clipRects.overflowClipRect());
    } else if (m_renderer->style()->position() == AbsolutePosition) {
        clipRects.setOverflowClipRect(clipRects.posClipRect());
    }

    // Update the clip rects that will be passed to child layers.
    if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || m_renderer->layer() != clipRectsContext.rootLayer)) || m_renderer->hasClip()) {
        // This layer establishes a clip of some kind.

        // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
        // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
        // clipRects are needed in view space.
        LayoutPoint offset;
        offset = roundedLayoutPoint(m_renderer->localToContainerPoint(FloatPoint(), clipRectsContext.rootLayer->renderer()));
        RenderView* view = m_renderer->view();
        ASSERT(view);
        if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) {
            offset -= view->frameView()->scrollOffsetForFixedPosition();
        }

        if (m_renderer->hasOverflowClip()) {
            ClipRect newOverflowClip = toRenderBox(m_renderer)->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy);
            if (m_renderer->style()->hasBorderRadius())
                newOverflowClip.setHasRadius(true);
            clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
            if (m_renderer->isPositioned())
                clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
        }
        if (m_renderer->hasClip()) {
            LayoutRect newPosClip = toRenderBox(m_renderer)->clipRect(offset, clipRectsContext.region);
            clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
            clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
            clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
        }
    }
}
예제 #16
0
void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
    ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
{
    bool isClippingRoot = isClippingRootForContext(clipRectsContext);

    if (!isClippingRoot && m_renderer.layer()->parent()) {
        backgroundRect = backgroundClipRect(clipRectsContext);
        backgroundRect.move(roundedIntSize(clipRectsContext.subPixelAccumulation));
        backgroundRect.intersect(paintDirtyRect);
    } else {
        backgroundRect = paintDirtyRect;
    }

    foregroundRect = backgroundRect;
    outlineRect = backgroundRect;

    LayoutPoint offset;
    if (offsetFromRoot)
        offset = *offsetFromRoot;
    else
        m_renderer.layer()->convertToLayerCoords(clipRectsContext.rootLayer, offset);
    layerBounds = LayoutRect(offset, m_renderer.layer()->size());

    // Update the clip rects that will be passed to child layers.
    if (m_renderer.hasOverflowClip()) {
        // This layer establishes a clip of some kind.
        if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip) {
            foregroundRect.intersect(toRenderBox(m_renderer).overflowClipRect(offset, clipRectsContext.overlayScrollbarSizeRelevancy));
            if (m_renderer.style()->hasBorderRadius())
                foregroundRect.setHasRadius(true);
        }

        // If we establish an overflow clip at all, then go ahead and make sure our background
        // rect is intersected with our layer's bounds including our visual overflow,
        // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
        if (toRenderBox(m_renderer).hasVisualOverflow()) {
            // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though
            //        we may need to inflate our clip specifically for shadows or outsets.
            // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
            // individual region boxes as overflow.
            LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer).visualOverflowRect();
            toRenderBox(m_renderer).flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
            layerBoundsWithVisualOverflow.moveBy(offset);
            if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
                backgroundRect.intersect(layerBoundsWithVisualOverflow);
        } else {
            LayoutRect bounds = toRenderBox(m_renderer).borderBoxRect();
            bounds.moveBy(offset);
            if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
                backgroundRect.intersect(bounds);
        }
    }

    // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
    if (m_renderer.hasClip()) {
        // Clip applies to *us* as well, so go ahead and update the damageRect.
        LayoutRect newPosClip = toRenderBox(m_renderer).clipRect(offset);
        backgroundRect.intersect(newPosClip);
        foregroundRect.intersect(newPosClip);
        outlineRect.intersect(newPosClip);
    }
}
    //
    // TransferList::Item::DrawSelf
    //
    // DrawSelf
    //
    void TransferList::Item::DrawSelf(PaintInfo &pi)
    {
      // Fill the background
      DrawCtrlBackground(pi, GetTexture());

      // Draw the frame
      DrawCtrlFrame(pi);

      if (!pi.font)
      {
        return;
      }

      CH buff[128];
      const CH *ch;

      // Draw the name of the file
      ch = Utils::Ansi2Unicode(offer->path.str);
      pi.font->Draw
      (
        pi.client.p0.x + transferList.offsetFile.x,
        pi.client.p0.y + transferList.offsetFile.y, 
        ch, 
        Utils::Strlen(ch),
        pi.colors->fg[ColorIndex()],
        &pi.client
      );

      Network::Player *player = Network::GetPlayers().Find(offer->who);
      if (player)
      {
        Utils::Sprintf(buff, 128, L"%s %s", offer->from ? L"From" : L"To", Utils::Ansi2Unicode(player->GetName()));
        ch = buff;
        pi.font->Draw
        (
          pi.client.p0.x + transferList.offsetPlayer.x,
          pi.client.p0.y + transferList.offsetPlayer.y, 
          ch, 
          Utils::Strlen(ch),
          pi.colors->fg[ColorIndex()],
          &pi.client
        );
      }

      ch = Utils::Ansi2Unicode(offer->path.str);
      pi.font->Draw
      (
        pi.client.p0.x + transferList.offsetFile.x,
        pi.client.p0.y + transferList.offsetFile.y, 
        ch, 
        Utils::Strlen(ch),
        pi.colors->fg[ColorIndex()],
        &pi.client
      );

      U32 state;
      U32 remaining;
      U32 rate;

      offer->transfer.Progress(state, remaining, rate);

      switch (state)
      {
        case StyxNet::TransferState::Transferring:
          break;

        default:
          remaining = offer->size;
          rate = 0;
          break;
      }

      U32 transferred = offer->size - remaining;

      // Draw the amount transferred
      if (transferred < 1000)
      {
        Utils::Sprintf(buff, 128, L"%.1fB", F32(transferred));
      }
      else if (transferred < 1000000)
      {
        Utils::Sprintf(buff, 128, L"%.1fkB", F32(transferred) / 1000.0f);
      }
      else
      {
        Utils::Sprintf(buff, 128, L"%.1fMB", F32(transferred) / 1000000.0f);
      }
      ch = buff;
      pi.font->Draw
      (
        pi.client.p0.x + transferList.offsetTransferred.x,
        pi.client.p0.y + transferList.offsetTransferred.y, 
        ch, 
        Utils::Strlen(ch),
        pi.colors->fg[ColorIndex()],
        &pi.client
      );

      // Draw the rate
      if (rate < 1000)
      {
        Utils::Sprintf(buff, 128, L"%.1fB/s", F32(rate));
      }
      else if (rate < 1000000)
      {
        Utils::Sprintf(buff, 128, L"%.1fkB/s", F32(rate) / 1000.0f);
      }
      else
      {
        Utils::Sprintf(buff, 128, L"%.1fMB/s", F32(rate) / 1000000.0f);
      }
      pi.font->Draw
      (
        pi.client.p0.x + transferList.offsetRate.x,
        pi.client.p0.y + transferList.offsetRate.y, 
        ch, 
        Utils::Strlen(ch),
        pi.colors->fg[ColorIndex()],
        &pi.client
      );

      // Draw the ETA
      if (rate)
      {
        S32 eta = remaining / rate;
        Utils::Sprintf(buff, 128, L"%d:%02d", eta / 60, eta % 60);
      }
      else
      {
        ch = L"?:??";
      }
      pi.font->Draw
      (
        pi.client.p0.x + transferList.offsetETA.x,
        pi.client.p0.y + transferList.offsetETA.y, 
        ch, 
        Utils::Strlen(ch),
        pi.colors->fg[ColorIndex()],
        &pi.client
      );

      // Draw a progress bar
      ClipRect c
      (
        pi.client.p0.x + transferList.offsetProgress.x, pi.client.p0.y + transferList.offsetProgress.y,
        pi.client.p1.x - transferList.offsetProgress.x, pi.client.p0.y + transferList.offsetProgress.y + transferList.heightProgress
      );

      IFace::RenderRectangle
      (
        c,
        Color(0.0f, 0.0f, 0.0f, pi.alphaScale), 
        NULL, 
        pi.alphaScale
      );

      IFace::RenderGradient
      (
        ClipRect
        (
          c.p0.x, c.p0.y,
          c.p1.x - (c.Width() * remaining / offer->size), c.p1.y
        ), 
        Color(0.2f, 1.0f, 1.0f, pi.alphaScale), 
        Color(0.1f, 0.5f, 0.5f, pi.alphaScale)
      );

    }
예제 #18
0
bool PaintLayerPainter::needsToClip(const PaintLayerPaintingInfo& localPaintingInfo, const ClipRect& clipRect)
{
    return clipRect.rect() != localPaintingInfo.paintDirtyRect || clipRect.hasRadius();
}