Bug 1288302 - Part 5: Make nsStyleImage use nsStyleImageRequest. r=bholley
This makes background-image, mask-image and border-image settable
from Servo.
Since imgRequestProxy resolution in nsStyleImages can now happen later than
at computed value setting time, and that resolution can fail,
nsStyleImage::GetImageData() might now return null. So all of the users of
nsStyleImage now null check its result.
MozReview-Commit-ID: FMRUrC3SfOs
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -662,36 +662,27 @@ nsCSSRendering::PaintBorder(nsPresContex
// same amount of time whether or not it's true.
if (!styleIfVisited) {
return PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, *styleBorder,
aStyleContext, aFlags, aSkipSides);
}
nsStyleBorder newStyleBorder(*styleBorder);
- // We could do something fancy to avoid the TrackImage/UntrackImage
- // work, but it doesn't seem worth it. (We need to call TrackImage
- // since we're not going through nsRuleNode::ComputeBorderData.)
- newStyleBorder.TrackImage(aPresContext->Document()->ImageTracker());
NS_FOR_CSS_SIDES(side) {
nscolor color = aStyleContext->GetVisitedDependentColor(
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
}
DrawResult result =
PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, newStyleBorder,
aStyleContext, aFlags, aSkipSides);
- // We could do something fancy to avoid the TrackImage/UntrackImage
- // work, but it doesn't seem worth it. (We need to call UntrackImage
- // since we're not going through nsStyleBorder::Destroy.)
- newStyleBorder.UntrackImage(aPresContext->Document()->ImageTracker());
-
return result;
}
DrawResult
nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
@@ -5027,26 +5018,31 @@ ShouldTreatAsCompleteDueToSyncDecode(con
if (!(aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES)) {
return false;
}
if (aImage->GetType() != eStyleImageType_Image) {
return false;
}
+ imgRequestProxy* req = aImage->GetImageData();
+ if (!req) {
+ return false;
+ }
+
uint32_t status = 0;
- if (NS_FAILED(aImage->GetImageData()->GetImageStatus(&status))) {
+ if (NS_FAILED(req->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;
- aImage->GetImageData()->GetImage(getter_AddRefs(image));
+ req->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;
}
@@ -5073,18 +5069,19 @@ nsImageRenderer::PrepareImage()
if (!mImage->IsComplete() &&
!ShouldTreatAsCompleteDueToSyncDecode(mImage, mFlags)) {
mPrepareResult = DrawResult::NOT_READY;
return false;
}
}
switch (mType) {
- case eStyleImageType_Image:
- {
+ case eStyleImageType_Image: {
+ MOZ_ASSERT(mImage->GetImageData(),
+ "must have image data, since we checked IsEmpty above");
nsCOMPtr<imgIContainer> srcImage;
DebugOnly<nsresult> rv =
mImage->GetImageData()->GetImage(getter_AddRefs(srcImage));
MOZ_ASSERT(NS_SUCCEEDED(rv) && srcImage,
"If GetImage() is failing, mImage->IsComplete() "
"should have returned false");
if (!mImage->GetCropRect()) {
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2859,17 +2859,19 @@ nsDisplayBackgroundImage::ShouldCreateOw
}
if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
const nsStyleImage* image = &layer.mImage;
if (image->GetType() == eStyleImageType_Image) {
imgIRequest* imgreq = image->GetImageData();
nsCOMPtr<imgIContainer> image;
- if (NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) && image) {
+ if (imgreq &&
+ NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) &&
+ image) {
bool animated = false;
if (NS_SUCCEEDED(image->GetAnimated(&animated)) && animated) {
return WHENEVER_POSSIBLE;
}
}
}
}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -787,33 +787,36 @@ AddAndRemoveImageAssociations(nsFrame* a
if (i >= aNewLayers->mImageCount ||
!aOldLayers->mLayers[i].mImage.ImageDataEquals(
aNewLayers->mLayers[i].mImage)) {
const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage;
if (oldImage.GetType() != eStyleImageType_Image) {
continue;
}
- imageLoader->DisassociateRequestFromFrame(oldImage.GetImageData(),
- aFrame);
+ if (imgRequestProxy* req = oldImage.GetImageData()) {
+ imageLoader->DisassociateRequestFromFrame(req, aFrame);
+ }
}
}
}
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) {
// If there is an image in newBG that's not in oldBG, add it.
if (!aOldLayers || i >= aOldLayers->mImageCount ||
!aNewLayers->mLayers[i].mImage.ImageDataEquals(
aOldLayers->mLayers[i].mImage)) {
const nsStyleImage& newImage = aNewLayers->mLayers[i].mImage;
if (newImage.GetType() != eStyleImageType_Image) {
continue;
}
- imageLoader->AssociateRequestToFrame(newImage.GetImageData(), aFrame);
+ if (imgRequestProxy* req = newImage.GetImageData()) {
+ imageLoader->AssociateRequestToFrame(req, aFrame);
+ }
}
}
}
// Subclass hook for style post processing
/* virtual */ void
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
{
@@ -4295,17 +4298,21 @@ nsIFrame::ContentOffsets nsFrame::CalcCo
void
nsIFrame::AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext)
{
if (aImage.GetType() != eStyleImageType_Image) {
return;
}
- imgIRequest *req = aImage.GetImageData();
+ imgRequestProxy* req = aImage.GetImageData();
+ if (!req) {
+ return;
+ }
+
mozilla::css::ImageLoader* loader =
aPresContext->Document()->StyleImageLoader();
// If this fails there's not much we can do ...
loader->AssociateRequestToFrame(req, this);
}
nsresult
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2077,17 +2077,25 @@ nsComputedDOMStyle::GetImageRectString(n
void
nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
nsROCSSPrimitiveValue* aValue)
{
switch (aStyleImage.GetType()) {
case eStyleImageType_Image:
{
- imgIRequest *req = aStyleImage.GetImageData();
+ imgIRequest* req = aStyleImage.GetImageData();
+ if (!req) {
+ // XXXheycam If we had some problem resolving the imgRequestProxy,
+ // maybe we should just use the URL stored in the nsStyleImage's
+ // mImageValue?
+ aValue->SetIdent(eCSSKeyword_none);
+ break;
+ }
+
nsCOMPtr<nsIURI> uri;
req->GetURI(getter_AddRefs(uri));
const UniquePtr<nsStyleSides>& cropRect = aStyleImage.GetCropRect();
if (cropRect) {
nsAutoString imageRectString;
GetImageRectString(uri, *cropRect, imageRectString);
aValue->SetString(imageRectString);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -129,16 +129,36 @@ SetImageRequest(function<void(imgRequest
const nsCSSValue& aValue)
{
RefPtr<imgRequestProxy> req =
aValue.GetPossiblyStaticImageValue(aPresContext->Document(),
aPresContext);
aCallback(req);
}
+static void
+SetStyleImageRequest(function<void(nsStyleImageRequest*)> aCallback,
+ nsPresContext* aPresContext,
+ const nsCSSValue& aValue,
+ nsStyleImageRequest::Mode aModeFlags =
+ nsStyleImageRequest::Mode::Track |
+ nsStyleImageRequest::Mode::Lock)
+{
+ SetImageRequest([&](imgRequestProxy* aProxy) {
+ RefPtr<nsStyleImageRequest> request;
+ if (aProxy) {
+ css::ImageValue* imageValue = aValue.GetImageStructValue();
+ ImageTracker* imageTracker = aPresContext->Document()->ImageTracker();
+ request =
+ new nsStyleImageRequest(aModeFlags, aProxy, imageValue, imageTracker);
+ }
+ aCallback(request);
+ }, aPresContext, aValue);
+}
+
template<typename ReferenceBox>
static void
SetStyleShapeSourceToCSSValue(StyleShapeSource<ReferenceBox>* aShapeSource,
const nsCSSValue* aValue,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions);
@@ -1259,18 +1279,18 @@ static void SetStyleImageToImageRect(nsS
aValue.EqualsFunction(eCSSKeyword__moz_image_rect),
"the value is not valid -moz-image-rect()");
nsCSSValue::Array* arr = aValue.GetArrayValue();
MOZ_ASSERT(arr && arr->Count() == 6, "invalid number of arguments");
// <uri>
if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
- SetImageRequest([&](imgRequestProxy* req) {
- aResult.SetImageData(req);
+ SetStyleImageRequest([&](nsStyleImageRequest* req) {
+ aResult.SetImageRequest(do_AddRef(req));
}, aStyleContext->PresContext(), arr->Item(1));
} else {
NS_WARNING("nsCSSValue::Image::Image() failed?");
}
// <top>, <right>, <bottom>, <left>
nsStyleSides cropRect;
NS_FOR_CSS_SIDES(side) {
@@ -1295,18 +1315,18 @@ static void SetStyleImage(nsStyleContext
if (aValue.GetUnit() == eCSSUnit_Null) {
return;
}
aResult.SetNull();
switch (aValue.GetUnit()) {
case eCSSUnit_Image:
- SetImageRequest([&](imgRequestProxy* req) {
- aResult.SetImageData(req);
+ SetStyleImageRequest([&](nsStyleImageRequest* req) {
+ aResult.SetImageRequest(do_AddRef(req));
}, aStyleContext->PresContext(), aValue);
break;
case eCSSUnit_Function:
if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
SetStyleImageToImageRect(aStyleContext, aValue, aResult);
} else {
NS_NOTREACHED("-moz-image-rect() is the only expected function");
}
@@ -7320,19 +7340,16 @@ nsRuleNode::ComputeBackgroundData(void*
initialSize, parentBG->mImage.mSizeCount,
bg->mImage.mSizeCount, maxItemCount, rebuild,
conditions);
if (rebuild) {
FillAllBackgroundLists(bg->mImage, maxItemCount);
}
- // Now that the dust has settled, register the images with the document
- bg->mImage.TrackImages(aContext->PresContext()->Document()->ImageTracker());
-
COMPUTE_END_RESET(Background, bg)
}
const void*
nsRuleNode::ComputeMarginData(void* aStartStruct,
const nsRuleData* aRuleData,
nsStyleContext* aContext,
nsRuleNode* aHighestNode,
@@ -7709,18 +7726,16 @@ nsRuleNode::ComputeBorderData(void* aSta
SetValue(borderImageRepeat.mYValue,
border->mBorderImageRepeatV,
conditions,
SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
parentBorder->mBorderImageRepeatV,
NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH);
- border->TrackImage(aContext->PresContext()->Document()->ImageTracker());
-
COMPUTE_END_RESET(Border, border)
}
const void*
nsRuleNode::ComputePaddingData(void* aStartStruct,
const nsRuleData* aRuleData,
nsStyleContext* aContext,
nsRuleNode* aHighestNode,
@@ -10047,18 +10062,16 @@ nsRuleNode::ComputeSVGResetData(void* aS
svgReset->mMask.mLayers[0].mSourceURI.SetNull();
} else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
conditions.SetUncacheable();
svgReset->mMask.mLayers[0].mSourceURI =
parentSVGReset->mMask.mLayers[0].mSourceURI;
}
#endif
- svgReset->mMask.TrackImages(aContext->PresContext()->Document()->ImageTracker());
-
COMPUTE_END_RESET(SVGReset, svgReset)
}
const void*
nsRuleNode::ComputeVariablesData(void* aStartStruct,
const nsRuleData* aRuleData,
nsStyleContext* aContext,
nsRuleNode* aHighestNode,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -446,16 +446,25 @@ nsStyleBorder::~nsStyleBorder()
if (mBorderColors) {
for (int32_t i = 0; i < 4; i++) {
delete mBorderColors[i];
}
delete [] mBorderColors;
}
}
+void
+nsStyleBorder::FinishStyle(nsPresContext* aPresContext)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
+
+ mBorderImageSource.ResolveImage(aPresContext);
+}
+
nsMargin
nsStyleBorder::GetImageOutset() const
{
// We don't check whether there is a border-image (which is OK since
// the initial values yields 0 outset) so that we don't have to
// reflow to update overflow areas when an image loads.
nsMargin outset;
NS_FOR_CSS_SIDES(s) {
@@ -476,18 +485,16 @@ nsStyleBorder::GetImageOutset() const
outset.Side(s) = value;
}
return outset;
}
void
nsStyleBorder::Destroy(nsPresContext* aContext)
{
- UntrackImage(aContext->Document()->ImageTracker());
-
this->~nsStyleBorder();
aContext->PresShell()->
FreeByObjectID(eArenaObjectID_nsStyleBorder, this);
}
nsChangeHint
nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
{
@@ -1181,23 +1188,30 @@ nsStyleSVGReset::nsStyleSVGReset(const n
, mMaskType(aSource.mMaskType)
{
MOZ_COUNT_CTOR(nsStyleSVGReset);
}
void
nsStyleSVGReset::Destroy(nsPresContext* aContext)
{
- mMask.UntrackImages(aContext->Document()->ImageTracker());
-
this->~nsStyleSVGReset();
aContext->PresShell()->
FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
}
+void
+nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
+
+ mMask.ResolveImages(aPresContext);
+}
+
nsChangeHint
nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
{
nsChangeHint hint = nsChangeHint(0);
if (mClipPath != aNewData.mClipPath) {
hint |= nsChangeHint_UpdateEffects |
nsChangeHint_RepaintFrame;
@@ -2093,37 +2107,31 @@ CachedBorderImageData::GetSubImage(uint8
// --------------------
// nsStyleImage
//
nsStyleImage::nsStyleImage()
: mType(eStyleImageType_Null)
, mCropRect(nullptr)
-#ifdef DEBUG
- , mImageTracked(false)
-#endif
{
MOZ_COUNT_CTOR(nsStyleImage);
}
nsStyleImage::~nsStyleImage()
{
MOZ_COUNT_DTOR(nsStyleImage);
if (mType != eStyleImageType_Null) {
SetNull();
}
}
nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
: mType(eStyleImageType_Null)
, mCropRect(nullptr)
-#ifdef DEBUG
- , mImageTracked(false)
-#endif
{
// We need our own copy constructor because we don't want
// to copy the reference count
MOZ_COUNT_CTOR(nsStyleImage);
DoCopy(aOther);
}
nsStyleImage&
@@ -2137,102 +2145,64 @@ nsStyleImage::operator=(const nsStyleIma
}
void
nsStyleImage::DoCopy(const nsStyleImage& aOther)
{
SetNull();
if (aOther.mType == eStyleImageType_Image) {
- SetImageData(aOther.mImage);
+ SetImageRequest(do_AddRef(aOther.mImage));
} else if (aOther.mType == eStyleImageType_Gradient) {
SetGradientData(aOther.mGradient);
} else if (aOther.mType == eStyleImageType_Element) {
SetElementId(aOther.mElementId);
}
UniquePtr<nsStyleSides> cropRectCopy;
if (aOther.mCropRect) {
cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
}
SetCropRect(Move(cropRectCopy));
}
void
nsStyleImage::SetNull()
{
- MOZ_ASSERT(!mImageTracked,
- "Calling SetNull() with image tracked!");
-
if (mType == eStyleImageType_Gradient) {
mGradient->Release();
} else if (mType == eStyleImageType_Image) {
NS_RELEASE(mImage);
} else if (mType == eStyleImageType_Element) {
free(mElementId);
}
mType = eStyleImageType_Null;
mCropRect = nullptr;
}
void
-nsStyleImage::SetImageData(imgRequestProxy* aImage)
+nsStyleImage::SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage)
{
- MOZ_ASSERT(!mImageTracked,
- "Setting a new image without untracking the old one!");
-
- NS_IF_ADDREF(aImage);
+ RefPtr<nsStyleImageRequest> image = aImage;
if (mType != eStyleImageType_Null) {
SetNull();
}
- if (aImage) {
- mImage = aImage;
+ if (image) {
+ mImage = image.forget().take();
mType = eStyleImageType_Image;
}
if (mCachedBIData) {
mCachedBIData->PurgeCachedImages();
}
}
void
-nsStyleImage::TrackImage(ImageTracker* aImageTracker)
-{
- // Sanity
- MOZ_ASSERT(!mImageTracked, "Already tracking image!");
- MOZ_ASSERT(mType == eStyleImageType_Image,
- "Can't track image when there isn't one!");
-
- aImageTracker->Add(mImage);
-
- // Mark state
-#ifdef DEBUG
- mImageTracked = true;
-#endif
-}
-
-void
-nsStyleImage::UntrackImage(ImageTracker* aImageTracker)
-{
- // Sanity
- MOZ_ASSERT(mImageTracked, "Image not tracked!");
- MOZ_ASSERT(mType == eStyleImageType_Image,
- "Can't untrack image when there isn't one!");
-
- aImageTracker->Remove(mImage);
-
- // Mark state
-#ifdef DEBUG
- mImageTracked = false;
-#endif
-}
-
-void
nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
{
if (aGradient) {
aGradient->AddRef();
}
if (mType != eStyleImageType_Null) {
SetNull();
@@ -2286,18 +2256,23 @@ ConvertToPixelCoord(const nsStyleCoord&
bool
nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
bool* aIsEntireImage) const
{
if (mType != eStyleImageType_Image) {
return false;
}
+ imgRequestProxy* req = GetImageData();
+ if (!req) {
+ return false;
+ }
+
nsCOMPtr<imgIContainer> imageContainer;
- mImage->GetImage(getter_AddRefs(imageContainer));
+ req->GetImage(getter_AddRefs(imageContainer));
if (!imageContainer) {
return false;
}
nsIntSize imageSize;
imageContainer->GetWidth(&imageSize.width);
imageContainer->GetHeight(&imageSize.height);
if (imageSize.width <= 0 || imageSize.height <= 0) {
@@ -2319,17 +2294,21 @@ nsStyleImage::ComputeActualCropRect(nsIn
}
return true;
}
nsresult
nsStyleImage::StartDecoding() const
{
if (mType == eStyleImageType_Image) {
- return mImage->StartDecoding();
+ imgRequestProxy* req = GetImageData();
+ if (!req) {
+ return NS_ERROR_FAILURE;
+ }
+ return req->StartDecoding();
}
return NS_OK;
}
bool
nsStyleImage::IsOpaque() const
{
if (!IsComplete()) {
@@ -2340,19 +2319,20 @@ nsStyleImage::IsOpaque() const
return mGradient->IsOpaque();
}
if (mType == eStyleImageType_Element) {
return false;
}
MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
+ MOZ_ASSERT(GetImageData(), "should've returned earlier above");
nsCOMPtr<imgIContainer> imageContainer;
- mImage->GetImage(getter_AddRefs(imageContainer));
+ GetImageData()->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;
}
@@ -2371,20 +2351,23 @@ bool
nsStyleImage::IsComplete() const
{
switch (mType) {
case eStyleImageType_Null:
return false;
case eStyleImageType_Gradient:
case eStyleImageType_Element:
return true;
- case eStyleImageType_Image:
- {
+ case eStyleImageType_Image: {
+ imgRequestProxy* req = GetImageData();
+ if (!req) {
+ return false;
+ }
uint32_t status = imgIRequest::STATUS_ERROR;
- return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
+ return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
(status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
(status & imgIRequest::STATUS_FRAME_COMPLETE);
}
default:
NS_NOTREACHED("unexpected image type");
return false;
}
}
@@ -2393,20 +2376,23 @@ bool
nsStyleImage::IsLoaded() const
{
switch (mType) {
case eStyleImageType_Null:
return false;
case eStyleImageType_Gradient:
case eStyleImageType_Element:
return true;
- case eStyleImageType_Image:
- {
+ case eStyleImageType_Image: {
+ imgRequestProxy* req = GetImageData();
+ if (!req) {
+ return false;
+ }
uint32_t status = imgIRequest::STATUS_ERROR;
- return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
+ return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
!(status & imgIRequest::STATUS_ERROR) &&
(status & imgIRequest::STATUS_LOAD_COMPLETE);
}
default:
NS_NOTREACHED("unexpected image type");
return false;
}
}
@@ -2425,17 +2411,17 @@ nsStyleImage::operator==(const nsStyleIm
return false;
}
if (!EqualRects(mCropRect, aOther.mCropRect)) {
return false;
}
if (mType == eStyleImageType_Image) {
- return EqualImages(mImage, aOther.mImage);
+ return DefinitelyEqualImages(mImage, aOther.mImage);
}
if (mType == eStyleImageType_Gradient) {
return *mGradient == *aOther.mGradient;
}
if (mType == eStyleImageType_Element) {
return NS_strcmp(mElementId, aOther.mElementId) == 0;
@@ -2706,17 +2692,19 @@ 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;
- aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer));
+ if (imgRequestProxy* req = aImage.GetImageData()) {
+ req->GetImage(getter_AddRefs(imgContainer));
+ }
if (imgContainer) {
CSSIntSize imageSize;
nsSize imageRatio;
bool hasWidth, hasHeight;
nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
hasWidth, hasHeight);
// If the image has a fixed width and height, rendering never depends on
@@ -2940,24 +2928,30 @@ nsStyleBackground::nsStyleBackground(con
nsStyleBackground::~nsStyleBackground()
{
MOZ_COUNT_DTOR(nsStyleBackground);
}
void
nsStyleBackground::Destroy(nsPresContext* aContext)
{
- // Untrack all the images stored in our layers
- mImage.UntrackImages(aContext->Document()->ImageTracker());
-
this->~nsStyleBackground();
aContext->PresShell()->
FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
}
+void
+nsStyleBackground::FinishStyle(nsPresContext* aPresContext)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
+
+ mImage.ResolveImages(aPresContext);
+}
+
nsChangeHint
nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
{
nsChangeHint hint = nsChangeHint(0);
if (mBackgroundColor != aNewData.mBackgroundColor) {
hint |= nsChangeHint_RepaintFrame;
}
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -417,32 +417,38 @@ private:
struct nsStyleImage
{
nsStyleImage();
~nsStyleImage();
nsStyleImage(const nsStyleImage& aOther);
nsStyleImage& operator=(const nsStyleImage& aOther);
void SetNull();
- void SetImageData(imgRequestProxy* aImage);
- void TrackImage(mozilla::dom::ImageTracker* aImageTracker);
- void UntrackImage(mozilla::dom::ImageTracker* aImageTracker);
+ void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
void SetGradientData(nsStyleGradient* aGradient);
void SetElementId(const char16_t* aElementId);
void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
+ void ResolveImage(nsPresContext* aContext) {
+ MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
+ if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
+ mImage->Resolve(aContext);
+ }
+ }
+
nsStyleImageType GetType() const {
return mType;
}
+ nsStyleImageRequest* GetImageRequest() const {
+ MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
+ MOZ_ASSERT(mImage);
+ return mImage;
+ }
imgRequestProxy* GetImageData() const {
- MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
- MOZ_ASSERT(mImage);
- MOZ_ASSERT(mImageTracked,
- "Should be tracking any image we're going to use!");
- return mImage;
+ return GetImageRequest()->get();
}
nsStyleGradient* GetGradientData() const {
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
return mGradient;
}
const char16_t* GetElementId() const {
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
return mElementId;
@@ -526,26 +532,23 @@ private:
void EnsureCachedBIData() const;
// This variable keeps some cache data for border image and is lazily
// allocated since it is only used in border image case.
mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
nsStyleImageType mType;
union {
- imgRequestProxy* mImage;
+ nsStyleImageRequest* mImage;
nsStyleGradient* mGradient;
char16_t* mElementId;
};
// This is _currently_ used only in conjunction with eStyleImageType_Image.
mozilla::UniquePtr<nsStyleSides> mCropRect;
-#ifdef DEBUG
- bool mImageTracked;
-#endif
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
{
explicit nsStyleColor(StyleStructContext aContext);
nsStyleColor(const nsStyleColor& aOther);
~nsStyleColor() {
MOZ_COUNT_DTOR(nsStyleColor);
@@ -812,26 +815,19 @@ struct nsStyleImageLayers {
// This constructor does not initialize mRepeat or mOrigin and Initialize()
// must be called to do that.
Layer();
~Layer();
// Initialize mRepeat and mOrigin by specified layer type
void Initialize(LayerType aType);
- // Register/unregister images with the document. We do this only
- // after the dust has settled in ComputeBackgroundData.
- void TrackImages(mozilla::dom::ImageTracker* aImageTracker) {
+ void ResolveImage(nsPresContext* aContext) {
if (mImage.GetType() == eStyleImageType_Image) {
- mImage.TrackImage(aImageTracker);
- }
- }
- void UntrackImages(mozilla::dom::ImageTracker* aImageTracker) {
- if (mImage.GetType() == eStyleImageType_Image) {
- mImage.UntrackImage(aImageTracker);
+ mImage.ResolveImage(aContext);
}
}
// 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.
@@ -871,25 +867,21 @@ struct nsStyleImageLayers {
// background-clip applies to the background-color) may not be last
// layer. In layers below the bottom layer, properties will be
// uninitialized unless their count, above, indicates that they are
// present.
nsStyleAutoArray<Layer> mLayers;
const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
- void TrackImages(mozilla::dom::ImageTracker* aImageTracker) {
+ void ResolveImages(nsPresContext* aContext) {
for (uint32_t i = 0; i < mImageCount; ++i) {
- mLayers[i].TrackImages(aImageTracker);
+ mLayers[i].ResolveImage(aContext);
}
}
- void UntrackImages(mozilla::dom::ImageTracker* aImageTracker) {
- for (uint32_t i = 0; i < mImageCount; ++i)
- mLayers[i].UntrackImages(aImageTracker);
- }
nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
nsStyleImageLayers::LayerType aType) const;
bool HasLayerWithImage() const;
static const nsCSSPropertyID kBackgroundLayerTable[];
static const nsCSSPropertyID kMaskLayerTable[];
@@ -901,17 +893,21 @@ struct nsStyleImageLayers {
NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
explicit nsStyleBackground(StyleStructContext aContext);
nsStyleBackground(const nsStyleBackground& aOther);
~nsStyleBackground();
- void FinishStyle(nsPresContext* aPresContext) {}
+
+ // Resolves and tracks the images in mImage. Only called with a Servo-backed
+ // style system, where those images must be resolved later than the OMT
+ // nsStyleBackground constructor call.
+ void FinishStyle(nsPresContext* aPresContext);
void* operator new(size_t sz, nsStyleBackground* aSelf) { return aSelf; }
void* operator new(size_t sz, nsPresContext* aContext) {
return aContext->PresShell()->
AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
}
void Destroy(nsPresContext* aContext);
@@ -1210,17 +1206,21 @@ static bool IsVisibleBorderStyle(uint8_t
aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
}
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
{
explicit nsStyleBorder(StyleStructContext aContext);
nsStyleBorder(const nsStyleBorder& aBorder);
~nsStyleBorder();
- void FinishStyle(nsPresContext* aPresContext) {}
+
+ // 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* aPresContext);
void* operator new(size_t sz, nsStyleBorder* aSelf) { return aSelf; }
void* operator new(size_t sz, nsPresContext* aContext) {
return aContext->PresShell()->
AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
}
void Destroy(nsPresContext* aContext);
@@ -1314,26 +1314,20 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
(HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
}
inline bool IsBorderImageLoaded() const
{
return mBorderImageSource.IsLoaded();
}
- void TrackImage(mozilla::dom::ImageTracker* aImageTracker)
+ void ResolveImage(nsPresContext* aContext)
{
if (mBorderImageSource.GetType() == eStyleImageType_Image) {
- mBorderImageSource.TrackImage(aImageTracker);
- }
- }
- void UntrackImage(mozilla::dom::ImageTracker* aImageTracker)
- {
- if (mBorderImageSource.GetType() == eStyleImageType_Image) {
- mBorderImageSource.UntrackImage(aImageTracker);
+ mBorderImageSource.ResolveImage(aContext);
}
}
nsMargin GetImageOutset() const;
void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
{
if (!mBorderColors) {
@@ -3766,17 +3760,21 @@ struct nsTArray_CopyChooser<nsStyleFilte
typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset
{
explicit nsStyleSVGReset(StyleStructContext aContext);
nsStyleSVGReset(const nsStyleSVGReset& aSource);
~nsStyleSVGReset();
- void FinishStyle(nsPresContext* aPresContext) {}
+
+ // Resolves and tracks the images in mMask. Only called with a Servo-backed
+ // style system, where those images must be resolved later than the OMT
+ // nsStyleSVGReset constructor call.
+ void FinishStyle(nsPresContext* aPresContext);
void* operator new(size_t sz, nsStyleSVGReset* aSelf) { return aSelf; }
void* operator new(size_t sz, nsPresContext* aContext) {
return aContext->PresShell()->
AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
}
void Destroy(nsPresContext* aContext);