diff --git a/layout/xul/nsImageBoxFrame.cpp b/layout/xul/nsImageBoxFrame.cpp index 10538a785e99..f830ed6acc53 100644 --- a/layout/xul/nsImageBoxFrame.cpp +++ b/layout/xul/nsImageBoxFrame.cpp @@ -15,6 +15,7 @@ #include "nsRenderingContext.h" #include "nsStyleContext.h" #include "nsStyleConsts.h" +#include "nsStyleUtil.h" #include "nsCOMPtr.h" #include "nsPresContext.h" #include "nsBoxLayoutState.h" @@ -51,6 +52,7 @@ #include "mozilla/BasicEvents.h" #include "mozilla/EventDispatcher.h" +#include "mozilla/Maybe.h" #define ONLOAD_CALLED_TOO_EARLY 1 @@ -307,6 +309,13 @@ nsImageBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (!IsVisibleForPainting(aBuilder)) return; + uint32_t clipFlags = + nsStyleUtil::ObjectPropsMightCauseOverflow(StylePosition()) ? + 0 : DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT; + + DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox + clip(aBuilder, this, clipFlags); + nsDisplayList list; list.AppendNewToTop( new (aBuilder) nsDisplayXULImage(aBuilder, this)); @@ -321,10 +330,10 @@ nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt, uint32_t aFlags) { - nsRect rect; - GetClientRect(rect); + nsRect constraintRect; + GetClientRect(constraintRect); - rect += aPt; + constraintRect += aPt; if (!mImageRequest) { // This probably means we're drawn by a native theme. @@ -334,7 +343,7 @@ nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext, // don't draw if the image is not dirty // XXX(seth): Can this actually happen anymore? nsRect dirty; - if (!dirty.IntersectRect(aDirtyRect, rect)) { + if (!dirty.IntersectRect(aDirtyRect, constraintRect)) { return DrawResult::TEMPORARY_ERROR; } @@ -346,11 +355,47 @@ nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext, } bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0); + + Maybe 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), - rect, dirty, nullptr, aFlags, nullptr, + dest, dirty, nullptr, aFlags, + anchorPoint.ptrOr(nullptr), hasSubRect ? &mSubRect : nullptr); }