Bug 1170052 part 2: Support object-fit & object-position on XUL <image src=""> elements. r=seth
☠☠ backed out by c117126d24e7 ☠ ☠
authorDaniel Holbert <dholbert@cs.stanford.edu>
Fri, 12 Jun 2015 11:40:36 -0700
changeset 279429 b84154e35c7747d71bc1096b1e00b74a4d15b097
parent 279428 d3a9981cf85892938f0054ee1b96afefe0e187d3
child 279430 629a920112ee10beae64510be88658742f427619
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersseth
bugs1170052
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1170052 part 2: Support object-fit & object-position on XUL <image src=""> elements. r=seth
layout/xul/nsImageBoxFrame.cpp
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -10,16 +10,17 @@
 // See documentation in associated header file
 //
 
 #include "nsImageBoxFrame.h"
 #include "nsGkAtoms.h"
 #include "nsRenderingContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
+#include "nsStyleUtil.h"
 #include "nsCOMPtr.h"
 #include "nsPresContext.h"
 #include "nsBoxLayoutState.h"
 
 #include "nsHTMLParts.h"
 #include "nsString.h"
 #include "nsLeafFrame.h"
 #include "nsIPresShell.h"
@@ -46,16 +47,17 @@
 #include "ImageLayers.h"
 #include "ImageContainer.h"
 #include "nsIContent.h"
 
 #include "nsContentUtils.h"
 
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/Maybe.h"
 
 #define ONLOAD_CALLED_TOO_EARLY 1
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 using namespace mozilla::layers;
 
@@ -302,60 +304,103 @@ nsImageBoxFrame::BuildDisplayList(nsDisp
     // scaling work while we wait for our image dimensions to arrive
     // asynchronously.
     return;
   }
 
   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));
 
   CreateOwnLayerIfNeeded(aBuilder, &list);
 
   aLists.Content()->AppendToTop(&list);
 }
 
 DrawResult
 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.
     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, rect)) {
+  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),
-           rect, dirty, nullptr, aFlags, nullptr,
+           dest, dirty, nullptr, aFlags,
+           anchorPoint.ptrOr(nullptr),
            hasSubRect ? &mSubRect : nullptr);
 }
 
 void nsDisplayXULImage::Paint(nsDisplayListBuilder* aBuilder,
                               nsRenderingContext* aCtx)
 {
   uint32_t flags = imgIContainer::FLAG_NONE;
   if (aBuilder->ShouldSyncDecodeImages())