DrawResult nsGroupBoxFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect) { DrawTarget* drawTarget = aRenderingContext.GetDrawTarget(); gfxContext* gfx = aRenderingContext.ThebesContext(); Sides skipSides; const nsStyleBorder* borderStyleData = StyleBorder(); const nsMargin& border = borderStyleData->GetComputedBorder(); nscoord yoff = 0; nsPresContext* presContext = PresContext(); nsRect groupRect; nsIFrame* groupBox = GetCaptionBox(presContext, groupRect); if (groupBox) { // if the border is smaller than the legend. Move the border down // to be centered on the legend. nsMargin groupMargin; groupBox->StyleMargin()->GetMargin(groupMargin); groupRect.Inflate(groupMargin); if (border.top < groupRect.height) yoff = (groupRect.height - border.top)/2 + groupRect.y; } nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff); groupRect += aPt; DrawResult result = nsCSSRendering::PaintBackground(presContext, aRenderingContext, this, aDirtyRect, rect, nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES); if (groupBox) { int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel(); // we should probably use PaintBorderEdges to do this but for now just use clipping // to achieve the same effect. // draw left side nsRect clipRect(rect); clipRect.width = groupRect.x - rect.x; clipRect.height = border.top; gfx->Save(); gfx->Clip(NSRectToSnappedRect(clipRect, appUnitsPerDevPixel, *drawTarget)); result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, rect, mStyleContext, PaintBorderFlags::SYNC_DECODE_IMAGES, skipSides); gfx->Restore(); // draw right side clipRect = rect; clipRect.x = groupRect.XMost(); clipRect.width = rect.XMost() - groupRect.XMost(); clipRect.height = border.top; gfx->Save(); gfx->Clip(NSRectToSnappedRect(clipRect, appUnitsPerDevPixel, *drawTarget)); result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, rect, mStyleContext, PaintBorderFlags::SYNC_DECODE_IMAGES, skipSides); gfx->Restore(); // draw bottom clipRect = rect; clipRect.y += border.top; clipRect.height = mRect.height - (yoff + border.top); gfx->Save(); gfx->Clip(NSRectToSnappedRect(clipRect, appUnitsPerDevPixel, *drawTarget)); result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, rect, mStyleContext, PaintBorderFlags::SYNC_DECODE_IMAGES, skipSides); gfx->Restore(); } else { result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, nsRect(aPt, GetSize()), mStyleContext, PaintBorderFlags::SYNC_DECODE_IMAGES, skipSides); } return result; }
DrawResult nsFieldSetFrame::PaintBorderBackground( nsDisplayListBuilder* aBuilder, nsRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect) { // if the border is smaller than the legend. Move the border down // to be centered on the legend. // FIXME: This means border-radius clamping is incorrect; we should // override nsIFrame::GetBorderRadii. WritingMode wm = GetWritingMode(); nsRect rect = VisualBorderRectRelativeToSelf(); nscoord off = wm.IsVertical() ? rect.x : rect.y; rect += aPt; nsPresContext* presContext = PresContext(); uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags(); PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages() ? PaintBorderFlags::SYNC_DECODE_IMAGES : PaintBorderFlags(); DrawResult result = nsCSSRendering::PaintBackground(presContext, aRenderingContext, this, aDirtyRect, rect, bgFlags); nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext, this, rect, aDirtyRect); if (nsIFrame* legend = GetLegend()) { css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart); nscoord legendBorderWidth = StyleBorder()->GetComputedBorderWidth(legendSide); // Use the rect of the legend frame, not mLegendRect, so we draw our // border under the legend's inline-start and -end margins. LogicalRect legendRect(wm, legend->GetRect() + aPt, rect.Size()); // Compute clipRect using logical coordinates, so that the legend space // will be clipped out of the appropriate physical side depending on mode. LogicalRect clipRect = LogicalRect(wm, rect, rect.Size()); DrawTarget* drawTarget = aRenderingContext.GetDrawTarget(); gfxContext* gfx = aRenderingContext.ThebesContext(); int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); // draw inline-start portion of the block-start side of the border clipRect.ISize(wm) = legendRect.IStart(wm) - clipRect.IStart(wm); clipRect.BSize(wm) = legendBorderWidth; gfx->Save(); gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.Size()), appUnitsPerDevPixel, *drawTarget)); result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, rect, mStyleContext, borderFlags); gfx->Restore(); // draw inline-end portion of the block-start side of the border clipRect = LogicalRect(wm, rect, rect.Size()); clipRect.ISize(wm) = clipRect.IEnd(wm) - legendRect.IEnd(wm); clipRect.IStart(wm) = legendRect.IEnd(wm); clipRect.BSize(wm) = legendBorderWidth; gfx->Save(); gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.Size()), appUnitsPerDevPixel, *drawTarget)); result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, rect, mStyleContext, borderFlags); gfx->Restore(); // draw remainder of the border (omitting the block-start side) clipRect = LogicalRect(wm, rect, rect.Size()); clipRect.BStart(wm) += legendBorderWidth; clipRect.BSize(wm) = BSize(wm) - (off + legendBorderWidth); gfx->Save(); gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.Size()), appUnitsPerDevPixel, *drawTarget)); result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, rect, mStyleContext, borderFlags); gfx->Restore(); } else { result &= nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, aDirtyRect, nsRect(aPt, mRect.Size()), mStyleContext, borderFlags); } return result; }
DrawResult nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt, uint32_t aFlags) { nsRect constraintRect; GetClientRect(constraintRect); constraintRect += aPt; if (!mImageRequest) { // This probably means we're drawn by a native theme. return DrawResult::SUCCESS; } // don't draw if the image is not dirty // XXX(seth): Can this actually happen anymore? nsRect dirty; if (!dirty.IntersectRect(aDirtyRect, constraintRect)) { return DrawResult::TEMPORARY_ERROR; } nsCOMPtr<imgIContainer> imgCon; mImageRequest->GetImage(getter_AddRefs(imgCon)); if (!imgCon) { return DrawResult::NOT_READY; } bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0); Maybe<nsPoint> anchorPoint; nsRect dest; if (!mUseSrcAttr) { // Our image (if we have one) is coming from the CSS property // 'list-style-image' (combined with '-moz-image-region'). For now, ignore // 'object-fit' & 'object-position' in this case, and just fill our rect. // XXXdholbert Should we even honor these properties in this case? They only // apply to replaced elements, and I'm not sure we count as a replaced // element when our image data is determined by CSS. dest = constraintRect; } else { // Determine dest rect based on intrinsic size & ratio, along with // 'object-fit' & 'object-position' properties: IntrinsicSize intrinsicSize; nsSize intrinsicRatio; if (mIntrinsicSize.width > 0 && mIntrinsicSize.height > 0) { // Image has a valid size; use it as intrinsic size & ratio. intrinsicSize.width.SetCoordValue(mIntrinsicSize.width); intrinsicSize.height.SetCoordValue(mIntrinsicSize.height); intrinsicRatio = mIntrinsicSize; } else { // Image doesn't have a (valid) intrinsic size. // Try to look up intrinsic ratio and use that at least. imgCon->GetIntrinsicRatio(&intrinsicRatio); } anchorPoint.emplace(); dest = nsLayoutUtils::ComputeObjectDestRect(constraintRect, intrinsicSize, intrinsicRatio, StylePosition(), anchorPoint.ptr()); } return nsLayoutUtils::DrawSingleImage( *aRenderingContext.ThebesContext(), PresContext(), imgCon, nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, dirty, nullptr, aFlags, anchorPoint.ptrOr(nullptr), hasSubRect ? &mSubRect : nullptr); }