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); }
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())); } }
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); } }
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()); } }
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())); } }
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; }
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; }
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; }
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(); } }
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; }
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()); } }
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())); } }
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)); }
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); }
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())); } } }
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) ); }
bool PaintLayerPainter::needsToClip(const PaintLayerPaintingInfo& localPaintingInfo, const ClipRect& clipRect) { return clipRect.rect() != localPaintingInfo.paintDirtyRect || clipRect.hasRadius(); }