--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1702,27 +1702,29 @@ nsCSSFrameConstructor::CreateGenConTextN
aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
}
return content.forget();
}
already_AddRefed<nsIContent>
nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
Element* aParentContent,
+ nsIFrame* aParentFrame,
ComputedStyle* aComputedStyle,
- uint32_t aContentIndex)
+ uint32_t aContentIndex)
{
// Get the content value
- const nsStyleContentData &data =
+ const nsStyleContentData& data =
aComputedStyle->StyleContent()->ContentAt(aContentIndex);
nsStyleContentType type = data.GetType();
switch (type) {
case eStyleContentType_Image: {
- imgRequestProxy* image = data.GetImage();
+ imgRequestProxy* image =
+ aParentFrame->GetImageRequest(*data.ImageRequest());
if (!image) {
// CSS had something specified that couldn't be converted to an
// image object
return nullptr;
}
// Create an image content object and pass it the image request.
// XXX Check if it's an image type we can handle...
@@ -1911,18 +1913,18 @@ nsCSSFrameConstructor::CreateGeneratedCo
// and replace old one.
mPresShell->StyleSet()->StyleNewSubtree(container);
pseudoComputedStyle = styleSet->ResolveServoStyle(container);
}
uint32_t contentCount = pseudoComputedStyle->StyleContent()->ContentCount();
for (uint32_t contentIndex = 0; contentIndex < contentCount; contentIndex++) {
nsCOMPtr<nsIContent> content =
- CreateGeneratedContent(aState, aParentContent, pseudoComputedStyle,
- contentIndex);
+ CreateGeneratedContent(aState, aParentContent, aParentFrame,
+ pseudoComputedStyle, contentIndex);
if (content) {
container->AppendChildTo(content, false);
if (content->IsElement()) {
// If we created any children elements, Servo needs to traverse them, but
// the root is already set up.
mPresShell->StyleSet()->StyleNewSubtree(content->AsElement());
}
}
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -462,16 +462,17 @@ private:
* The caller takes care of making it SetIsNativeAnonymousRoot, binding it
* to the document, and creating frames for it.
* @param aParentContent is the node that has the before/after style
* @param aComputedStyle is the 'before' or 'after' pseudo-element style.
* @param aContentIndex is the index of the content item to create
*/
already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
mozilla::dom::Element* aParentContent,
+ nsIFrame* aParentFrame,
ComputedStyle* aComputedStyle,
uint32_t aContentIndex);
// aFrame may be null; this method doesn't use it directly in any case.
void CreateGeneratedContentItem(nsFrameConstructorState& aState,
nsContainerFrame* aFrame,
mozilla::dom::Element* aContent,
ComputedStyle* aComputedStyle,
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -7097,24 +7097,24 @@ nsBlockFrame::CreateBulletFrameForListIt
bool
nsBlockFrame::BulletIsEmpty() const
{
NS_ASSERTION(mContent->GetPrimaryFrame()->StyleDisplay()->mDisplay ==
mozilla::StyleDisplay::ListItem && HasOutsideBullet(),
"should only care when we have an outside bullet");
const nsStyleList* list = StyleList();
return list->mCounterStyle->IsNone() &&
- !list->GetListStyleImage();
+ !GetImageRequest(list->mListStyleImage);
}
void
nsBlockFrame::GetSpokenBulletText(nsAString& aText) const
{
const nsStyleList* myList = StyleList();
- if (myList->GetListStyleImage()) {
+ if (GetImageRequest(myList->mListStyleImage)) {
aText.Assign(kDiscCharacter);
aText.Append(' ');
} else {
nsBulletFrame* bullet = GetBullet();
if (bullet) {
bullet->GetSpokenText(aText);
} else {
aText.Truncate();
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -101,20 +101,18 @@ nsBulletFrame::IsSelfEmpty()
return StyleList()->mCounterStyle->IsNone();
}
/* virtual */ void
nsBulletFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle)
{
nsFrame::DidSetComputedStyle(aOldComputedStyle);
- imgRequestProxy *newRequest = StyleList()->GetListStyleImage();
-
+ imgRequestProxy* newRequest = GetImageRequest(StyleList()->mListStyleImage);
if (newRequest) {
-
if (!mListener) {
mListener = new nsBulletListener();
mListener->SetFrame(this);
}
bool needNewRequest = true;
if (mImageRequest) {
@@ -155,21 +153,21 @@ nsBulletFrame::DidSetComputedStyle(Compu
#ifdef ACCESSIBILITY
// Update the list bullet accessible. If old style list isn't available then
// no need to update the accessible tree because it's not created yet.
if (aOldComputedStyle) {
nsAccessibilityService* accService = nsIPresShell::AccService();
if (accService) {
const nsStyleList* oldStyleList = aOldComputedStyle->PeekStyleList();
if (oldStyleList) {
- bool hadBullet = oldStyleList->GetListStyleImage() ||
+ bool hadBullet = GetImageRequest(oldStyleList->mListStyleImage) ||
!oldStyleList->mCounterStyle->IsNone();
const nsStyleList* newStyleList = StyleList();
- bool hasBullet = newStyleList->GetListStyleImage() ||
+ bool hasBullet = GetImageRequest(newStyleList->mListStyleImage) ||
!newStyleList->mCounterStyle->IsNone();
if (hadBullet != hasBullet) {
accService->UpdateListBullet(PresContext()->GetPresShell(), mContent,
hasBullet);
}
}
}
@@ -736,17 +734,17 @@ nsBulletFrame::BuildDisplayList(nsDispla
Maybe<BulletRenderer>
nsBulletFrame::CreateBulletRenderer(gfxContext& aRenderingContext, nsPoint aPt)
{
const nsStyleList* myList = StyleList();
CounterStyle* listStyleType = myList->mCounterStyle;
nsMargin padding = mPadding.GetPhysicalMargin(GetWritingMode());
- if (myList->GetListStyleImage() && mImageRequest) {
+ if (GetImageRequest(myList->mListStyleImage) && mImageRequest) {
uint32_t status;
mImageRequest->GetImageStatus(&status);
if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
!(status & imgIRequest::STATUS_ERROR)) {
nsCOMPtr<imgIContainer> imageCon;
mImageRequest->GetImage(getter_AddRefs(imageCon));
if (imageCon) {
nsRect dest(padding.left, padding.top,
@@ -986,17 +984,20 @@ nsBulletFrame::GetDesiredSize(nsPresCont
const nsStyleList* myList = StyleList();
nscoord ascent;
RefPtr<nsFontMetrics> fm =
nsLayoutUtils::GetFontMetricsForFrame(this, aFontSizeInflation);
RemoveStateBits(BULLET_FRAME_IMAGE_LOADING);
- if (myList->GetListStyleImage() && mImageRequest) {
+ // FIXME(emilio): Moderately sure the GetImageRequest checks here are not
+ // needed and are an artifact from bug 1310463. Checking mImageRequest should
+ // just work here.
+ if (GetImageRequest(myList->mListStyleImage) && mImageRequest) {
uint32_t status;
mImageRequest->GetImageStatus(&status);
if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
!(status & imgIRequest::STATUS_ERROR)) {
// auto size the image
finalSize.ISize(wm) = mIntrinsicSize.ISize(wm);
aMetrics.SetBlockStartAscent(finalSize.BSize(wm) =
mIntrinsicSize.BSize(wm));
@@ -1139,17 +1140,17 @@ nsBulletFrame::GetPrefISize(gfxContext *
static inline bool
IsIgnoreable(const nsIFrame* aFrame, nscoord aISize)
{
if (aISize != nscoord(0)) {
return false;
}
auto listStyle = aFrame->StyleList();
return listStyle->mCounterStyle->IsNone() &&
- !listStyle->GetListStyleImage();
+ !aFrame->GetImageRequest(listStyle->mListStyleImage);
}
/* virtual */ void
nsBulletFrame::AddInlineMinISize(gfxContext* aRenderingContext,
nsIFrame::InlineMinISizeData* aData)
{
nscoord isize = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
this, nsLayoutUtils::MIN_ISIZE);
@@ -1321,17 +1322,17 @@ nsBulletFrame::SetFontSizeInflation(floa
AddStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
SetProperty(FontSizeInflationProperty(), aInflation);
}
already_AddRefed<imgIContainer>
nsBulletFrame::GetImage() const
{
- if (mImageRequest && StyleList()->GetListStyleImage()) {
+ if (mImageRequest && GetImageRequest(StyleList()->mListStyleImage)) {
nsCOMPtr<imgIContainer> imageCon;
mImageRequest->GetImage(getter_AddRefs(imageCon));
return imageCon.forget();
}
return nullptr;
}
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -588,17 +588,17 @@ public:
nscoord aShapeMargin,
nsIFrame* const aFrame,
const LogicalRect& aShapeBoxRect,
const LogicalRect& aMarginRect,
WritingMode aWM,
const nsSize& aContainerSize);
static UniquePtr<ShapeInfo> CreateImageShape(
- const UniquePtr<nsStyleImage>& aShapeImage,
+ nsStyleImage& aShapeImage,
float aShapeImageThreshold,
nscoord aShapeMargin,
nsIFrame* const aFrame,
const LogicalRect& aMarginRect,
WritingMode aWM,
const nsSize& aContainerSize);
protected:
@@ -2366,17 +2366,17 @@ nsFloatManager::FloatInfo::FloatInfo(nsI
return;
case StyleShapeSourceType::URL:
MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have URL source type!");
return;
case StyleShapeSourceType::Image: {
float shapeImageThreshold = mFrame->StyleDisplay()->mShapeImageThreshold;
- mShapeInfo = ShapeInfo::CreateImageShape(shapeOutside.GetShapeImage(),
+ mShapeInfo = ShapeInfo::CreateImageShape(shapeOutside.ShapeImage(),
shapeImageThreshold,
shapeMargin,
mFrame,
aMarginRect,
aWM,
aContainerSize);
if (!mShapeInfo) {
// Image is not ready, or fails to load, etc.
@@ -2767,29 +2767,29 @@ nsFloatManager::ShapeInfo::CreatePolygon
// computes the float area using a rasterization method.
int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
return MakeUnique<PolygonShapeInfo>(Move(vertices), aShapeMargin,
appUnitsPerDevPixel, marginRect);
}
/* static */ UniquePtr<nsFloatManager::ShapeInfo>
nsFloatManager::ShapeInfo::CreateImageShape(
- const UniquePtr<nsStyleImage>& aShapeImage,
+ nsStyleImage& aShapeImage,
float aShapeImageThreshold,
nscoord aShapeMargin,
nsIFrame* const aFrame,
const LogicalRect& aMarginRect,
WritingMode aWM,
const nsSize& aContainerSize)
{
- MOZ_ASSERT(aShapeImage ==
- aFrame->StyleDisplay()->mShapeOutside.GetShapeImage(),
+ MOZ_ASSERT(&aShapeImage ==
+ &aFrame->StyleDisplay()->mShapeOutside.ShapeImage(),
"aFrame should be the frame that we got aShapeImage from");
- nsImageRenderer imageRenderer(aFrame, aShapeImage.get(),
+ nsImageRenderer imageRenderer(aFrame, &aShapeImage,
nsImageRenderer::FLAG_SYNC_DECODE_IMAGES);
if (!imageRenderer.PrepareImage()) {
// The image is not ready yet.
return nullptr;
}
nsRect contentRect = aFrame->GetContentRect();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -840,34 +840,41 @@ nsresult
nsFrame::GetOffsets(int32_t &aStart, int32_t &aEnd) const
{
aStart = 0;
aEnd = 0;
return NS_OK;
}
static void
-CompareLayers(const nsStyleImageLayers* aFirstLayers,
+CompareLayers(nsIFrame* aFrame,
+ const nsStyleImageLayers* aFirstLayers,
const nsStyleImageLayers* aSecondLayers,
const std::function<void(imgRequestProxy* aReq)>& aCallback)
{
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aFirstLayers)) {
const nsStyleImage& image = aFirstLayers->mLayers[i].mImage;
+ // TODO(emilio): Pretty sure the image is always resolved already by the
+ // time we get here.
if (image.GetType() != eStyleImageType_Image || !image.IsResolved()) {
continue;
}
// aCallback is called when the style image in aFirstLayers is thought to
// be different with the corresponded one in aSecondLayers
+ imgRequestProxy* thisRequest =
+ aFrame->GetImageRequest(*image.ImageRequest());
+ if (!thisRequest) {
+ continue;
+ }
+
if (!aSecondLayers || i >= aSecondLayers->mImageCount ||
- (!aSecondLayers->mLayers[i].mImage.IsResolved() ||
- !image.ImageDataEquals(aSecondLayers->mLayers[i].mImage))) {
- if (imgRequestProxy* req = image.GetImageData()) {
- aCallback(req);
- }
+ !aSecondLayers->mLayers[i].mImage.IsResolved() ||
+ thisRequest != aFrame->GetImageRequest(aSecondLayers->mLayers[i].mImage)) {
+ aCallback(thisRequest);
}
}
}
static void
AddAndRemoveImageAssociations(nsFrame* aFrame,
const nsStyleImageLayers* aOldLayers,
const nsStyleImageLayers* aNewLayers)
@@ -879,23 +886,23 @@ AddAndRemoveImageAssociations(nsFrame* a
// and new context does not have the same image, clear the image load
// notifier (which keeps the image loading, if it still is) for the frame.
// We want to do this conservatively because some frames paint their
// backgrounds from some other frame's style data, and we don't want
// to clear those notifiers unless we have to. (They'll be reset
// when we paint, although we could miss a notification in that
// interval.)
if (aOldLayers && aFrame->HasImageRequest()) {
- CompareLayers(aOldLayers, aNewLayers,
+ CompareLayers(aFrame, aOldLayers, aNewLayers,
[&imageLoader, aFrame](imgRequestProxy* aReq)
{ imageLoader->DisassociateRequestFromFrame(aReq, aFrame); }
);
}
- CompareLayers(aNewLayers, aOldLayers,
+ CompareLayers(aFrame, aNewLayers, aOldLayers,
[&imageLoader, aFrame](imgRequestProxy* aReq)
{ imageLoader->AssociateRequestToFrame(aReq, aFrame, 0); }
);
}
void
nsIFrame::AddDisplayItem(nsDisplayItem* aItem)
{
@@ -1131,20 +1138,21 @@ nsFrame::DidSetComputedStyle(ComputedSty
if (oldValue != newValue &&
!HasProperty(UsedBorderProperty())) {
AddProperty(UsedBorderProperty(), new nsMargin(oldValue));
}
}
}
ImageLoader* imageLoader = PresContext()->Document()->StyleImageLoader();
- imgIRequest *oldBorderImage = aOldComputedStyle
- ? aOldComputedStyle->StyleBorder()->GetBorderImageRequest()
+ imgRequestProxy* oldBorderImage = aOldComputedStyle
+ ? GetImageRequest(aOldComputedStyle->StyleBorder()->mBorderImageSource)
: nullptr;
- imgIRequest *newBorderImage = StyleBorder()->GetBorderImageRequest();
+ imgRequestProxy* newBorderImage =
+ GetImageRequest(StyleBorder()->mBorderImageSource);
// FIXME (Bug 759996): The following is no longer true.
// For border-images, we can't be as conservative (we need to set the
// new loaders if there has been any change) since the CalcDifference
// call depended on the result of GetComputedBorder() and that result
// depends on whether the image has loaded, start the image load now
// so that we'll get notified when it completes loading and can do a
// restyle. Otherwise, the image might finish loading from the
// network before we start listening to its notifications, and then
@@ -1160,21 +1168,22 @@ nsFrame::DidSetComputedStyle(ComputedSty
imageLoader->DisassociateRequestFromFrame(oldBorderImage, this);
}
if (newBorderImage) {
imageLoader->AssociateRequestToFrame(newBorderImage, this, 0);
}
}
imgIRequest* oldShapeImage =
- aOldComputedStyle
- ? aOldComputedStyle->StyleDisplay()->mShapeOutside.GetShapeImageData()
- : nullptr;
+ aOldComputedStyle
+ ? GetImageRequest(aOldComputedStyle->StyleDisplay()->mShapeOutside.GetShapeImage())
+ : nullptr;
+
imgIRequest* newShapeImage =
- StyleDisplay()->mShapeOutside.GetShapeImageData();
+ GetImageRequest(StyleDisplay()->mShapeOutside.GetShapeImage());
if (oldShapeImage != newShapeImage) {
if (oldShapeImage && HasImageRequest()) {
imageLoader->DisassociateRequestFromFrame(oldShapeImage, this);
}
if (newShapeImage) {
imageLoader->AssociateRequestToFrame(newShapeImage, this,
ImageLoader::REQUEST_REQUIRES_REFLOW);
@@ -5218,34 +5227,29 @@ nsIFrame::ContentOffsets nsFrame::CalcCo
{
return OffsetsForSingleFrame(this, aPoint);
}
void
nsIFrame::AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext,
uint32_t aImageLoaderFlags)
{
- if (aImage.GetType() != eStyleImageType_Image) {
- return;
- }
-
- imgRequestProxy* req = aImage.GetImageData();
+ imgRequestProxy* req = GetImageRequest(aImage);
if (!req) {
return;
}
mozilla::css::ImageLoader* loader =
aPresContext->Document()->StyleImageLoader();
// If this fails there's not much we can do ...
loader->AssociateRequestToFrame(req, this, aImageLoaderFlags);
}
nsresult
-nsFrame::GetCursor(const nsPoint& aPoint,
- nsIFrame::Cursor& aCursor)
+nsFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
{
FillCursorInformationFromStyle(StyleUserInterface(), aCursor);
if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) {
// If this is editable, I-beam cursor is better for most elements.
aCursor.mCursor =
(mContent && mContent->IsEditable())
? NS_STYLE_CURSOR_TEXT : NS_STYLE_CURSOR_DEFAULT;
}
@@ -10113,17 +10117,17 @@ void nsFrame::FillCursorInformationFromS
{
aCursor.mCursor = ui->mCursor;
aCursor.mHaveHotspot = false;
aCursor.mLoading = false;
aCursor.mHotspotX = aCursor.mHotspotY = 0.0f;
for (const nsCursorImage& item : ui->mCursorImages) {
uint32_t status;
- imgRequestProxy* req = item.GetImage();
+ imgRequestProxy* req = GetImageRequest(item.mImage);
if (!req || NS_FAILED(req->GetImageStatus(&status))) {
continue;
}
if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
// If we are falling back because any cursor before is loading,
// let the consumer know.
aCursor.mLoading = true;
} else if (!(status & imgIRequest::STATUS_ERROR)) {
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -674,18 +674,21 @@ protected:
nsresult GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
nsIPresShell* aPresShell,
mozilla::WidgetMouseEvent* aMouseEvent,
nsIContent** aParentContent,
int32_t* aContentOffset,
mozilla::TableSelection* aTarget);
// Fills aCursor with the appropriate information from ui
- static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
- nsIFrame::Cursor& aCursor);
+ //
+ // NOTE: the nsStyleUserInterface could be from a pseudo style instead of our
+ // style.
+ void FillCursorInformationFromStyle(const nsStyleUserInterface* aUi,
+ nsIFrame::Cursor& aCursor);
NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
nsBoxLayoutMetrics* BoxMetrics() const;
// Fire DOM event. If no aContent argument use frame's mContent.
void FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent = nullptr);
private:
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -63,16 +63,17 @@
* 4. if you move a frame (outside of the reflow process, or after reflowing it),
* then you must make sure that its view (or its child frame's views) are re-positioned
* as well. It's reasonable to not position the view until after all reflowing the
* entire line, for example, but the frame should still be positioned and sized (and
* the view sized) during the reflow (i.e., before sending the DidReflow() notification)
* 5. the view system handles moving of widgets, i.e., it's not our problem
*/
+class imgRequestProxy;
class nsAtom;
class nsPresContext;
class nsIPresShell;
class nsView;
class nsIWidget;
class nsISelectionController;
class nsBoxLayoutState;
class nsBoxLayout;
@@ -4095,16 +4096,47 @@ public:
// Returns true if this frame is visible or may have visible descendants.
bool IsVisibleOrMayHaveVisibleDescendants() const {
return !mAllDescendantsAreInvisible || StyleVisibility()->IsVisible();
}
// Update mAllDescendantsAreInvisible flag for this frame and ancestors.
void UpdateVisibleDescendantsState();
+ // Gets an image request for a given nsStyleImage, or null if the image is not
+ // well, an image, but other thing like, e.g., a gradient.
+ imgRequestProxy* GetImageRequest(const nsStyleImage& aImage) const
+ {
+ if (aImage.GetType() != eStyleImageType_Image) {
+ return nullptr;
+ }
+
+ return GetImageRequest(*aImage.ImageRequest());
+ }
+
+ imgRequestProxy* GetImageRequest(const nsStyleImage* aImage) const
+ {
+ return aImage ? GetImageRequest(*aImage) : nullptr;
+ }
+
+ // Gets an image request for a given nsStyleImageRequest.
+ //
+ // NOTE(emilio): This is a temporary state until we move resolved image
+ // requests outside of the style system.
+ imgRequestProxy* GetImageRequest(nsStyleImageRequest& aRequest) const
+ {
+ return aRequest.get();
+ }
+
+ // Gets an image request for a given nsStyleImageRequest.
+ imgRequestProxy* GetImageRequest(nsStyleImageRequest* aRequest) const
+ {
+ return aRequest ? GetImageRequest(*aRequest) : nullptr;
+ }
+
/**
* If this returns true, the frame it's called on should get the
* NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
* if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
* reflow.
*/
virtual bool RenumberFrameAndDescendants(int32_t* aOrdinal,
int32_t aDepth,
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -2074,17 +2074,18 @@ nsCSSRendering::CanBuildWebRenderDisplay
// We only support painting gradients and image for a single style image layer
const nsStyleImage* styleImage = &aBackgroundStyle->mImage.mLayers[aLayer].mImage;
if (styleImage->GetType() == eStyleImageType_Image) {
if (styleImage->GetCropRect()) {
return false;
}
- imgRequestProxy* requestProxy = styleImage->GetImageData();
+ imgRequestProxy* requestProxy =
+ aFrame->GetImageRequest(*styleImage->ImageRequest());
if (!requestProxy) {
return false;
}
uint32_t imageFlags = imgIContainer::FLAG_NONE;
if (aPaintFlags & nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES) {
imageFlags |= imgIContainer::FLAG_SYNC_DECODE;
}
@@ -2575,17 +2576,17 @@ nsCSSRendering::DetermineBackgroundColor
// We can skip painting the background color if a background image is opaque.
nsStyleImageLayers::Repeat repeat = bg->BottomLayer().mRepeat;
bool xFullRepeat = repeat.mXRepeat == StyleImageLayerRepeat::Repeat ||
repeat.mXRepeat == StyleImageLayerRepeat::Round;
bool yFullRepeat = repeat.mYRepeat == StyleImageLayerRepeat::Repeat ||
repeat.mYRepeat == StyleImageLayerRepeat::Round;
if (aDrawBackgroundColor &&
xFullRepeat && yFullRepeat &&
- bg->BottomLayer().mImage.IsOpaque() &&
+ bg->BottomLayer().mImage.IsOpaque(aFrame) &&
bg->BottomLayer().mBlendMode == NS_STYLE_BLEND_NORMAL) {
aDrawBackgroundColor = false;
}
return bgColor;
}
static CompositionOp
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4015,17 +4015,18 @@ nsDisplayBackgroundImage::ShouldCreateOw
backgroundStyleFrame)) {
return WHENEVER_POSSIBLE;
}
if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
const nsStyleImage* image = &layer.mImage;
if (image->GetType() == eStyleImageType_Image) {
- imgIRequest* imgreq = image->GetImageData();
+ imgRequestProxy* imgreq =
+ backgroundStyleFrame->GetImageRequest(*image->ImageRequest());
nsCOMPtr<imgIContainer> image;
if (imgreq &&
NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) &&
image) {
bool animated = false;
if (NS_SUCCEEDED(image->GetAnimated(&animated)) && animated) {
return WHENEVER_POSSIBLE;
}
@@ -4234,17 +4235,18 @@ nsDisplayBackgroundImage::GetOpaqueRegio
// this could easily lead to O(N^2) behavior inside InlineBackgroundData,
// which expects frames to be sent to it in content order, not reverse
// content order which we'll produce here.
// Of course, if there's only one frame in the flow, it doesn't matter.
if (mFrame->StyleBorder()->mBoxDecorationBreak ==
StyleBoxDecorationBreak::Clone ||
(!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
const nsStyleImageLayers::Layer& layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
- if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL &&
+ if (layer.mImage.IsOpaque(mFrame) &&
+ layer.mBlendMode == NS_STYLE_BLEND_NORMAL &&
layer.mRepeat.mXRepeat != StyleImageLayerRepeat::Space &&
layer.mRepeat.mYRepeat != StyleImageLayerRepeat::Space &&
layer.mClip != StyleGeometryBox::Text) {
result = GetInsideClipRegion(this, layer.mClip, mBounds, mBackgroundRect);
}
}
return result;
@@ -4284,17 +4286,17 @@ nsDisplayBackgroundImage::RenderingMight
nscoord radii[8];
if (mFrame->GetBorderRadii(radii)) {
// A change in the size of the positioning area might change the position
// of the rounded corners.
return true;
}
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
- if (layer.RenderingMightDependOnPositioningAreaSizeChange()) {
+ if (layer.RenderingMightDependOnPositioningAreaSizeChange(mFrame)) {
return true;
}
return false;
}
void
nsDisplayBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) {
@@ -5426,17 +5428,17 @@ nsDisplayBorder::nsDisplayBorder(nsDispl
bool
nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect) const
{
nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
ToReferenceFrame();
const nsStyleBorder *styleBorder;
if (paddingRect.Contains(aRect) &&
- !(styleBorder = mFrame->StyleBorder())->IsBorderImageLoaded() &&
+ !(styleBorder = mFrame->StyleBorder())->IsBorderImageLoaded(mFrame) &&
!nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) {
// aRect is entirely inside the content rect, and no part
// of the border is rendered inside the content rect, so we are not
// visible
// Skip this if there's a border-image (which draws a background
// too) or if there is a border-radius (which makes the border draw
// further in).
return true;
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -3786,17 +3786,17 @@ protected:
mozilla::wr::IpcResourceUpdateQueue& aResource,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder);
template<typename T>
T CalculateBounds(const nsStyleBorder& aStyleBorder) const
{
nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
- if (aStyleBorder.IsBorderImageLoaded()) {
+ if (aStyleBorder.IsBorderImageLoaded(mFrame)) {
borderBounds.Inflate(aStyleBorder.GetImageOutset());
return borderBounds;
} else {
nsMargin border = aStyleBorder.GetComputedBorder();
T result;
if (border.top > 0) {
result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(), border.top);
}
--- a/layout/painting/nsImageRenderer.cpp
+++ b/layout/painting/nsImageRenderer.cpp
@@ -65,47 +65,39 @@ nsImageRenderer::nsImageRenderer(nsIFram
, mPrepareResult(ImgDrawResult::NOT_READY)
, mSize(0, 0)
, mFlags(aFlags)
, mExtendMode(ExtendMode::CLAMP)
, mMaskOp(NS_STYLE_MASK_MODE_MATCH_SOURCE)
{
}
-nsImageRenderer::~nsImageRenderer()
-{
-}
+nsImageRenderer::~nsImageRenderer() = default;
static bool
-ShouldTreatAsCompleteDueToSyncDecode(const nsStyleImage* aImage,
- uint32_t aFlags)
+ShouldTreatAsCompleteDueToSyncDecode(imgRequestProxy* aRequest, uint32_t aFlags)
{
if (!(aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES)) {
return false;
}
- if (aImage->GetType() != eStyleImageType_Image) {
- return false;
- }
-
- imgRequestProxy* req = aImage->GetImageData();
- if (!req) {
+ if (!aRequest) {
return false;
}
uint32_t status = 0;
- if (NS_FAILED(req->GetImageStatus(&status))) {
+ if (NS_FAILED(aRequest->GetImageStatus(&status))) {
return false;
}
if (status & imgIRequest::STATUS_ERROR) {
// The image is "complete" since it's a corrupt image. If we created an
// imgIContainer at all, return true.
nsCOMPtr<imgIContainer> image;
- req->GetImage(getter_AddRefs(image));
+ aRequest->GetImage(getter_AddRefs(image));
return bool(image);
}
if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
// We must have loaded all of the image's data and the size must be
// available, or else sync decoding won't be able to decode the image.
return false;
}
@@ -116,49 +108,50 @@ ShouldTreatAsCompleteDueToSyncDecode(con
bool
nsImageRenderer::PrepareImage()
{
if (mImage->IsEmpty()) {
mPrepareResult = ImgDrawResult::BAD_IMAGE;
return false;
}
- if (!mImage->IsComplete()) {
+ imgRequestProxy* request = mForFrame->GetImageRequest(*mImage);
+ if (!mImage->IsComplete(mForFrame)) {
// Make sure the image is actually decoding.
- bool frameComplete = mImage->StartDecoding();
+ bool frameComplete = mImage->StartDecoding(mForFrame);
// Check again to see if we finished.
// We cannot prepare the image for rendering if it is not fully loaded.
// Special case: If we requested a sync decode and the image has loaded, push
// on through because the Draw() will do a sync decode then.
- if (!(frameComplete || mImage->IsComplete()) &&
- !ShouldTreatAsCompleteDueToSyncDecode(mImage, mFlags)) {
+ if (!(frameComplete || mImage->IsComplete(mForFrame)) &&
+ !ShouldTreatAsCompleteDueToSyncDecode(request, mFlags)) {
mPrepareResult = ImgDrawResult::NOT_READY;
return false;
}
}
switch (mType) {
case eStyleImageType_Image: {
- MOZ_ASSERT(mImage->GetImageData(),
+ MOZ_ASSERT(request,
"must have image data, since we checked IsEmpty above");
nsCOMPtr<imgIContainer> srcImage;
DebugOnly<nsresult> rv =
- mImage->GetImageData()->GetImage(getter_AddRefs(srcImage));
+ request->GetImage(getter_AddRefs(srcImage));
MOZ_ASSERT(NS_SUCCEEDED(rv) && srcImage,
"If GetImage() is failing, mImage->IsComplete() "
"should have returned false");
if (!mImage->GetCropRect()) {
mImageContainer.swap(srcImage);
} else {
nsIntRect actualCropRect;
bool isEntireImage;
bool success =
- mImage->ComputeActualCropRect(actualCropRect, &isEntireImage);
+ mImage->ComputeActualCropRect(mForFrame, actualCropRect, &isEntireImage);
if (!success || actualCropRect.IsEmpty()) {
// The cropped image has zero size
mPrepareResult = ImgDrawResult::BAD_IMAGE;
return false;
}
if (isEntireImage) {
// The cropped image is identical to the source image
mImageContainer.swap(srcImage);
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1346,20 +1346,17 @@ nsComputedDOMStyle::DoGetContent()
case eStyleContentType_String: {
nsAutoString str;
nsStyleUtil::AppendEscapedCSSString(
nsDependentString(data.GetString()), str);
val->SetString(str);
break;
}
case eStyleContentType_Image: {
- nsCOMPtr<nsIURI> uri;
- if (imgRequestProxy* image = data.GetImage()) {
- image->GetURI(getter_AddRefs(uri));
- }
+ nsCOMPtr<nsIURI> uri = data.ImageRequest()->GetImageURI();
val->SetURI(uri);
break;
}
case eStyleContentType_Attr: {
// XXXbholley: We don't correctly serialize namespaces here. Doing so
// would require either storing the prefix on the nsStyleContentAttr,
// or poking at the namespaces in the stylesheet to map from the
// namespace URL.
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1050,28 +1050,16 @@ StyleShapeSource::SetURL(css::URLValue*
void
StyleShapeSource::SetShapeImage(UniquePtr<nsStyleImage> aShapeImage)
{
MOZ_ASSERT(aShapeImage);
mShapeImage = Move(aShapeImage);
mType = StyleShapeSourceType::Image;
}
-imgIRequest*
-StyleShapeSource::GetShapeImageData() const
-{
- if (mType != StyleShapeSourceType::Image) {
- return nullptr;
- }
- if (mShapeImage->GetType() != eStyleImageType_Image) {
- return nullptr;
- }
- return mShapeImage->GetImageData();
-}
-
void
StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
StyleGeometryBox aReferenceBox)
{
MOZ_ASSERT(aBasicShape);
mBasicShape = Move(aBasicShape);
mReferenceBox = aReferenceBox;
mType = StyleShapeSourceType::Shape;
@@ -2464,24 +2452,25 @@ nsStyleImageRequest::GetImageURI() const
return nullptr;
}
uri = mImageValue->GetURI();
return uri.forget();
}
bool
-nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
+nsStyleImage::ComputeActualCropRect(nsIFrame* aForFrame,
+ nsIntRect& aActualCropRect,
bool* aIsEntireImage) const
{
MOZ_ASSERT(mType == eStyleImageType_Image,
"This function is designed to be used only when mType"
"is eStyleImageType_Image.");
- imgRequestProxy* req = GetImageData();
+ imgRequestProxy* req = aForFrame->GetImageRequest(*ImageRequest());
if (!req) {
return false;
}
nsCOMPtr<imgIContainer> imageContainer;
req->GetImage(getter_AddRefs(imageContainer));
if (!imageContainer) {
return false;
@@ -2506,107 +2495,109 @@ nsStyleImage::ComputeActualCropRect(nsIn
if (aIsEntireImage) {
*aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
}
return true;
}
bool
-nsStyleImage::StartDecoding() const
+nsStyleImage::StartDecoding(nsIFrame* aForFrame) const
{
if (mType == eStyleImageType_Image) {
- imgRequestProxy* req = GetImageData();
+ imgRequestProxy* req = aForFrame->GetImageRequest(*ImageRequest());
if (!req) {
return false;
}
return req->StartDecodingWithResult(imgIContainer::FLAG_ASYNC_NOTIFY);
}
// null image types always return false from IsComplete, so we do the same here.
- return mType != eStyleImageType_Null ? true : false;
+ return mType != eStyleImageType_Null;
}
bool
-nsStyleImage::IsOpaque() const
-{
- if (!IsComplete()) {
+nsStyleImage::IsOpaque(nsIFrame* aForFrame) const
+{
+ if (!IsComplete(aForFrame)) {
return false;
}
if (mType == eStyleImageType_Gradient) {
return mGradient->IsOpaque();
}
if (mType == eStyleImageType_Element || mType == eStyleImageType_URL) {
return false;
}
MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
- MOZ_ASSERT(GetImageData(), "should've returned earlier above");
+ imgRequestProxy* req = aForFrame->GetImageRequest(*ImageRequest());
+ MOZ_ASSERT(req, "should've returned earlier above");
nsCOMPtr<imgIContainer> imageContainer;
- GetImageData()->GetImage(getter_AddRefs(imageContainer));
+ req->GetImage(getter_AddRefs(imageContainer));
MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
// Check if the crop region of the image is opaque.
if (imageContainer->WillDrawOpaqueNow()) {
if (!mCropRect) {
return true;
}
// Must make sure if mCropRect contains at least a pixel.
// XXX Is this optimization worth it? Maybe I should just return false.
nsIntRect actualCropRect;
- return ComputeActualCropRect(actualCropRect) && !actualCropRect.IsEmpty();
+ return ComputeActualCropRect(aForFrame, actualCropRect) &&
+ !actualCropRect.IsEmpty();
}
return false;
}
bool
-nsStyleImage::IsComplete() const
+nsStyleImage::IsComplete(nsIFrame* aForFrame) const
{
switch (mType) {
case eStyleImageType_Null:
return false;
case eStyleImageType_Gradient:
case eStyleImageType_Element:
case eStyleImageType_URL:
return true;
case eStyleImageType_Image: {
if (!IsResolved()) {
return false;
}
- imgRequestProxy* req = GetImageData();
+ imgRequestProxy* req = aForFrame->GetImageRequest(*ImageRequest());
if (!req) {
return false;
}
uint32_t status = imgIRequest::STATUS_ERROR;
return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
(status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
(status & imgIRequest::STATUS_FRAME_COMPLETE);
}
default:
NS_NOTREACHED("unexpected image type");
return false;
}
}
bool
-nsStyleImage::IsLoaded() const
+nsStyleImage::IsLoaded(nsIFrame* aForFrame) const
{
switch (mType) {
case eStyleImageType_Null:
return false;
case eStyleImageType_Gradient:
case eStyleImageType_Element:
case eStyleImageType_URL:
return true;
case eStyleImageType_Image: {
- imgRequestProxy* req = GetImageData();
+ imgRequestProxy* req = aForFrame->GetImageRequest(*ImageRequest());
if (!req) {
return false;
}
uint32_t status = imgIRequest::STATUS_ERROR;
return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
!(status & imgIRequest::STATUS_ERROR) &&
(status & imgIRequest::STATUS_LOAD_COMPLETE);
}
@@ -2981,17 +2972,19 @@ Position::SetInitialZeroValues()
mXPosition.mLength = 0;
mXPosition.mHasPercent = false;
mYPosition.mPercent = 0;
mYPosition.mLength = 0;
mYPosition.mHasPercent = false;
}
bool
-nsStyleImageLayers::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
+nsStyleImageLayers::Size::DependsOnPositioningAreaSize(
+ nsIFrame* aFrame,
+ const nsStyleImage& aImage) const
{
MOZ_ASSERT(aImage.GetType() != eStyleImageType_Null,
"caller should have handled this");
// If either dimension contains a non-zero percentage, rendering for that
// dimension straightforwardly depends on frame size.
if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
(mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
@@ -3026,17 +3019,17 @@ nsStyleImageLayers::Size::DependsOnPosit
// according to the spec. However, we don't implement the spec yet, so
// for now we bail and say element() plus auto affects ultimate size.
if (type == eStyleImageType_Element) {
return true;
}
if (type == eStyleImageType_Image) {
nsCOMPtr<imgIContainer> imgContainer;
- if (imgRequestProxy* req = aImage.GetImageData()) {
+ if (imgRequestProxy* req = aFrame->GetImageRequest(*aImage.ImageRequest())) {
req->GetImage(getter_AddRefs(imgContainer));
}
if (imgContainer) {
CSSIntSize imageSize;
nsSize imageRatio;
bool hasWidth, hasHeight;
nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
hasWidth, hasHeight);
@@ -3116,25 +3109,26 @@ nsStyleImageLayers::Layer::Initialize(ns
mOrigin = StyleGeometryBox::PaddingBox;
} else {
MOZ_ASSERT(aType == LayerType::Mask, "unsupported layer type.");
mOrigin = StyleGeometryBox::BorderBox;
}
}
bool
-nsStyleImageLayers::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
+nsStyleImageLayers::Layer::RenderingMightDependOnPositioningAreaSizeChange(
+ nsIFrame* aFrame) const
{
// Do we even have an image?
if (mImage.IsEmpty()) {
return false;
}
return mPosition.DependsOnPositioningAreaSize() ||
- mSize.DependsOnPositioningAreaSize(mImage) ||
+ mSize.DependsOnPositioningAreaSize(aFrame, mImage) ||
mRepeat.DependsOnPositioningAreaSize();
}
bool
nsStyleImageLayers::Layer::operator==(const Layer& aOther) const
{
return mAttachment == aOther.mAttachment &&
mClip == aOther.mClip &&
@@ -3685,35 +3679,34 @@ nsStyleDisplay::~nsStyleDisplay()
}
void
nsStyleDisplay::FinishStyle(
nsPresContext* aPresContext, const nsStyleDisplay* aOldStyle)
{
MOZ_ASSERT(NS_IsMainThread());
- if (mShapeOutside.GetType() == StyleShapeSourceType::Image) {
- const UniquePtr<nsStyleImage>& shapeImage = mShapeOutside.GetShapeImage();
- if (shapeImage) {
- // Bug 1434963: The CORS mode should instead be set when the
- // ImageValue is created, in both Gecko and Stylo. That will
- // avoid doing a mutation here.
- if (shapeImage->GetType() == eStyleImageType_Image) {
- shapeImage->ImageRequest()->GetImageValue()->SetCORSMode(
- CORSMode::CORS_ANONYMOUS);
- }
- const nsStyleImage* oldShapeImage =
- (aOldStyle &&
- aOldStyle->mShapeOutside.GetType() == StyleShapeSourceType::Image)
- ? &*aOldStyle->mShapeOutside.GetShapeImage() : nullptr;
- shapeImage->ResolveImage(aPresContext, oldShapeImage);
- }
- }
-
GenerateCombinedTransform();
+
+ nsStyleImage* shapeImage = mShapeOutside.GetShapeImage();
+ if (!shapeImage) {
+ return;
+ }
+
+ // Bug 1434963: The CORS mode should instead be set when the
+ // ImageValue is created, in both Gecko and Stylo. That will
+ // avoid doing a mutation here.
+ if (shapeImage->GetType() == eStyleImageType_Image) {
+ shapeImage->ImageRequest()->GetImageValue()->SetCORSMode(
+ CORSMode::CORS_ANONYMOUS);
+ }
+
+ const nsStyleImage* oldShapeImage =
+ aOldStyle ? aOldStyle->mShapeOutside.GetShapeImage() : nullptr;
+ shapeImage->ResolveImage(aPresContext, oldShapeImage);
}
static inline nsChangeHint
CompareTransformValues(const RefPtr<nsCSSValueSharedList>& aList,
const RefPtr<nsCSSValueSharedList>& aNewList)
{
nsChangeHint result = nsChangeHint(0);
if (!aList != !aNewList || (aList && *aList != *aNewList)) {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -260,21 +260,24 @@ public:
// Can be called from any thread, but Resolve() must be called later
// on the main thread before get() can be used.
nsStyleImageRequest(Mode aModeFlags, mozilla::css::ImageValue* aImageValue);
bool Resolve(nsPresContext*, const nsStyleImageRequest* aOldImageRequest);
bool IsResolved() const { return mResolved; }
+ // NOTE(emilio): Please don't add callers of this outside of nsIFrame, this is
+ // going away soon.
imgRequestProxy* get() {
MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
MOZ_ASSERT(NS_IsMainThread());
return mRequestProxy.get();
}
+
const imgRequestProxy* get() const {
return const_cast<nsStyleImageRequest*>(this)->get();
}
// Returns whether the ImageValue objects in the two nsStyleImageRequests
// return true from URLValueData::DefinitelyEqualURIs.
bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
@@ -372,19 +375,16 @@ struct nsStyleImage
nsStyleImageType GetType() const {
return mType;
}
nsStyleImageRequest* ImageRequest() const {
MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
MOZ_ASSERT(mImage);
return mImage;
}
- imgRequestProxy* GetImageData() const {
- return ImageRequest()->get();
- }
nsStyleGradient* GetGradientData() const {
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
return mGradient;
}
bool IsResolved() const {
return mType != eStyleImageType_Image || ImageRequest()->IsResolved();
}
const nsAtom* GetElementId() const {
@@ -405,43 +405,44 @@ struct nsStyleImage
* Compute the actual crop rect in pixels, using the source image bounds.
* The computation involves converting percentage unit to pixel unit and
* clamping each side value to fit in the source image bounds.
* @param aActualCropRect the computed actual crop rect.
* @param aIsEntireImage true iff |aActualCropRect| is identical to the
* source image bounds.
* @return true iff |aActualCropRect| holds a meaningful value.
*/
- bool ComputeActualCropRect(nsIntRect& aActualCropRect,
- bool* aIsEntireImage = nullptr) const;
+ bool ComputeActualCropRect(nsIFrame* aForFrame,
+ nsIntRect& aActualCropRect,
+ bool* aIsEntireImage = nullptr) const;
/**
* Starts the decoding of a image. Returns true if the current frame of the
* image is complete. The return value is intended to be used instead of
* IsComplete because IsComplete may not be up to date if notifications
* from decoding are pending because they are being sent async.
*/
- bool StartDecoding() const;
+ bool StartDecoding(nsIFrame* aForFrame) const;
/**
* @return true if the item is definitely opaque --- i.e., paints every
* pixel within its bounds opaquely, and the bounds contains at least a pixel.
*/
- bool IsOpaque() const;
+ bool IsOpaque(nsIFrame* aForFrame) const;
/**
* @return true if this image is fully loaded, and its size is calculated;
* always returns true if |mType| is |eStyleImageType_Gradient| or
* |eStyleImageType_Element|.
*/
- bool IsComplete() const;
+ bool IsComplete(nsIFrame* aForFrame) const;
/**
* @return true if this image is loaded without error;
* always returns true if |mType| is |eStyleImageType_Gradient| or
* |eStyleImageType_Element|.
*/
- bool IsLoaded() const;
+ bool IsLoaded(nsIFrame* aForFrame) const;
/**
* @return true if it is 100% confident that this image contains no pixel
* to draw.
*/
bool IsEmpty() const {
// There are some other cases when the image will be empty, for example
// when the crop rect is empty. However, checking the emptiness of crop
// rect is non-trivial since each side value can be specified with
@@ -452,23 +453,16 @@ struct nsStyleImage
return mType == eStyleImageType_Null;
}
bool operator==(const nsStyleImage& aOther) const;
bool operator!=(const nsStyleImage& aOther) const {
return !(*this == aOther);
}
- bool ImageDataEquals(const nsStyleImage& aOther) const
- {
- return GetType() == eStyleImageType_Image &&
- aOther.GetType() == eStyleImageType_Image &&
- GetImageData() == aOther.GetImageData();
- }
-
// These methods are used for the caller to caches the sub images created
// during a border-image paint operation
inline void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const;
inline imgIContainer* GetSubImage(uint8_t aIndex) const;
void PurgeCacheForViewportChange(
const mozilla::Maybe<nsSize>& aSVGViewportSize,
const bool aHasIntrinsicRatio) const;
@@ -583,17 +577,18 @@ struct nsStyleImageLayers {
eLengthPercentage,
eDimensionType_COUNT
};
uint8_t mWidthType, mHeightType;
// True if the effective image size described by this depends on the size of
// the corresponding frame, when aImage (which must not have null type) is
// the background image.
- bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
+ bool DependsOnPositioningAreaSize(nsIFrame* aFrame,
+ const nsStyleImage& aImage) const;
// Initialize nothing
Size() {}
// Initialize to initial values
void SetInitialValues();
bool operator==(const Size& aOther) const;
@@ -682,17 +677,17 @@ struct nsStyleImageLayers {
mImage.ResolveImage(aContext, aOldLayer ? &aOldLayer->mImage : nullptr);
}
// True if the rendering of this layer might change when the size
// of the background positioning area changes. This is true for any
// non-solid-color background whose position or size depends on
// the size of the positioning area. It's also true for SVG images
// whose root <svg> node has a viewBox.
- bool RenderingMightDependOnPositioningAreaSizeChange() const;
+ bool RenderingMightDependOnPositioningAreaSizeChange(nsIFrame*) const;
// Compute the change hint required by changes in just this layer.
nsChangeHint CalcDifference(const Layer& aNewLayer) const;
// An equality operator that compares the images using URL-equality
// rather than pointer-equality.
bool operator==(const Layer& aOther) const;
bool operator!=(const Layer& aOther) const {
@@ -988,16 +983,21 @@ static bool IsVisibleBorderStyle(uint8_t
}
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
{
explicit nsStyleBorder(const nsPresContext* aContext);
nsStyleBorder(const nsStyleBorder& aBorder);
~nsStyleBorder();
+ bool IsBorderImageLoaded(nsIFrame* aForFrame) const
+ {
+ return mBorderImageSource.IsLoaded(aForFrame);
+ }
+
// Resolves and tracks mBorderImageSource. Only called with a Servo-backed
// style system, where those images must be resolved later than the OMT
// nsStyleBorder constructor call.
void FinishStyle(nsPresContext*, const nsStyleBorder*);
const static bool kHasFinishStyle = true;
nsChangeHint CalcDifference(const nsStyleBorder& aNewData) const;
@@ -1053,31 +1053,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
void SetBorderStyle(mozilla::Side aSide, uint8_t aStyle)
{
NS_ASSERTION(aSide <= mozilla::eSideLeft, "bad side");
mBorderStyle[aSide] = aStyle;
mComputedBorder.Side(aSide) =
(HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
}
- inline bool IsBorderImageLoaded() const
- {
- return mBorderImageSource.IsLoaded();
- }
-
nsMargin GetImageOutset() const;
- imgIRequest* GetBorderImageRequest() const
- {
- if (mBorderImageSource.GetType() == eStyleImageType_Image) {
- return mBorderImageSource.GetImageData();
- }
- return nullptr;
- }
-
public:
nsStyleCorners mBorderRadius; // [reset] coord, percent
nsStyleImage mBorderImageSource; // [reset]
nsStyleSides mBorderImageSlice; // [reset] factor, percent
nsStyleSides mBorderImageWidth; // [reset] length, factor, percent, auto
nsStyleSides mBorderImageOutset; // [reset] length, factor
uint8_t mBorderImageFill; // [reset]
@@ -1234,21 +1221,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
nsChangeHint CalcDifference(const nsStyleList& aNewData,
const nsStyleDisplay* aOldDisplay) const;
static void Shutdown() {
sInitialQuotes = nullptr;
sNoneQuotes = nullptr;
}
- imgRequestProxy* GetListStyleImage() const
- {
- return mListStyleImage ? mListStyleImage->get() : nullptr;
- }
-
already_AddRefed<nsIURI> GetListStyleImageURI() const;
const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
void SetQuotesInherit(const nsStyleList* aOther);
void SetQuotesInitial();
void SetQuotesNone();
void SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues);
@@ -2113,26 +2095,27 @@ struct StyleShapeSource final
MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
return mShapeImage
? static_cast<css::URLValue*>(mShapeImage->GetURLValue())
: nullptr;
}
void SetURL(css::URLValue* aValue);
- const UniquePtr<nsStyleImage>& GetShapeImage() const
+ nsStyleImage& ShapeImage() const
{
- MOZ_ASSERT(mType == StyleShapeSourceType::Image, "Wrong shape source type!");
- return mShapeImage;
+ MOZ_ASSERT(mType == StyleShapeSourceType::Image);
+ MOZ_ASSERT(mShapeImage);
+ return *mShapeImage;
}
- // Iff we have "shape-outside:<image>" with an image URI (not a gradient),
- // this method returns the corresponding imgIRequest*. Else, returns
- // null.
- imgIRequest* GetShapeImageData() const;
+ nsStyleImage* GetShapeImage() const
+ {
+ return mType == StyleShapeSourceType::Image ? &ShapeImage() : nullptr;
+ }
void SetShapeImage(UniquePtr<nsStyleImage> aShapeImage);
const UniquePtr<StyleBasicShape>& GetBasicShape() const
{
MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
return mBasicShape;
}
@@ -2669,21 +2652,16 @@ public:
nsStyleImageRequest* ImageRequest() const
{
MOZ_ASSERT(mType == eStyleContentType_Image);
MOZ_ASSERT(mContent.mImage);
return mContent.mImage;
}
- imgRequestProxy* GetImage() const
- {
- return ImageRequest()->get();
- }
-
void SetKeyword(nsStyleContentType aType)
{
MOZ_ASSERT(aType == eStyleContentType_OpenQuote ||
aType == eStyleContentType_CloseQuote ||
aType == eStyleContentType_NoOpenQuote ||
aType == eStyleContentType_NoCloseQuote ||
aType == eStyleContentType_AltContent);
MOZ_ASSERT(mType == eStyleContentType_Uninitialized,
@@ -2843,20 +2821,16 @@ struct nsCursorImage
nsCursorImage& operator=(const nsCursorImage& aOther);
bool operator==(const nsCursorImage& aOther) const;
bool operator!=(const nsCursorImage& aOther) const
{
return !(*this == aOther);
}
-
- imgRequestProxy* GetImage() const {
- return mImage->get();
- }
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
{
explicit nsStyleUserInterface(const nsPresContext* aContext);
nsStyleUserInterface(const nsStyleUserInterface& aOther);
~nsStyleUserInterface();
--- a/layout/svg/SVGObserverUtils.cpp
+++ b/layout/svg/SVGObserverUtils.cpp
@@ -407,26 +407,28 @@ nsSVGMaskProperty::nsSVGMaskProperty(nsI
}
void
nsSVGMaskProperty::ResolveImage(uint32_t aIndex)
{
const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
MOZ_ASSERT(aIndex < svgReset->mMask.mImageCount);
+ // FIXME(emilio): const_cast is evil. Also, stop calling ResolveImage here
+ // manually.
nsStyleImage& image =
const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
if (!image.IsResolved()) {
MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
image.ResolveImage(mFrame->PresContext(), nullptr);
mozilla::css::ImageLoader* imageLoader =
mFrame->PresContext()->Document()->StyleImageLoader();
- if (imgRequestProxy* req = image.GetImageData()) {
+ if (imgRequestProxy* req = mFrame->GetImageRequest(image)) {
imageLoader->AssociateRequestToFrame(req, mFrame, 0);
}
}
}
bool
nsSVGTextPathProperty::TargetIsValid()
{
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -727,17 +727,17 @@ nsSVGIntegrationUtils::IsMaskResourceRea
for (uint32_t i = 0; i < maskFrames.Length(); i++) {
// Refers to a valid SVG mask.
if (maskFrames[i]) {
continue;
}
// Refers to an external resource, which is not ready yet.
- if (!svgReset->mMask.mLayers[i].mImage.IsComplete()) {
+ if (!svgReset->mMask.mLayers[i].mImage.IsComplete(firstFrame)) {
return false;
}
}
// Either all mask resources are ready, or no mask resource is needed.
return true;
}
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -267,17 +267,18 @@ nsImageBoxFrame::UpdateImage()
}
} else {
// Only get the list-style-image if we aren't being drawn
// by a native theme.
uint8_t appearance = StyleDisplay()->mAppearance;
if (!(appearance && nsBox::gTheme &&
nsBox::gTheme->ThemeSupportsWidget(nullptr, this, appearance))) {
// get the list-style-image
- imgRequestProxy *styleRequest = StyleList()->GetListStyleImage();
+ imgRequestProxy* styleRequest =
+ GetImageRequest(StyleList()->mListStyleImage);
if (styleRequest) {
styleRequest->SyncClone(mListener,
mContent->GetComposedDoc(),
getter_AddRefs(mImageRequest));
}
}
}
@@ -662,18 +663,19 @@ nsImageBoxFrame::DidSetComputedStyle(Com
if (disp->mAppearance && nsBox::gTheme &&
nsBox::gTheme->ThemeSupportsWidget(nullptr, this, disp->mAppearance))
return;
// If list-style-image changes, we have a new image.
nsCOMPtr<nsIURI> oldURI, newURI;
if (mImageRequest)
mImageRequest->GetURI(getter_AddRefs(oldURI));
- if (myList->GetListStyleImage())
- myList->GetListStyleImage()->GetURI(getter_AddRefs(newURI));
+ if (auto* request = GetImageRequest(myList->mListStyleImage)) {
+ request->GetURI(getter_AddRefs(newURI));
+ }
bool equal;
if (newURI == oldURI || // handles null==null
(newURI && oldURI &&
NS_SUCCEEDED(newURI->Equals(oldURI, &equal)) && equal))
return;
UpdateImage();
} // DidSetComputedStyle
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2104,17 +2104,17 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn
mView->GetImageSrc(aRowIndex, aCol, imageSrc);
RefPtr<imgRequestProxy> styleRequest;
if (!aUseContext && !imageSrc.IsEmpty()) {
aAllowImageRegions = false;
}
else {
// Obtain the URL from the ComputedStyle.
aAllowImageRegions = true;
- styleRequest = aComputedStyle->StyleList()->GetListStyleImage();
+ styleRequest = GetImageRequest(aComputedStyle->StyleList()->mListStyleImage);
if (!styleRequest)
return NS_OK;
nsCOMPtr<nsIURI> uri;
styleRequest->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
nsresult rv = uri->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
CopyUTF8toUTF16(spec, imageSrc);