зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset c9f4dd3ed78b (bug 1606628) for causing failures in ImageLoader.cpp
CLOSED TREE
This commit is contained in:
Родитель
77c6b3e983
Коммит
823e8c21f1
|
@ -56,6 +56,7 @@ class ImageTracker {
|
||||||
void SetAnimatingState(bool aAnimating);
|
void SetAnimatingState(bool aAnimating);
|
||||||
|
|
||||||
void RequestDiscardAll();
|
void RequestDiscardAll();
|
||||||
|
|
||||||
void MediaFeatureValuesChangedAllDocuments(const MediaFeatureChange&);
|
void MediaFeatureValuesChangedAllDocuments(const MediaFeatureChange&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1525,6 +1525,7 @@ void nsPresContext::MediaFeatureValuesChangedAllDocuments(
|
||||||
|
|
||||||
// Propagate the media feature value change down to any SVG images the
|
// Propagate the media feature value change down to any SVG images the
|
||||||
// document is using.
|
// document is using.
|
||||||
|
mDocument->StyleImageLoader()->MediaFeatureValuesChangedAllDocuments(aChange);
|
||||||
mDocument->ImageTracker()->MediaFeatureValuesChangedAllDocuments(aChange);
|
mDocument->ImageTracker()->MediaFeatureValuesChangedAllDocuments(aChange);
|
||||||
|
|
||||||
// And then into any subdocuments.
|
// And then into any subdocuments.
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "mozilla/ComputedStyle.h"
|
#include "mozilla/ComputedStyle.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/dom/ElementInlines.h"
|
#include "mozilla/dom/ElementInlines.h"
|
||||||
#include "mozilla/dom/ImageTracker.h"
|
|
||||||
#include "mozilla/dom/Selection.h"
|
#include "mozilla/dom/Selection.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
|
@ -1163,7 +1162,7 @@ void nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||||
MaybeScheduleReflowSVGNonDisplayText(this);
|
MaybeScheduleReflowSVGNonDisplayText(this);
|
||||||
|
|
||||||
Document* doc = PresContext()->Document();
|
Document* doc = PresContext()->Document();
|
||||||
ImageLoader* loader = doc->StyleImageLoader();
|
ImageLoader* imageLoader = doc->StyleImageLoader();
|
||||||
// Continuing text frame doesn't initialize its continuation pointer before
|
// Continuing text frame doesn't initialize its continuation pointer before
|
||||||
// reaching here for the first time, so we have to exclude text frames. This
|
// reaching here for the first time, so we have to exclude text frames. This
|
||||||
// doesn't affect correctness because text can't match selectors.
|
// doesn't affect correctness because text can't match selectors.
|
||||||
|
@ -1183,12 +1182,12 @@ void nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||||
aOldComputedStyle ? &aOldComputedStyle->StyleBackground()->mImage
|
aOldComputedStyle ? &aOldComputedStyle->StyleBackground()->mImage
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const nsStyleImageLayers* newLayers = &StyleBackground()->mImage;
|
const nsStyleImageLayers* newLayers = &StyleBackground()->mImage;
|
||||||
AddAndRemoveImageAssociations(*loader, this, oldLayers, newLayers);
|
AddAndRemoveImageAssociations(*imageLoader, this, oldLayers, newLayers);
|
||||||
|
|
||||||
oldLayers =
|
oldLayers =
|
||||||
aOldComputedStyle ? &aOldComputedStyle->StyleSVGReset()->mMask : nullptr;
|
aOldComputedStyle ? &aOldComputedStyle->StyleSVGReset()->mMask : nullptr;
|
||||||
newLayers = &StyleSVGReset()->mMask;
|
newLayers = &StyleSVGReset()->mMask;
|
||||||
AddAndRemoveImageAssociations(*loader, this, oldLayers, newLayers);
|
AddAndRemoveImageAssociations(*imageLoader, this, oldLayers, newLayers);
|
||||||
|
|
||||||
const nsStyleDisplay* disp = StyleDisplay();
|
const nsStyleDisplay* disp = StyleDisplay();
|
||||||
bool handleStickyChange = false;
|
bool handleStickyChange = false;
|
||||||
|
@ -1315,10 +1314,10 @@ void nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||||
if (oldBorderImage != newBorderImage) {
|
if (oldBorderImage != newBorderImage) {
|
||||||
// stop and restart the image loading/notification
|
// stop and restart the image loading/notification
|
||||||
if (oldBorderImage && HasImageRequest()) {
|
if (oldBorderImage && HasImageRequest()) {
|
||||||
loader->DisassociateRequestFromFrame(oldBorderImage, this);
|
imageLoader->DisassociateRequestFromFrame(oldBorderImage, this);
|
||||||
}
|
}
|
||||||
if (newBorderImage) {
|
if (newBorderImage) {
|
||||||
loader->AssociateRequestToFrame(newBorderImage, this, 0);
|
imageLoader->AssociateRequestToFrame(newBorderImage, this, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,11 +1330,11 @@ void nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||||
|
|
||||||
if (oldShapeImage != newShapeImage) {
|
if (oldShapeImage != newShapeImage) {
|
||||||
if (oldShapeImage && HasImageRequest()) {
|
if (oldShapeImage && HasImageRequest()) {
|
||||||
loader->DisassociateRequestFromFrame(oldShapeImage, this);
|
imageLoader->DisassociateRequestFromFrame(oldShapeImage, this);
|
||||||
}
|
}
|
||||||
if (newShapeImage) {
|
if (newShapeImage) {
|
||||||
loader->AssociateRequestToFrame(newShapeImage, this,
|
imageLoader->AssociateRequestToFrame(
|
||||||
ImageLoader::REQUEST_REQUIRES_REFLOW);
|
newShapeImage, this, ImageLoader::REQUEST_REQUIRES_REFLOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -272,6 +272,7 @@ void nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||||
imageLoader->FrameDestroyed(this);
|
imageLoader->FrameDestroyed(this);
|
||||||
imageLoader->RemoveNativeObserver(mListener);
|
imageLoader->RemoveNativeObserver(mListener);
|
||||||
} else if (mContentURLRequest) {
|
} else if (mContentURLRequest) {
|
||||||
|
PresContext()->Document()->ImageTracker()->Remove(mContentURLRequest);
|
||||||
nsLayoutUtils::DeregisterImageRequest(PresContext(), mContentURLRequest,
|
nsLayoutUtils::DeregisterImageRequest(PresContext(), mContentURLRequest,
|
||||||
&mContentURLRequestRegistered);
|
&mContentURLRequestRegistered);
|
||||||
mContentURLRequest->Cancel(NS_BINDING_ABORTED);
|
mContentURLRequest->Cancel(NS_BINDING_ABORTED);
|
||||||
|
@ -367,7 +368,7 @@ void nsImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||||
auto& url = const_cast<StyleComputedUrl&>(
|
auto& url = const_cast<StyleComputedUrl&>(
|
||||||
styleContent->ContentAt(contentIndex).AsUrl());
|
styleContent->ContentAt(contentIndex).AsUrl());
|
||||||
Document* doc = PresContext()->Document();
|
Document* doc = PresContext()->Document();
|
||||||
if (imgRequestProxy* proxy = url.GetImage()) {
|
if (RefPtr<imgRequestProxy> proxy = url.LoadImage(*doc)) {
|
||||||
proxy->Clone(mListener, doc, getter_AddRefs(mContentURLRequest));
|
proxy->Clone(mListener, doc, getter_AddRefs(mContentURLRequest));
|
||||||
SetupForContentURLRequest();
|
SetupForContentURLRequest();
|
||||||
}
|
}
|
||||||
|
@ -393,6 +394,9 @@ void nsImageFrame::SetupForContentURLRequest() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We're not using nsStyleImageRequest, so manually track the image.
|
||||||
|
PresContext()->Document()->ImageTracker()->Add(mContentURLRequest);
|
||||||
|
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
nsresult rv = mContentURLRequest->GetImageStatus(&status);
|
nsresult rv = mContentURLRequest->GetImageStatus(&status);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
|
|
@ -1115,10 +1115,19 @@ void Gecko_SetGradientImageValue(nsStyleImage* aImage,
|
||||||
aImage->SetGradientData(UniquePtr<StyleGradient>(aGradient));
|
aImage->SetGradientData(UniquePtr<StyleGradient>(aGradient));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static already_AddRefed<nsStyleImageRequest> CreateStyleImageRequest(
|
||||||
|
nsStyleImageRequest::Mode aModeFlags, const StyleComputedImageUrl* aUrl) {
|
||||||
|
RefPtr<nsStyleImageRequest> req = new nsStyleImageRequest(aModeFlags, *aUrl);
|
||||||
|
return req.forget();
|
||||||
|
}
|
||||||
|
|
||||||
void Gecko_SetLayerImageImageValue(nsStyleImage* aImage,
|
void Gecko_SetLayerImageImageValue(nsStyleImage* aImage,
|
||||||
const StyleComputedImageUrl* aUrl) {
|
const StyleComputedImageUrl* aUrl) {
|
||||||
MOZ_ASSERT(aImage && aUrl);
|
MOZ_ASSERT(aImage && aUrl);
|
||||||
aImage->SetImageUrl(*aUrl);
|
|
||||||
|
RefPtr<nsStyleImageRequest> req =
|
||||||
|
CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aUrl);
|
||||||
|
aImage->SetImageRequest(req.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gecko_SetImageElement(nsStyleImage* aImage, nsAtom* aAtom) {
|
void Gecko_SetImageElement(nsStyleImage* aImage, nsAtom* aAtom) {
|
||||||
|
@ -1141,25 +1150,50 @@ void Gecko_InitializeImageCropRect(nsStyleImage* aImage) {
|
||||||
nsStyleImage::CropRect{zero, zero, zero, zero}));
|
nsStyleImage::CropRect{zero, zero, zero, zero}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gecko_SetCursorArrayCapacity(nsStyleUI* aUi, size_t aCapacity) {
|
void Gecko_SetCursorArrayLength(nsStyleUI* aStyleUI, size_t aLen) {
|
||||||
aUi->mCursorImages.Clear();
|
aStyleUI->mCursorImages.Clear();
|
||||||
aUi->mCursorImages.SetCapacity(aCapacity);
|
aStyleUI->mCursorImages.SetLength(aLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gecko_AppendCursorImage(nsStyleUI* aUi,
|
void Gecko_SetCursorImageValue(nsCursorImage* aCursor,
|
||||||
const StyleComputedImageUrl* aUrl) {
|
const StyleComputedImageUrl* aUrl) {
|
||||||
aUi->mCursorImages.EmplaceBack(*aUrl);
|
MOZ_ASSERT(aCursor && aUrl);
|
||||||
|
|
||||||
|
aCursor->mImage =
|
||||||
|
CreateStyleImageRequest(nsStyleImageRequest::Mode::Discard, aUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gecko_CopyCursorArrayFrom(nsStyleUI* aDest, const nsStyleUI* aSrc) {
|
void Gecko_CopyCursorArrayFrom(nsStyleUI* aDest, const nsStyleUI* aSrc) {
|
||||||
aDest->mCursorImages = aSrc->mCursorImages;
|
aDest->mCursorImages = aSrc->mCursorImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nsStyleImageRequest* Gecko_GetImageRequest(const nsStyleImage* aImage) {
|
||||||
|
MOZ_ASSERT(aImage);
|
||||||
|
return aImage->ImageRequest();
|
||||||
|
}
|
||||||
|
|
||||||
nsAtom* Gecko_GetImageElement(const nsStyleImage* aImage) {
|
nsAtom* Gecko_GetImageElement(const nsStyleImage* aImage) {
|
||||||
MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Element);
|
MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Element);
|
||||||
return const_cast<nsAtom*>(aImage->GetElementId());
|
return const_cast<nsAtom*>(aImage->GetElementId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gecko_SetListStyleImageNone(nsStyleList* aList) {
|
||||||
|
aList->mListStyleImage = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gecko_SetListStyleImageImageValue(nsStyleList* aList,
|
||||||
|
const StyleComputedImageUrl* aUrl) {
|
||||||
|
MOZ_ASSERT(aList && aUrl);
|
||||||
|
|
||||||
|
aList->mListStyleImage =
|
||||||
|
CreateStyleImageRequest(nsStyleImageRequest::Mode(0), aUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gecko_CopyListStyleImageFrom(nsStyleList* aList,
|
||||||
|
const nsStyleList* aSource) {
|
||||||
|
aList->mListStyleImage = aSource->mListStyleImage;
|
||||||
|
}
|
||||||
|
|
||||||
void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
|
void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
|
||||||
size_t aElemSize) {
|
size_t aElemSize) {
|
||||||
auto base = reinterpret_cast<
|
auto base = reinterpret_cast<
|
||||||
|
@ -1845,6 +1879,11 @@ bool Gecko_AssertClassAttrValueIsSane(const nsAttrValue* aValue) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gecko_LoadData_DeregisterLoad(const StyleLoadData* aData) {
|
||||||
|
MOZ_ASSERT(aData->load_id != 0);
|
||||||
|
ImageLoader::DeregisterCSSImageFromAllLoaders(*aData);
|
||||||
|
}
|
||||||
|
|
||||||
void Gecko_PrintfStderr(const nsCString* aStr) {
|
void Gecko_PrintfStderr(const nsCString* aStr) {
|
||||||
printf_stderr("%s", aStr->get());
|
printf_stderr("%s", aStr->get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,6 +349,7 @@ void Gecko_SetImageElement(nsStyleImage* image, nsAtom* atom);
|
||||||
void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
|
void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
|
||||||
void Gecko_InitializeImageCropRect(nsStyleImage* image);
|
void Gecko_InitializeImageCropRect(nsStyleImage* image);
|
||||||
|
|
||||||
|
const nsStyleImageRequest* Gecko_GetImageRequest(const nsStyleImage* image);
|
||||||
nsAtom* Gecko_GetImageElement(const nsStyleImage* image);
|
nsAtom* Gecko_GetImageElement(const nsStyleImage* image);
|
||||||
|
|
||||||
// list-style-image style.
|
// list-style-image style.
|
||||||
|
@ -360,8 +361,11 @@ void Gecko_SetListStyleImageImageValue(
|
||||||
void Gecko_CopyListStyleImageFrom(nsStyleList* dest, const nsStyleList* src);
|
void Gecko_CopyListStyleImageFrom(nsStyleList* dest, const nsStyleList* src);
|
||||||
|
|
||||||
// cursor style.
|
// cursor style.
|
||||||
void Gecko_SetCursorArrayCapacity(nsStyleUI*, size_t);
|
void Gecko_SetCursorArrayLength(nsStyleUI* ui, size_t len);
|
||||||
void Gecko_AppendCursorImage(nsStyleUI*, const mozilla::StyleComputedImageUrl*);
|
|
||||||
|
void Gecko_SetCursorImageValue(nsCursorImage* aCursor,
|
||||||
|
const mozilla::StyleComputedImageUrl* url);
|
||||||
|
|
||||||
void Gecko_CopyCursorArrayFrom(nsStyleUI* dest, const nsStyleUI* src);
|
void Gecko_CopyCursorArrayFrom(nsStyleUI* dest, const nsStyleUI* src);
|
||||||
|
|
||||||
// Dirtiness tracking.
|
// Dirtiness tracking.
|
||||||
|
@ -502,7 +506,7 @@ float Gecko_FontStretch_ToFloat(mozilla::FontStretch aStretch);
|
||||||
void Gecko_FontStretch_SetFloat(mozilla::FontStretch* aStretch,
|
void Gecko_FontStretch_SetFloat(mozilla::FontStretch* aStretch,
|
||||||
float aFloatValue);
|
float aFloatValue);
|
||||||
|
|
||||||
void Gecko_LoadData_Drop(mozilla::StyleLoadData*);
|
void Gecko_LoadData_DeregisterLoad(const mozilla::StyleLoadData*);
|
||||||
|
|
||||||
float Gecko_FontSlantStyle_ToFloat(mozilla::FontSlantStyle aStyle);
|
float Gecko_FontSlantStyle_ToFloat(mozilla::FontSlantStyle aStyle);
|
||||||
void Gecko_FontSlantStyle_SetNormal(mozilla::FontSlantStyle*);
|
void Gecko_FontSlantStyle_SetNormal(mozilla::FontSlantStyle*);
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/dom/DocumentInlines.h"
|
#include "mozilla/dom/DocumentInlines.h"
|
||||||
#include "mozilla/dom/ImageTracker.h"
|
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
|
@ -31,56 +30,15 @@ using namespace mozilla::dom;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace css {
|
namespace css {
|
||||||
|
|
||||||
// This is a singleton observer which looks in the `GlobalRequestTable` to look
|
|
||||||
// at which loaders to notify.
|
|
||||||
struct GlobalImageObserver final : public imgINotificationObserver {
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_IMGINOTIFICATIONOBSERVER
|
|
||||||
|
|
||||||
GlobalImageObserver() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~GlobalImageObserver() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF(GlobalImageObserver)
|
|
||||||
NS_IMPL_RELEASE(GlobalImageObserver)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN(GlobalImageObserver)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(imgINotificationObserver)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
// Data associated with every started load.
|
|
||||||
struct ImageTableEntry {
|
|
||||||
// Set of all ImageLoaders that have registered this URL and care for updates
|
|
||||||
// for it.
|
|
||||||
nsTHashtable<nsPtrHashKey<ImageLoader>> mImageLoaders;
|
|
||||||
};
|
|
||||||
|
|
||||||
using GlobalRequestTable =
|
|
||||||
nsClassHashtable<nsRefPtrHashKey<imgIRequest>, ImageTableEntry>;
|
|
||||||
|
|
||||||
// A table of all loads, keyed by their id mapping them to the set of
|
|
||||||
// ImageLoaders they have been registered in, and recording their "canonical"
|
|
||||||
// image request.
|
|
||||||
//
|
|
||||||
// We use the load id as the key since we can only access sImages on the
|
|
||||||
// main thread, but LoadData objects might be destroyed from other threads,
|
|
||||||
// and we don't want to leave dangling pointers around.
|
|
||||||
static GlobalRequestTable* sImages = nullptr;
|
|
||||||
static StaticRefPtr<GlobalImageObserver> sImageObserver;
|
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void ImageLoader::Init() {
|
void ImageLoader::Init() {
|
||||||
sImages = new GlobalRequestTable();
|
sImages = new nsClassHashtable<nsUint64HashKey, ImageTableEntry>();
|
||||||
sImageObserver = new GlobalImageObserver();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void ImageLoader::Shutdown() {
|
void ImageLoader::Shutdown() {
|
||||||
delete sImages;
|
delete sImages;
|
||||||
sImages = nullptr;
|
sImages = nullptr;
|
||||||
sImageObserver = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageLoader::DropDocumentReference() {
|
void ImageLoader::DropDocumentReference() {
|
||||||
|
@ -91,6 +49,21 @@ void ImageLoader::DropDocumentReference() {
|
||||||
// been destroyed, and it also calls ClearFrames when it is destroyed.
|
// been destroyed, and it also calls ClearFrames when it is destroyed.
|
||||||
ClearFrames(GetPresContext());
|
ClearFrames(GetPresContext());
|
||||||
|
|
||||||
|
for (auto it = mRegisteredImages.Iter(); !it.Done(); it.Next()) {
|
||||||
|
if (imgRequestProxy* request = it.Data()) {
|
||||||
|
request->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to check whether the entry exists, since the css::URLValue might
|
||||||
|
// go away before ImageLoader::DropDocumentReference is called.
|
||||||
|
uint64_t imageLoadID = it.Key();
|
||||||
|
if (auto entry = sImages->Lookup(imageLoadID)) {
|
||||||
|
entry.Data()->mImageLoaders.RemoveEntry(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mRegisteredImages.Clear();
|
||||||
|
|
||||||
mDocument = nullptr;
|
mDocument = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,31 +90,20 @@ void ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest,
|
||||||
nsIFrame* aFrame, FrameFlags aFlags) {
|
nsIFrame* aFrame, FrameFlags aFlags) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
{
|
nsCOMPtr<imgINotificationObserver> observer;
|
||||||
nsCOMPtr<imgINotificationObserver> observer;
|
aRequest->GetNotificationObserver(getter_AddRefs(observer));
|
||||||
aRequest->GetNotificationObserver(getter_AddRefs(observer));
|
if (!observer) {
|
||||||
if (!observer) {
|
// The request has already been canceled, so ignore it. This is ok because
|
||||||
// The request has already been canceled, so ignore it. This is ok because
|
// we're not going to get any more notifications from a canceled request.
|
||||||
// we're not going to get any more notifications from a canceled request.
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(observer == sImageObserver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(observer == this);
|
||||||
|
|
||||||
const auto& frameSet =
|
const auto& frameSet =
|
||||||
mRequestToFrameMap.LookupForAdd(aRequest).OrInsert([=]() {
|
mRequestToFrameMap.LookupForAdd(aRequest).OrInsert([=]() {
|
||||||
mDocument->ImageTracker()->Add(aRequest);
|
nsPresContext* presContext = GetPresContext();
|
||||||
|
if (presContext) {
|
||||||
if (auto entry = sImages->Lookup(aRequest)) {
|
|
||||||
DebugOnly<bool> inserted =
|
|
||||||
entry.Data()->mImageLoaders.EnsureInserted(this);
|
|
||||||
MOZ_ASSERT(inserted);
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT_UNREACHABLE(
|
|
||||||
"Shouldn't be associating images not in sImages");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsPresContext* presContext = GetPresContext()) {
|
|
||||||
nsLayoutUtils::RegisterImageRequestIfAnimated(presContext, aRequest,
|
nsLayoutUtils::RegisterImageRequestIfAnimated(presContext, aRequest,
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
@ -242,13 +204,100 @@ void ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest,
|
||||||
"We should only add to one map iff we also add to the other map.");
|
"We should only add to one map iff we also add to the other map.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imgRequestProxy* ImageLoader::RegisterCSSImage(const StyleLoadData& aData) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
uint64_t loadId = aData.load_id;
|
||||||
|
|
||||||
|
if (loadId == 0) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Image should have a valid LoadID");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imgRequestProxy* request = mRegisteredImages.GetWeak(loadId)) {
|
||||||
|
// This document already has a request.
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgRequestProxy* canonicalRequest = nullptr;
|
||||||
|
{
|
||||||
|
auto entry = sImages->Lookup(loadId);
|
||||||
|
if (entry) {
|
||||||
|
canonicalRequest = entry.Data()->mCanonicalRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canonicalRequest) {
|
||||||
|
// The image was blocked or something.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Data()->mImageLoaders.PutEntry(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<imgRequestProxy> request;
|
||||||
|
|
||||||
|
// Ignore errors here. If cloning fails for some reason we'll put a null
|
||||||
|
// entry in the hash and we won't keep trying to clone.
|
||||||
|
mInClone = true;
|
||||||
|
canonicalRequest->SyncClone(this, mDocument, getter_AddRefs(request));
|
||||||
|
mInClone = false;
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mRegisteredImages.Contains(loadId));
|
||||||
|
|
||||||
|
imgRequestProxy* requestWeak = request;
|
||||||
|
mRegisteredImages.Put(loadId, request.forget());
|
||||||
|
return requestWeak;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void ImageLoader::DeregisterCSSImageFromAllLoaders(const StyleLoadData& aData) {
|
||||||
|
uint64_t loadID = aData.load_id;
|
||||||
|
if (loadID == 0) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Image should have a valid LoadID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
DeregisterCSSImageFromAllLoaders(loadID);
|
||||||
|
} else {
|
||||||
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
|
"css::ImageLoader::DeregisterCSSImageFromAllLoaders",
|
||||||
|
[loadID] { DeregisterCSSImageFromAllLoaders(loadID); }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void ImageLoader::DeregisterCSSImageFromAllLoaders(uint64_t aImageLoadID) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(aImageLoadID != 0);
|
||||||
|
|
||||||
|
if (auto e = sImages->Lookup(aImageLoadID)) {
|
||||||
|
const auto& tableEntry = e.Data();
|
||||||
|
if (imgRequestProxy* request = tableEntry->mCanonicalRequest) {
|
||||||
|
request->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto iter = tableEntry->mImageLoaders.Iter(); !iter.Done();
|
||||||
|
iter.Next()) {
|
||||||
|
ImageLoader* loader = iter.Get()->GetKey();
|
||||||
|
if (auto e = loader->mRegisteredImages.Lookup(aImageLoadID)) {
|
||||||
|
if (imgRequestProxy* request = e.Data()) {
|
||||||
|
request->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||||
|
}
|
||||||
|
e.Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ImageLoader::RemoveRequestToFrameMapping(imgIRequest* aRequest,
|
void ImageLoader::RemoveRequestToFrameMapping(imgIRequest* aRequest,
|
||||||
nsIFrame* aFrame) {
|
nsIFrame* aFrame) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
{
|
{
|
||||||
nsCOMPtr<imgINotificationObserver> observer;
|
nsCOMPtr<imgINotificationObserver> observer;
|
||||||
aRequest->GetNotificationObserver(getter_AddRefs(observer));
|
aRequest->GetNotificationObserver(getter_AddRefs(observer));
|
||||||
MOZ_ASSERT(!observer || observer == sImageObserver);
|
MOZ_ASSERT(!observer || observer == this);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -271,25 +320,15 @@ void ImageLoader::RemoveRequestToFrameMapping(imgIRequest* aRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frameSet->IsEmpty()) {
|
if (frameSet->IsEmpty()) {
|
||||||
DeregisterImageRequest(aRequest, GetPresContext());
|
nsPresContext* presContext = GetPresContext();
|
||||||
|
if (presContext) {
|
||||||
|
nsLayoutUtils::DeregisterImageRequest(presContext, aRequest, nullptr);
|
||||||
|
}
|
||||||
entry.Remove();
|
entry.Remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageLoader::DeregisterImageRequest(imgIRequest* aRequest,
|
|
||||||
nsPresContext* aPresContext) {
|
|
||||||
mDocument->ImageTracker()->Remove(aRequest);
|
|
||||||
|
|
||||||
if (auto entry = sImages->Lookup(aRequest)) {
|
|
||||||
entry.Data()->mImageLoaders.EnsureRemoved(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aPresContext) {
|
|
||||||
nsLayoutUtils::DeregisterImageRequest(aPresContext, aRequest, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageLoader::RemoveFrameToRequestMapping(imgIRequest* aRequest,
|
void ImageLoader::RemoveFrameToRequestMapping(imgIRequest* aRequest,
|
||||||
nsIFrame* aFrame) {
|
nsIFrame* aFrame) {
|
||||||
if (auto entry = mFrameToRequestMap.Lookup(aFrame)) {
|
if (auto entry = mFrameToRequestMap.Lookup(aFrame)) {
|
||||||
|
@ -373,7 +412,9 @@ void ImageLoader::ClearFrames(nsPresContext* aPresContext) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DeregisterImageRequest(request, aPresContext);
|
if (aPresContext) {
|
||||||
|
nsLayoutUtils::DeregisterImageRequest(aPresContext, request, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mRequestToFrameMap.Clear();
|
mRequestToFrameMap.Clear();
|
||||||
|
@ -395,12 +436,25 @@ static CORSMode EffectiveCorsMode(nsIURI* aURI,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
already_AddRefed<imgRequestProxy> ImageLoader::LoadImage(
|
void ImageLoader::LoadImage(const StyleComputedImageUrl& aImage,
|
||||||
const StyleComputedImageUrl& aImage, Document& aLoadingDoc) {
|
Document& aLoadingDoc) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
uint64_t loadId = aImage.LoadData().load_id;
|
||||||
|
if (loadId == 0) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Image should have a valid LoadID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lookup = sImages->LookupForAdd(loadId);
|
||||||
|
if (lookup) {
|
||||||
|
// This url has already been loaded.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto& entry = lookup.OrInsert([]() { return new ImageTableEntry(); });
|
||||||
|
|
||||||
nsIURI* uri = aImage.GetURI();
|
nsIURI* uri = aImage.GetURI();
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t loadFlags =
|
int32_t loadFlags =
|
||||||
|
@ -412,27 +466,13 @@ already_AddRefed<imgRequestProxy> ImageLoader::LoadImage(
|
||||||
RefPtr<imgRequestProxy> request;
|
RefPtr<imgRequestProxy> request;
|
||||||
nsresult rv = nsContentUtils::LoadImage(
|
nsresult rv = nsContentUtils::LoadImage(
|
||||||
uri, &aLoadingDoc, &aLoadingDoc, data.Principal(), 0, data.ReferrerInfo(),
|
uri, &aLoadingDoc, &aLoadingDoc, data.Principal(), 0, data.ReferrerInfo(),
|
||||||
sImageObserver, loadFlags, NS_LITERAL_STRING("css"),
|
nullptr, loadFlags, NS_LITERAL_STRING("css"), getter_AddRefs(request));
|
||||||
getter_AddRefs(request));
|
|
||||||
|
|
||||||
if (NS_FAILED(rv) || !request) {
|
if (NS_FAILED(rv) || !request) {
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sImages->LookupForAdd(request).OrInsert([] { return new ImageTableEntry(); });
|
entry->mCanonicalRequest = std::move(request);
|
||||||
return request.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageLoader::DeregisterImageFromAllLoaders(imgRequestProxy* aImage) {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
MOZ_ASSERT(aImage);
|
|
||||||
aImage->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
|
||||||
if (auto lookup = sImages->Lookup(aImage)) {
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(lookup.Data()->mImageLoaders.IsEmpty(),
|
|
||||||
"Shouldn't be keeping references to any loader "
|
|
||||||
"by now");
|
|
||||||
lookup.Remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPresContext* ImageLoader::GetPresContext() {
|
nsPresContext* ImageLoader::GetPresContext() {
|
||||||
|
@ -571,8 +611,6 @@ void ImageLoader::RequestReflowOnFrame(FrameWithFlags* aFwf,
|
||||||
nsIFrame* frame = aFwf->mFrame;
|
nsIFrame* frame = aFwf->mFrame;
|
||||||
|
|
||||||
// Actually request the reflow.
|
// Actually request the reflow.
|
||||||
//
|
|
||||||
// FIXME(emilio): Why requesting reflow on the _parent_?
|
|
||||||
nsIFrame* parent = frame->GetInFlowParent();
|
nsIFrame* parent = frame->GetInFlowParent();
|
||||||
parent->PresShell()->FrameNeedsReflow(parent, IntrinsicDirty::StyleChange,
|
parent->PresShell()->FrameNeedsReflow(parent, IntrinsicDirty::StyleChange,
|
||||||
NS_FRAME_IS_DIRTY);
|
NS_FRAME_IS_DIRTY);
|
||||||
|
@ -580,32 +618,21 @@ void ImageLoader::RequestReflowOnFrame(FrameWithFlags* aFwf,
|
||||||
// We'll respond to the reflow events by unblocking onload, regardless
|
// We'll respond to the reflow events by unblocking onload, regardless
|
||||||
// of whether the reflow was completed or cancelled. The callback will
|
// of whether the reflow was completed or cancelled. The callback will
|
||||||
// also delete itself when it is called.
|
// also delete itself when it is called.
|
||||||
auto* unblocker = new ImageReflowCallback(this, frame, aRequest);
|
ImageReflowCallback* unblocker =
|
||||||
|
new ImageReflowCallback(this, frame, aRequest);
|
||||||
parent->PresShell()->PostReflowCallback(unblocker);
|
parent->PresShell()->PostReflowCallback(unblocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF(ImageLoader)
|
||||||
|
NS_IMPL_RELEASE(ImageLoader)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(ImageLoader)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(imgINotificationObserver)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GlobalImageObserver::Notify(imgIRequest* aRequest, int32_t aType,
|
ImageLoader::Notify(imgIRequest* aRequest, int32_t aType,
|
||||||
const nsIntRect* aData) {
|
const nsIntRect* aData) {
|
||||||
auto entry = sImages->Lookup(aRequest);
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(entry);
|
|
||||||
if (MOZ_UNLIKELY(!entry)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& loaders = entry.Data()->mImageLoaders;
|
|
||||||
nsTArray<RefPtr<ImageLoader>> loadersToNotify(loaders.Count());
|
|
||||||
for (auto iter = loaders.Iter(); !iter.Done(); iter.Next()) {
|
|
||||||
loadersToNotify.AppendElement(iter.Get()->GetKey());
|
|
||||||
}
|
|
||||||
for (auto& loader : loadersToNotify) {
|
|
||||||
loader->Notify(aRequest, aType, aData);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult ImageLoader::Notify(imgIRequest* aRequest, int32_t aType,
|
|
||||||
const nsIntRect* aData) {
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
nsCString uriString;
|
nsCString uriString;
|
||||||
if (profiler_is_active()) {
|
if (profiler_is_active()) {
|
||||||
|
@ -697,7 +724,7 @@ nsresult ImageLoader::OnImageIsAnimated(imgIRequest* aRequest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ImageLoader::OnFrameComplete(imgIRequest* aRequest) {
|
nsresult ImageLoader::OnFrameComplete(imgIRequest* aRequest) {
|
||||||
if (!mDocument) {
|
if (!mDocument || mInClone) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,7 +745,7 @@ nsresult ImageLoader::OnFrameComplete(imgIRequest* aRequest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ImageLoader::OnFrameUpdate(imgIRequest* aRequest) {
|
nsresult ImageLoader::OnFrameUpdate(imgIRequest* aRequest) {
|
||||||
if (!mDocument) {
|
if (!mDocument || mInClone) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,7 +760,7 @@ nsresult ImageLoader::OnFrameUpdate(imgIRequest* aRequest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ImageLoader::OnLoadComplete(imgIRequest* aRequest) {
|
nsresult ImageLoader::OnLoadComplete(imgIRequest* aRequest) {
|
||||||
if (!mDocument) {
|
if (!mDocument || mInClone) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,6 +788,30 @@ nsresult ImageLoader::OnLoadComplete(imgIRequest* aRequest) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageLoader::MediaFeatureValuesChangedAllDocuments(
|
||||||
|
const MediaFeatureChange& aChange) {
|
||||||
|
// Inform every CSS image used in the document that media feature values have
|
||||||
|
// changed. If the same image is used in multiple places, then we can end up
|
||||||
|
// informing them multiple times. Theme changes are rare though and we don't
|
||||||
|
// bother trying to ensure we only do this once per image.
|
||||||
|
//
|
||||||
|
// Pull the images out into an array and iterate over them, in case the
|
||||||
|
// image notifications do something that ends up modifying the table.
|
||||||
|
nsTArray<nsCOMPtr<imgIContainer>> images;
|
||||||
|
for (auto iter = mRegisteredImages.Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
imgRequestProxy* req = iter.Data();
|
||||||
|
nsCOMPtr<imgIContainer> image;
|
||||||
|
req->GetImage(getter_AddRefs(image));
|
||||||
|
if (!image) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
images.AppendElement(image->Unwrap());
|
||||||
|
}
|
||||||
|
for (imgIContainer* image : images) {
|
||||||
|
image->MediaFeatureValuesChangedAllDocuments(aChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ImageLoader::ImageReflowCallback::ReflowFinished() {
|
bool ImageLoader::ImageReflowCallback::ReflowFinished() {
|
||||||
// Check that the frame is still valid. If it isn't, then onload was
|
// Check that the frame is still valid. If it isn't, then onload was
|
||||||
// unblocked when the frame was removed from the FrameSet in
|
// unblocked when the frame was removed from the FrameSet in
|
||||||
|
@ -788,5 +839,8 @@ void ImageLoader::ImageReflowCallback::ReflowCallbackCanceled() {
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsClassHashtable<nsUint64HashKey, ImageLoader::ImageTableEntry>*
|
||||||
|
ImageLoader::sImages = nullptr;
|
||||||
|
|
||||||
} // namespace css
|
} // namespace css
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "imgIRequest.h"
|
#include "imgIRequest.h"
|
||||||
#include "imgINotificationObserver.h"
|
#include "imgINotificationObserver.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/MediaFeatureChange.h"
|
||||||
|
|
||||||
class imgIContainer;
|
class imgIContainer;
|
||||||
class nsIFrame;
|
class nsIFrame;
|
||||||
|
@ -37,7 +38,7 @@ namespace css {
|
||||||
* NOTE: All methods must be called from the main thread unless otherwise
|
* NOTE: All methods must be called from the main thread unless otherwise
|
||||||
* specified.
|
* specified.
|
||||||
*/
|
*/
|
||||||
class ImageLoader final {
|
class ImageLoader final : public imgINotificationObserver {
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
@ -51,14 +52,17 @@ class ImageLoader final {
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ImageLoader(dom::Document* aDocument)
|
explicit ImageLoader(dom::Document* aDocument)
|
||||||
: mDocument(aDocument) {
|
: mDocument(aDocument), mInClone(false) {
|
||||||
MOZ_ASSERT(mDocument);
|
MOZ_ASSERT(mDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_INLINE_DECL_REFCOUNTING(ImageLoader)
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_IMGINOTIFICATIONOBSERVER
|
||||||
|
|
||||||
void DropDocumentReference();
|
void DropDocumentReference();
|
||||||
|
|
||||||
|
imgRequestProxy* RegisterCSSImage(const StyleLoadData& aImage);
|
||||||
|
|
||||||
void AssociateRequestToFrame(imgIRequest* aRequest, nsIFrame* aFrame,
|
void AssociateRequestToFrame(imgIRequest* aRequest, nsIFrame* aFrame,
|
||||||
FrameFlags aFlags);
|
FrameFlags aFlags);
|
||||||
|
|
||||||
|
@ -68,24 +72,26 @@ class ImageLoader final {
|
||||||
|
|
||||||
void SetAnimationMode(uint16_t aMode);
|
void SetAnimationMode(uint16_t aMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the document's pres context when media features in all
|
||||||
|
* SVG images must be re-evaluated.
|
||||||
|
*/
|
||||||
|
void MediaFeatureValuesChangedAllDocuments(const MediaFeatureChange& aChange);
|
||||||
|
|
||||||
// The prescontext for this ImageLoader's document. We need it to be passed
|
// The prescontext for this ImageLoader's document. We need it to be passed
|
||||||
// in because this can be called during presentation destruction after the
|
// in because this can be called during presentation destruction after the
|
||||||
// presshell pointer on the document has been cleared.
|
// presshell pointer on the document has been cleared.
|
||||||
void ClearFrames(nsPresContext* aPresContext);
|
void ClearFrames(nsPresContext* aPresContext);
|
||||||
|
|
||||||
static already_AddRefed<imgRequestProxy> LoadImage(
|
static void LoadImage(const StyleComputedImageUrl& aImage, dom::Document&);
|
||||||
const StyleComputedImageUrl&, dom::Document&);
|
|
||||||
|
|
||||||
static void DeregisterImageFromAllLoaders(imgRequestProxy*);
|
// Cancels the image load for the given LoadData and deregisters it from any
|
||||||
|
// ImageLoaders it was registered with.
|
||||||
// This is called whenever an image we care about notifies the
|
//
|
||||||
// GlobalImageObserver.
|
// May be called from any thread.
|
||||||
nsresult Notify(imgIRequest*, int32_t aType, const nsIntRect* aData);
|
static void DeregisterCSSImageFromAllLoaders(const StyleLoadData&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Called when we stop caring about a given request.
|
|
||||||
void DeregisterImageRequest(imgIRequest*, nsPresContext*);
|
|
||||||
|
|
||||||
// This callback is used to unblock document onload after a reflow
|
// This callback is used to unblock document onload after a reflow
|
||||||
// triggered from an image load.
|
// triggered from an image load.
|
||||||
struct ImageReflowCallback final : public nsIReflowCallback {
|
struct ImageReflowCallback final : public nsIReflowCallback {
|
||||||
|
@ -155,6 +161,9 @@ class ImageLoader final {
|
||||||
void RemoveRequestToFrameMapping(imgIRequest* aRequest, nsIFrame* aFrame);
|
void RemoveRequestToFrameMapping(imgIRequest* aRequest, nsIFrame* aFrame);
|
||||||
void RemoveFrameToRequestMapping(imgIRequest* aRequest, nsIFrame* aFrame);
|
void RemoveFrameToRequestMapping(imgIRequest* aRequest, nsIFrame* aFrame);
|
||||||
|
|
||||||
|
// Helper for the public DeregisterCSSImageFromAllLoaders overload above.
|
||||||
|
static void DeregisterCSSImageFromAllLoaders(uint64_t aLoadID);
|
||||||
|
|
||||||
// A map of imgIRequests to the nsIFrames that are using them.
|
// A map of imgIRequests to the nsIFrames that are using them.
|
||||||
RequestToFrameMap mRequestToFrameMap;
|
RequestToFrameMap mRequestToFrameMap;
|
||||||
|
|
||||||
|
@ -163,6 +172,40 @@ class ImageLoader final {
|
||||||
|
|
||||||
// A weak pointer to our document. Nulled out by DropDocumentReference.
|
// A weak pointer to our document. Nulled out by DropDocumentReference.
|
||||||
dom::Document* mDocument;
|
dom::Document* mDocument;
|
||||||
|
|
||||||
|
// A map of css ComputedUrls, keyed by their LoadID(), to the imgRequestProxy
|
||||||
|
// representing the load of the image for this ImageLoader's document.
|
||||||
|
//
|
||||||
|
// We use the LoadID() as the key since we can only access mRegisteredImages
|
||||||
|
// on the main thread, but Urls might be destroyed from other threads, and we
|
||||||
|
// don't want to leave dangling pointers around.
|
||||||
|
nsRefPtrHashtable<nsUint64HashKey, imgRequestProxy> mRegisteredImages;
|
||||||
|
|
||||||
|
// Are we cloning? If so, ignore any notifications we get.
|
||||||
|
bool mInClone;
|
||||||
|
|
||||||
|
// Data associated with every started load.
|
||||||
|
struct ImageTableEntry {
|
||||||
|
// Set of all ImageLoaders that have registered this URL.
|
||||||
|
nsTHashtable<nsPtrHashKey<ImageLoader>> mImageLoaders;
|
||||||
|
|
||||||
|
// The "canonical" image request for this URL.
|
||||||
|
//
|
||||||
|
// This request is held on to as long as the specified URL is, so that any
|
||||||
|
// image that has already started loading (or has completed loading) will
|
||||||
|
// stay alive even if all computed values referencing the image requesst
|
||||||
|
// have gone away.
|
||||||
|
RefPtr<imgRequestProxy> mCanonicalRequest;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A table of all loads, keyed by their id mapping them to the set of
|
||||||
|
// ImageLoaders they have been registered in, and recording their "canonical"
|
||||||
|
// image request.
|
||||||
|
//
|
||||||
|
// We use the load id as the key since we can only access sImages on the
|
||||||
|
// main thread, but LoadData objects might be destroyed from other threads,
|
||||||
|
// and we don't want to leave dangling pointers around.
|
||||||
|
static nsClassHashtable<nsUint64HashKey, ImageTableEntry>* sImages;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace css
|
} // namespace css
|
||||||
|
|
|
@ -115,8 +115,6 @@ enum class CallerType : uint32_t;
|
||||||
|
|
||||||
class Element;
|
class Element;
|
||||||
class Document;
|
class Document;
|
||||||
class ImageTracker;
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
@ -177,7 +175,6 @@ struct StyleBox {
|
||||||
// Work-around weird cbindgen renaming / avoiding moving stuff outside its
|
// Work-around weird cbindgen renaming / avoiding moving stuff outside its
|
||||||
// namespace.
|
// namespace.
|
||||||
|
|
||||||
using StyleImageTracker = dom::ImageTracker;
|
|
||||||
using StyleLoader = css::Loader;
|
using StyleLoader = css::Loader;
|
||||||
using StyleLoaderReusableStyleSheets = css::LoaderReusableStyleSheets;
|
using StyleLoaderReusableStyleSheets = css::LoaderReusableStyleSheets;
|
||||||
using StyleCallerType = dom::CallerType;
|
using StyleCallerType = dom::CallerType;
|
||||||
|
|
|
@ -390,14 +390,12 @@ inline StyleLoadData& StyleCssUrl::LoadData() const {
|
||||||
inline nsIURI* StyleCssUrl::GetURI() const {
|
inline nsIURI* StyleCssUrl::GetURI() const {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||||
auto& loadData = LoadData();
|
auto& loadData = LoadData();
|
||||||
if (!(loadData.flags & StyleLoadDataFlags::TRIED_TO_RESOLVE_URI)) {
|
if (!loadData.tried_to_resolve) {
|
||||||
loadData.flags |= StyleLoadDataFlags::TRIED_TO_RESOLVE_URI;
|
loadData.tried_to_resolve = true;
|
||||||
RefPtr<nsIURI> resolved;
|
NS_NewURI(getter_AddRefs(loadData.resolved), SpecifiedSerialization(),
|
||||||
NS_NewURI(getter_AddRefs(resolved), SpecifiedSerialization(), nullptr,
|
nullptr, ExtraData().BaseURI());
|
||||||
ExtraData().BaseURI());
|
|
||||||
loadData.resolved_uri = resolved.forget().take();
|
|
||||||
}
|
}
|
||||||
return loadData.resolved_uri;
|
return loadData.resolved.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline nsDependentCSubstring StyleComputedUrl::SpecifiedSerialization() const {
|
inline nsDependentCSubstring StyleComputedUrl::SpecifiedSerialization() const {
|
||||||
|
@ -429,15 +427,6 @@ inline bool StyleComputedUrl::HasRef() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool StyleComputedImageUrl::IsImageResolved() const {
|
|
||||||
return bool(LoadData().flags & StyleLoadDataFlags::TRIED_TO_RESOLVE_IMAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline imgRequestProxy* StyleComputedImageUrl::GetImage() const {
|
|
||||||
MOZ_ASSERT(IsImageResolved());
|
|
||||||
return LoadData().resolved_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool StyleGradient::IsOpaque() const;
|
bool StyleGradient::IsOpaque() const;
|
||||||
|
|
||||||
|
|
|
@ -625,6 +625,11 @@ static void AddImageURL(const StyleComputedUrl& aURL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AddImageURL(const nsStyleImageRequest& aRequest,
|
||||||
|
nsTArray<nsCString>& aURLs) {
|
||||||
|
AddImageURL(aRequest.GetImageValue(), aURLs);
|
||||||
|
}
|
||||||
|
|
||||||
static void AddImageURL(const nsStyleImage& aImage,
|
static void AddImageURL(const nsStyleImage& aImage,
|
||||||
nsTArray<nsCString>& aURLs) {
|
nsTArray<nsCString>& aURLs) {
|
||||||
if (auto* urlValue = aImage.GetURLValue()) {
|
if (auto* urlValue = aImage.GetURLValue()) {
|
||||||
|
@ -664,7 +669,7 @@ static void CollectImageURLsForProperty(nsCSSPropertyID aProp,
|
||||||
switch (aProp) {
|
switch (aProp) {
|
||||||
case eCSSProperty_cursor:
|
case eCSSProperty_cursor:
|
||||||
for (auto& image : aStyle.StyleUI()->mCursorImages) {
|
for (auto& image : aStyle.StyleUI()->mCursorImages) {
|
||||||
AddImageURL(image.mImage, aURLs);
|
AddImageURL(*image.mImage, aURLs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eCSSProperty_background_image:
|
case eCSSProperty_background_image:
|
||||||
|
@ -673,13 +678,11 @@ static void CollectImageURLsForProperty(nsCSSPropertyID aProp,
|
||||||
case eCSSProperty_mask_clip:
|
case eCSSProperty_mask_clip:
|
||||||
AddImageURLs(aStyle.StyleSVGReset()->mMask, aURLs);
|
AddImageURLs(aStyle.StyleSVGReset()->mMask, aURLs);
|
||||||
break;
|
break;
|
||||||
case eCSSProperty_list_style_image: {
|
case eCSSProperty_list_style_image:
|
||||||
const auto& image = aStyle.StyleList()->mListStyleImage;
|
if (nsStyleImageRequest* image = aStyle.StyleList()->mListStyleImage) {
|
||||||
if (image.IsUrl()) {
|
AddImageURL(*image, aURLs);
|
||||||
AddImageURL(image.AsUrl(), aURLs);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case eCSSProperty_border_image_source:
|
case eCSSProperty_border_image_source:
|
||||||
AddImageURL(aStyle.StyleBorder()->mBorderImageSource, aURLs);
|
AddImageURL(aStyle.StyleBorder()->mBorderImageSource, aURLs);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#include "mozilla/dom/ImageTracker.h"
|
#include "mozilla/dom/ImageTracker.h"
|
||||||
#include "mozilla/CORSMode.h"
|
#include "mozilla/CORSMode.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/GeckoBindings.h"
|
|
||||||
#include "mozilla/PreferenceSheet.h"
|
#include "mozilla/PreferenceSheet.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
|
@ -69,6 +68,19 @@ struct AssertSizeIsLessThan {
|
||||||
#include "nsStyleStructList.h"
|
#include "nsStyleStructList.h"
|
||||||
#undef STYLE_STRUCT
|
#undef STYLE_STRUCT
|
||||||
|
|
||||||
|
static bool DefinitelyEqualImages(const nsStyleImageRequest* aRequest1,
|
||||||
|
const nsStyleImageRequest* aRequest2) {
|
||||||
|
if (aRequest1 == aRequest2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aRequest1 || !aRequest2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aRequest1->DefinitelyEquals(*aRequest2);
|
||||||
|
}
|
||||||
|
|
||||||
bool StyleCssUrlData::operator==(const StyleCssUrlData& aOther) const {
|
bool StyleCssUrlData::operator==(const StyleCssUrlData& aOther) const {
|
||||||
// This very intentionally avoids comparing LoadData and such.
|
// This very intentionally avoids comparing LoadData and such.
|
||||||
const auto& extra = extra_data.get();
|
const auto& extra = extra_data.get();
|
||||||
|
@ -83,7 +95,11 @@ bool StyleCssUrlData::operator==(const StyleCssUrlData& aOther) const {
|
||||||
return serialization == aOther.serialization;
|
return serialization == aOther.serialization;
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleLoadData::~StyleLoadData() { Gecko_LoadData_Drop(this); }
|
StyleLoadData::~StyleLoadData() {
|
||||||
|
if (load_id != 0) {
|
||||||
|
css::ImageLoader::DeregisterCSSImageFromAllLoaders(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIURI> StyleComputedUrl::ResolveLocalRef(nsIURI* aURI) const {
|
already_AddRefed<nsIURI> StyleComputedUrl::ResolveLocalRef(nsIURI* aURI) const {
|
||||||
nsCOMPtr<nsIURI> result = GetURI();
|
nsCOMPtr<nsIURI> result = GetURI();
|
||||||
|
@ -106,124 +122,56 @@ already_AddRefed<nsIURI> StyleComputedUrl::ResolveLocalRef(
|
||||||
return ResolveLocalRef(aContent->GetBaseURI());
|
return ResolveLocalRef(aContent->GetBaseURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyleComputedUrl::ResolveImage(Document& aDocument,
|
already_AddRefed<imgRequestProxy> StyleComputedUrl::LoadImage(
|
||||||
const StyleComputedUrl* aOldImage) {
|
Document& aDocument) {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
StyleLoadData& data = LoadData();
|
|
||||||
|
|
||||||
MOZ_ASSERT(!(data.flags & StyleLoadDataFlags::TRIED_TO_RESOLVE_IMAGE));
|
|
||||||
|
|
||||||
data.flags |= StyleLoadDataFlags::TRIED_TO_RESOLVE_IMAGE;
|
|
||||||
|
|
||||||
nsIURI* docURI = aDocument.GetDocumentURI();
|
nsIURI* docURI = aDocument.GetDocumentURI();
|
||||||
if (HasRef()) {
|
if (HasRef()) {
|
||||||
bool isEqualExceptRef = false;
|
bool isEqualExceptRef = false;
|
||||||
nsIURI* imageURI = GetURI();
|
nsIURI* imageURI = GetURI();
|
||||||
if (!imageURI) {
|
if (!imageURI) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_SUCCEEDED(imageURI->EqualsExceptRef(docURI, &isEqualExceptRef)) &&
|
if (NS_SUCCEEDED(imageURI->EqualsExceptRef(docURI, &isEqualExceptRef)) &&
|
||||||
isEqualExceptRef) {
|
isEqualExceptRef) {
|
||||||
// Prevent loading an internal resource.
|
// Prevent loading an internal resource.
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
static uint64_t sNextLoadID = 1;
|
||||||
|
|
||||||
// TODO(emilio, bug 1440442): This is a hackaround to avoid flickering due the
|
StyleLoadData& data = LoadData();
|
||||||
// lack of non-http image caching in imagelib (bug 1406134), which causes
|
if (data.load_id == 0) {
|
||||||
// stuff like bug 1439285. Cleanest fix if that doesn't get fixed is bug
|
data.load_id = sNextLoadID++;
|
||||||
// 1440305, but that seems too risky, and a lot of work to do before 60.
|
|
||||||
//
|
|
||||||
// Once that's fixed, the "old style" argument to TriggerImageLoads can go
|
|
||||||
// away.
|
|
||||||
const bool reuseProxy = nsContentUtils::IsChromeDoc(&aDocument) &&
|
|
||||||
aOldImage && aOldImage->IsImageResolved() &&
|
|
||||||
*this == *aOldImage;
|
|
||||||
|
|
||||||
RefPtr<imgRequestProxy> request;
|
|
||||||
if (reuseProxy) {
|
|
||||||
request = aOldImage->LoadData().resolved_image;
|
|
||||||
} else {
|
|
||||||
// NB: If aDocument is not the original document, we may not be able to load
|
|
||||||
// images from aDocument. Instead we do the image load from the original
|
|
||||||
// doc and clone it to aDocument.
|
|
||||||
Document* loadingDoc = aDocument.GetOriginalDocument();
|
|
||||||
const bool isPrint = !!loadingDoc;
|
|
||||||
if (!loadingDoc) {
|
|
||||||
loadingDoc = &aDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kick off the load in the loading document.
|
|
||||||
request = css::ImageLoader::LoadImage(*this, *loadingDoc);
|
|
||||||
|
|
||||||
if (isPrint && request) {
|
|
||||||
RefPtr<imgRequestProxy> ret;
|
|
||||||
request->GetStaticRequest(&aDocument, getter_AddRefs(ret));
|
|
||||||
request = std::move(ret);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB: If aDocument is not the original document, we may not be able to load
|
||||||
|
// images from aDocument. Instead we do the image load from the original doc
|
||||||
|
// and clone it to aDocument.
|
||||||
|
Document* loadingDoc = aDocument.GetOriginalDocument();
|
||||||
|
const bool isPrint = !!loadingDoc;
|
||||||
|
if (!loadingDoc) {
|
||||||
|
loadingDoc = &aDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick off the load in the loading document.
|
||||||
|
css::ImageLoader::LoadImage(*this, *loadingDoc);
|
||||||
|
|
||||||
|
// Register the image in the document that's using it.
|
||||||
|
imgRequestProxy* request =
|
||||||
|
aDocument.StyleImageLoader()->RegisterCSSImage(data);
|
||||||
if (!request) {
|
if (!request) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (!isPrint) {
|
||||||
data.resolved_image = request.forget().take();
|
return do_AddRef(request);
|
||||||
|
|
||||||
// Boost priority now that we know the image is present in the ComputedStyle
|
|
||||||
// of some frame.
|
|
||||||
data.resolved_image->BoostPriority(imgIRequest::CATEGORY_FRAME_STYLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runnable to release the image request's mRequestProxy
|
|
||||||
* and mImageTracker on the main thread, and to perform
|
|
||||||
* any necessary unlocking and untracking of the image.
|
|
||||||
*/
|
|
||||||
class StyleImageRequestCleanupTask final : public mozilla::Runnable {
|
|
||||||
public:
|
|
||||||
explicit StyleImageRequestCleanupTask(StyleLoadData& aData)
|
|
||||||
: mozilla::Runnable("StyleImageRequestCleanupTask"),
|
|
||||||
mRequestProxy(dont_AddRef(aData.resolved_image)) {
|
|
||||||
MOZ_ASSERT(mRequestProxy);
|
|
||||||
aData.resolved_image = nullptr;
|
|
||||||
}
|
}
|
||||||
|
RefPtr<imgRequestProxy> ret;
|
||||||
NS_IMETHOD Run() final {
|
request->GetStaticRequest(&aDocument, getter_AddRefs(ret));
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
return ret.forget();
|
||||||
css::ImageLoader::DeregisterImageFromAllLoaders(mRequestProxy);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~StyleImageRequestCleanupTask() {
|
|
||||||
MOZ_ASSERT(!mRequestProxy || NS_IsMainThread(),
|
|
||||||
"mRequestProxy destructor need to run on the main thread!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Since we always dispatch this runnable to the main thread, these will be
|
|
||||||
// released on the main thread when the runnable itself is released.
|
|
||||||
RefPtr<imgRequestProxy> mRequestProxy;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is defined here for parallelism with LoadURI.
|
|
||||||
void Gecko_LoadData_Drop(StyleLoadData* aData) {
|
|
||||||
if (aData->resolved_image) {
|
|
||||||
auto task = MakeRefPtr<StyleImageRequestCleanupTask>(*aData);
|
|
||||||
if (NS_IsMainThread()) {
|
|
||||||
task->Run();
|
|
||||||
} else {
|
|
||||||
// if Resolve was not called at some point, mDocGroup is not set.
|
|
||||||
SystemGroup::Dispatch(TaskCategory::Other, task.forget());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// URIs are safe to refcount from any thread.
|
|
||||||
NS_IF_RELEASE(aData->resolved_uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
|
@ -614,7 +562,6 @@ nsChangeHint nsStyleOutline::CalcDifference(
|
||||||
nsStyleList::nsStyleList(const Document& aDocument)
|
nsStyleList::nsStyleList(const Document& aDocument)
|
||||||
: mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE),
|
: mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE),
|
||||||
mQuotes(StyleQuotes::Auto()),
|
mQuotes(StyleQuotes::Auto()),
|
||||||
mListStyleImage(StyleImageUrlOrNone::None()),
|
|
||||||
mImageRegion(StyleClipRectOrAuto::Auto()),
|
mImageRegion(StyleClipRectOrAuto::Auto()),
|
||||||
mMozListReversed(StyleMozListReversed::False) {
|
mMozListReversed(StyleMozListReversed::False) {
|
||||||
MOZ_COUNT_CTOR(nsStyleList);
|
MOZ_COUNT_CTOR(nsStyleList);
|
||||||
|
@ -627,9 +574,9 @@ nsStyleList::~nsStyleList() { MOZ_COUNT_DTOR(nsStyleList); }
|
||||||
|
|
||||||
nsStyleList::nsStyleList(const nsStyleList& aSource)
|
nsStyleList::nsStyleList(const nsStyleList& aSource)
|
||||||
: mListStylePosition(aSource.mListStylePosition),
|
: mListStylePosition(aSource.mListStylePosition),
|
||||||
|
mListStyleImage(aSource.mListStyleImage),
|
||||||
mCounterStyle(aSource.mCounterStyle),
|
mCounterStyle(aSource.mCounterStyle),
|
||||||
mQuotes(aSource.mQuotes),
|
mQuotes(aSource.mQuotes),
|
||||||
mListStyleImage(aSource.mListStyleImage),
|
|
||||||
mImageRegion(aSource.mImageRegion),
|
mImageRegion(aSource.mImageRegion),
|
||||||
mMozListReversed(aSource.mMozListReversed) {
|
mMozListReversed(aSource.mMozListReversed) {
|
||||||
MOZ_COUNT_CTOR(nsStyleList);
|
MOZ_COUNT_CTOR(nsStyleList);
|
||||||
|
@ -639,12 +586,9 @@ void nsStyleList::TriggerImageLoads(Document& aDocument,
|
||||||
const nsStyleList* aOldStyle) {
|
const nsStyleList* aOldStyle) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mListStyleImage.IsUrl() && !mListStyleImage.AsUrl().IsImageResolved()) {
|
if (mListStyleImage && !mListStyleImage->IsResolved()) {
|
||||||
auto* oldUrl = aOldStyle && aOldStyle->mListStyleImage.IsUrl()
|
mListStyleImage->Resolve(
|
||||||
? &aOldStyle->mListStyleImage.AsUrl()
|
aDocument, aOldStyle ? aOldStyle->mListStyleImage.get() : nullptr);
|
||||||
: nullptr;
|
|
||||||
const_cast<StyleComputedImageUrl&>(mListStyleImage.AsUrl())
|
|
||||||
.ResolveImage(aDocument, oldUrl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,7 +624,7 @@ nsChangeHint nsStyleList::CalcDifference(
|
||||||
}
|
}
|
||||||
// list-style-image and -moz-image-region may affect some XUL elements
|
// list-style-image and -moz-image-region may affect some XUL elements
|
||||||
// regardless of display value, so we still need to check them.
|
// regardless of display value, so we still need to check them.
|
||||||
if (mListStyleImage != aNewData.mListStyleImage) {
|
if (!DefinitelyEqualImages(mListStyleImage, aNewData.mListStyleImage)) {
|
||||||
return NS_STYLE_HINT_REFLOW;
|
return NS_STYLE_HINT_REFLOW;
|
||||||
}
|
}
|
||||||
if (mImageRegion != aNewData.mImageRegion) {
|
if (mImageRegion != aNewData.mImageRegion) {
|
||||||
|
@ -695,11 +639,11 @@ nsChangeHint nsStyleList::CalcDifference(
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIURI> nsStyleList::GetListStyleImageURI() const {
|
already_AddRefed<nsIURI> nsStyleList::GetListStyleImageURI() const {
|
||||||
if (!mListStyleImage.IsUrl()) {
|
if (!mListStyleImage) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri = mListStyleImage.AsUrl().GetURI();
|
nsCOMPtr<nsIURI> uri = mListStyleImage->GetImageURI();
|
||||||
return uri.forget();
|
return uri.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1578,6 +1522,154 @@ bool StyleGradient::IsOpaque() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// nsStyleImageRequest
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runnable to release the nsStyleImageRequest's mRequestProxy
|
||||||
|
* and mImageTracker on the main thread, and to perform
|
||||||
|
* any necessary unlocking and untracking of the image.
|
||||||
|
*/
|
||||||
|
class StyleImageRequestCleanupTask : public mozilla::Runnable {
|
||||||
|
public:
|
||||||
|
typedef nsStyleImageRequest::Mode Mode;
|
||||||
|
|
||||||
|
StyleImageRequestCleanupTask(Mode aModeFlags,
|
||||||
|
already_AddRefed<imgRequestProxy> aRequestProxy,
|
||||||
|
already_AddRefed<ImageTracker> aImageTracker)
|
||||||
|
: mozilla::Runnable("StyleImageRequestCleanupTask"),
|
||||||
|
mModeFlags(aModeFlags),
|
||||||
|
mRequestProxy(aRequestProxy),
|
||||||
|
mImageTracker(aImageTracker) {}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() final {
|
||||||
|
MOZ_ASSERT(!mRequestProxy || NS_IsMainThread(),
|
||||||
|
"If mRequestProxy is non-null, we need to run on main thread!");
|
||||||
|
|
||||||
|
if (!mRequestProxy) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mModeFlags & Mode::Track) {
|
||||||
|
MOZ_ASSERT(mImageTracker);
|
||||||
|
mImageTracker->Remove(mRequestProxy);
|
||||||
|
} else {
|
||||||
|
mRequestProxy->UnlockImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mModeFlags & Mode::Discard) {
|
||||||
|
mRequestProxy->RequestDiscard();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~StyleImageRequestCleanupTask() {
|
||||||
|
MOZ_ASSERT((!mRequestProxy && !mImageTracker) || NS_IsMainThread(),
|
||||||
|
"mRequestProxy and mImageTracker's destructor need to run "
|
||||||
|
"on the main thread!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mode mModeFlags;
|
||||||
|
// Since we always dispatch this runnable to the main thread, these will be
|
||||||
|
// released on the main thread when the runnable itself is released.
|
||||||
|
RefPtr<imgRequestProxy> mRequestProxy;
|
||||||
|
RefPtr<ImageTracker> mImageTracker;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsStyleImageRequest::nsStyleImageRequest(Mode aModeFlags,
|
||||||
|
const StyleComputedImageUrl& aImageURL)
|
||||||
|
: mImageURL(aImageURL), mModeFlags(aModeFlags), mResolved(false) {}
|
||||||
|
|
||||||
|
nsStyleImageRequest::~nsStyleImageRequest() {
|
||||||
|
// We may or may not be being destroyed on the main thread. To clean
|
||||||
|
// up, we must untrack and unlock the image (depending on mModeFlags),
|
||||||
|
// and release mRequestProxy and mImageTracker, all on the main thread.
|
||||||
|
{
|
||||||
|
RefPtr<StyleImageRequestCleanupTask> task =
|
||||||
|
new StyleImageRequestCleanupTask(mModeFlags, mRequestProxy.forget(),
|
||||||
|
mImageTracker.forget());
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
task->Run();
|
||||||
|
} else {
|
||||||
|
if (mDocGroup) {
|
||||||
|
mDocGroup->Dispatch(TaskCategory::Other, task.forget());
|
||||||
|
} else {
|
||||||
|
// if Resolve was not called at some point, mDocGroup is not set.
|
||||||
|
SystemGroup::Dispatch(TaskCategory::Other, task.forget());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mRequestProxy);
|
||||||
|
MOZ_ASSERT(!mImageTracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsStyleImageRequest::Resolve(Document& aDocument,
|
||||||
|
const nsStyleImageRequest* aOldImageRequest) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(!IsResolved(), "already resolved");
|
||||||
|
|
||||||
|
mResolved = true;
|
||||||
|
|
||||||
|
// TODO(emilio, bug 1440442): This is a hackaround to avoid flickering due the
|
||||||
|
// lack of non-http image caching in imagelib (bug 1406134), which causes
|
||||||
|
// stuff like bug 1439285. Cleanest fix if that doesn't get fixed is bug
|
||||||
|
// 1440305, but that seems too risky, and a lot of work to do before 60.
|
||||||
|
//
|
||||||
|
// Once that's fixed, the "old style" argument to TriggerImageLoads can go
|
||||||
|
// away.
|
||||||
|
if (nsContentUtils::IsChromeDoc(&aDocument) && aOldImageRequest &&
|
||||||
|
aOldImageRequest->IsResolved() && DefinitelyEquals(*aOldImageRequest)) {
|
||||||
|
MOZ_ASSERT(aOldImageRequest->mDocGroup == aDocument.GetDocGroup());
|
||||||
|
MOZ_ASSERT(mModeFlags == aOldImageRequest->mModeFlags);
|
||||||
|
|
||||||
|
mDocGroup = aOldImageRequest->mDocGroup;
|
||||||
|
mImageURL = aOldImageRequest->mImageURL;
|
||||||
|
|
||||||
|
mRequestProxy = aOldImageRequest->mRequestProxy;
|
||||||
|
} else {
|
||||||
|
mDocGroup = aDocument.GetDocGroup();
|
||||||
|
mRequestProxy = mImageURL.LoadImage(aDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mRequestProxy) {
|
||||||
|
// The URL resolution or image load failed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boost priority now that we know the image is present in the ComputedStyle
|
||||||
|
// of some frame.
|
||||||
|
mRequestProxy->BoostPriority(imgIRequest::CATEGORY_FRAME_STYLE);
|
||||||
|
|
||||||
|
if (mModeFlags & Mode::Track) {
|
||||||
|
mImageTracker = aDocument.ImageTracker();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeTrackAndLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsStyleImageRequest::MaybeTrackAndLock() {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(IsResolved());
|
||||||
|
MOZ_ASSERT(mRequestProxy);
|
||||||
|
|
||||||
|
if (mModeFlags & Mode::Track) {
|
||||||
|
MOZ_ASSERT(mImageTracker);
|
||||||
|
mImageTracker->Add(mRequestProxy);
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(!mImageTracker);
|
||||||
|
mRequestProxy->LockImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsStyleImageRequest::DefinitelyEquals(
|
||||||
|
const nsStyleImageRequest& aOther) const {
|
||||||
|
return mImageURL == aOther.mImageURL;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
// CachedBorderImageData
|
// CachedBorderImageData
|
||||||
//
|
//
|
||||||
|
@ -1628,7 +1720,8 @@ imgIContainer* CachedBorderImageData::GetSubImage(uint8_t aIndex) {
|
||||||
// nsStyleImage
|
// nsStyleImage
|
||||||
//
|
//
|
||||||
|
|
||||||
nsStyleImage::nsStyleImage() : mCropRect(nullptr), mType(eStyleImageType_Null) {
|
nsStyleImage::nsStyleImage()
|
||||||
|
: mType(eStyleImageType_Null), mImage(nullptr), mCropRect(nullptr) {
|
||||||
MOZ_COUNT_CTOR(nsStyleImage);
|
MOZ_COUNT_CTOR(nsStyleImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1640,7 +1733,7 @@ nsStyleImage::~nsStyleImage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
|
nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
|
||||||
: mCropRect(nullptr), mType(eStyleImageType_Null) {
|
: mType(eStyleImageType_Null), mCropRect(nullptr) {
|
||||||
// We need our own copy constructor because we don't want
|
// We need our own copy constructor because we don't want
|
||||||
// to copy the reference count
|
// to copy the reference count
|
||||||
MOZ_COUNT_CTOR(nsStyleImage);
|
MOZ_COUNT_CTOR(nsStyleImage);
|
||||||
|
@ -1659,7 +1752,7 @@ void nsStyleImage::DoCopy(const nsStyleImage& aOther) {
|
||||||
SetNull();
|
SetNull();
|
||||||
|
|
||||||
if (aOther.mType == eStyleImageType_Image) {
|
if (aOther.mType == eStyleImageType_Image) {
|
||||||
SetImageUrl(aOther.mImage);
|
SetImageRequest(do_AddRef(aOther.mImage));
|
||||||
} else if (aOther.mType == eStyleImageType_Gradient) {
|
} else if (aOther.mType == eStyleImageType_Gradient) {
|
||||||
SetGradientData(MakeUnique<StyleGradient>(*aOther.mGradient));
|
SetGradientData(MakeUnique<StyleGradient>(*aOther.mGradient));
|
||||||
} else if (aOther.mType == eStyleImageType_Element) {
|
} else if (aOther.mType == eStyleImageType_Element) {
|
||||||
|
@ -1678,7 +1771,7 @@ void nsStyleImage::SetNull() {
|
||||||
delete mGradient;
|
delete mGradient;
|
||||||
mGradient = nullptr;
|
mGradient = nullptr;
|
||||||
} else if (mType == eStyleImageType_Image) {
|
} else if (mType == eStyleImageType_Image) {
|
||||||
mImage.~StyleComputedImageUrl();
|
NS_RELEASE(mImage);
|
||||||
} else if (mType == eStyleImageType_Element) {
|
} else if (mType == eStyleImageType_Element) {
|
||||||
NS_RELEASE(mElementId);
|
NS_RELEASE(mElementId);
|
||||||
}
|
}
|
||||||
|
@ -1687,14 +1780,18 @@ void nsStyleImage::SetNull() {
|
||||||
mCropRect = nullptr;
|
mCropRect = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsStyleImage::SetImageUrl(const StyleComputedImageUrl& aImage) {
|
void nsStyleImage::SetImageRequest(
|
||||||
|
already_AddRefed<nsStyleImageRequest> aImage) {
|
||||||
|
RefPtr<nsStyleImageRequest> image = aImage;
|
||||||
|
|
||||||
if (mType != eStyleImageType_Null) {
|
if (mType != eStyleImageType_Null) {
|
||||||
SetNull();
|
SetNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
new (&mImage) StyleComputedImageUrl(aImage);
|
if (image) {
|
||||||
mType = eStyleImageType_Image;
|
mImage = image.forget().take();
|
||||||
|
mType = eStyleImageType_Image;
|
||||||
|
}
|
||||||
if (mCachedBIData) {
|
if (mCachedBIData) {
|
||||||
mCachedBIData->PurgeCachedImages();
|
mCachedBIData->PurgeCachedImages();
|
||||||
}
|
}
|
||||||
|
@ -1740,6 +1837,22 @@ static int32_t ConvertToPixelCoord(const StyleNumberOrPercentage& aCoord,
|
||||||
return NS_lround(pixelValue);
|
return NS_lround(pixelValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIURI> nsStyleImageRequest::GetImageURI() const {
|
||||||
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
|
||||||
|
if (mRequestProxy) {
|
||||||
|
mRequestProxy->GetURI(getter_AddRefs(uri));
|
||||||
|
if (uri) {
|
||||||
|
return uri.forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we had some problem resolving the mRequestProxy, use the URL stored
|
||||||
|
// in the mImageURL.
|
||||||
|
uri = mImageURL.GetURI();
|
||||||
|
return uri.forget();
|
||||||
|
}
|
||||||
|
|
||||||
bool nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
|
bool nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
|
||||||
bool* aIsEntireImage) const {
|
bool* aIsEntireImage) const {
|
||||||
MOZ_ASSERT(mType == eStyleImageType_Image,
|
MOZ_ASSERT(mType == eStyleImageType_Image,
|
||||||
|
@ -1896,7 +2009,7 @@ bool nsStyleImage::operator==(const nsStyleImage& aOther) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType == eStyleImageType_Image) {
|
if (mType == eStyleImageType_Image) {
|
||||||
return mImage == aOther.mImage;
|
return DefinitelyEqualImages(mImage, aOther.mImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType == eStyleImageType_Gradient) {
|
if (mType == eStyleImageType_Gradient) {
|
||||||
|
@ -1933,12 +2046,12 @@ already_AddRefed<nsIURI> nsStyleImage::GetImageURI() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri = mImage.GetURI();
|
nsCOMPtr<nsIURI> uri = mImage->GetImageURI();
|
||||||
return uri.forget();
|
return uri.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyleComputedImageUrl* nsStyleImage::GetURLValue() const {
|
const StyleComputedImageUrl* nsStyleImage::GetURLValue() const {
|
||||||
return mType == eStyleImageType_Image ? &mImage : nullptr;
|
return mType == eStyleImageType_Image ? &mImage->GetImageValue() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
|
@ -3140,35 +3253,6 @@ nsChangeHint nsStyleContent::CalcDifference(
|
||||||
return nsChangeHint(0);
|
return nsChangeHint(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsStyleContent::TriggerImageLoads(Document& aDoc,
|
|
||||||
const nsStyleContent* aOld) {
|
|
||||||
if (!mContent.IsItems()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Span<const StyleContentItem> oldItems;
|
|
||||||
if (aOld && aOld->mContent.IsItems()) {
|
|
||||||
oldItems = aOld->mContent.AsItems().AsSpan();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto items = mContent.AsItems().AsSpan();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < items.Length(); ++i) {
|
|
||||||
auto& item = items[i];
|
|
||||||
if (!item.IsUrl()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto& url = item.AsUrl();
|
|
||||||
if (url.IsImageResolved()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto* oldUrl = i < oldItems.Length() && oldItems[i].IsUrl()
|
|
||||||
? &oldItems[i].AsUrl()
|
|
||||||
: nullptr;
|
|
||||||
const_cast<StyleComputedImageUrl&>(url).ResolveImage(aDoc, oldUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
// nsStyleTextReset
|
// nsStyleTextReset
|
||||||
//
|
//
|
||||||
|
@ -3417,8 +3501,8 @@ LogicalSide nsStyleText::TextEmphasisSide(WritingMode aWM) const {
|
||||||
// nsStyleUI
|
// nsStyleUI
|
||||||
//
|
//
|
||||||
|
|
||||||
nsCursorImage::nsCursorImage(const StyleComputedImageUrl& aImage)
|
nsCursorImage::nsCursorImage()
|
||||||
: mHaveHotspot(false), mHotspotX(0.0f), mHotspotY(0.0f), mImage(aImage) {}
|
: mHaveHotspot(false), mHotspotX(0.0f), mHotspotY(0.0f) {}
|
||||||
|
|
||||||
nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
|
nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
|
||||||
: mHaveHotspot(aOther.mHaveHotspot),
|
: mHaveHotspot(aOther.mHaveHotspot),
|
||||||
|
@ -3444,7 +3528,8 @@ bool nsCursorImage::operator==(const nsCursorImage& aOther) const {
|
||||||
aOther.mHaveHotspot || (aOther.mHotspotX == 0 && aOther.mHotspotY == 0),
|
aOther.mHaveHotspot || (aOther.mHotspotX == 0 && aOther.mHotspotY == 0),
|
||||||
"expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
|
"expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
|
||||||
return mHaveHotspot == aOther.mHaveHotspot && mHotspotX == aOther.mHotspotX &&
|
return mHaveHotspot == aOther.mHaveHotspot && mHotspotX == aOther.mHotspotX &&
|
||||||
mHotspotY == aOther.mHotspotY && mImage == aOther.mImage;
|
mHotspotY == aOther.mHotspotY &&
|
||||||
|
DefinitelyEqualImages(mImage, aOther.mImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsStyleUI::nsStyleUI(const Document& aDocument)
|
nsStyleUI::nsStyleUI(const Document& aDocument)
|
||||||
|
@ -3479,13 +3564,13 @@ void nsStyleUI::TriggerImageLoads(Document& aDocument,
|
||||||
for (size_t i = 0; i < mCursorImages.Length(); ++i) {
|
for (size_t i = 0; i < mCursorImages.Length(); ++i) {
|
||||||
nsCursorImage& cursor = mCursorImages[i];
|
nsCursorImage& cursor = mCursorImages[i];
|
||||||
|
|
||||||
if (!cursor.mImage.IsImageResolved()) {
|
if (cursor.mImage && !cursor.mImage->IsResolved()) {
|
||||||
const nsCursorImage* oldCursor =
|
const nsCursorImage* oldCursor =
|
||||||
(aOldStyle && aOldStyle->mCursorImages.Length() > i)
|
(aOldStyle && aOldStyle->mCursorImages.Length() > i)
|
||||||
? &aOldStyle->mCursorImages[i]
|
? &aOldStyle->mCursorImages[i]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
cursor.mImage.ResolveImage(aDocument,
|
cursor.mImage->Resolve(aDocument,
|
||||||
oldCursor ? &oldCursor->mImage : nullptr);
|
oldCursor ? oldCursor->mImage.get() : nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,96 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont {
|
||||||
RefPtr<nsAtom> mLanguage;
|
RefPtr<nsAtom> mLanguage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for an imgRequestProxy that supports off-main-thread creation
|
||||||
|
* and equality comparison.
|
||||||
|
*
|
||||||
|
* An nsStyleImageRequest can be created using the constructor that takes the
|
||||||
|
* URL, base URI, referrer and principal that can be used to initiate an image
|
||||||
|
* load and produce an imgRequestProxy later.
|
||||||
|
*
|
||||||
|
* This can be called from any thread. The nsStyleImageRequest is not
|
||||||
|
* considered "resolved" at this point, and the Resolve() method must be called
|
||||||
|
* later to initiate the image load and make calls to get() valid.
|
||||||
|
*
|
||||||
|
* Calls to TrackImage(), UntrackImage(), LockImage(), UnlockImage() and
|
||||||
|
* RequestDiscard() are made to the imgRequestProxy and ImageTracker as
|
||||||
|
* appropriate, according to the mode flags passed in to the constructor.
|
||||||
|
*
|
||||||
|
* The constructor receives a css::URLValue to represent the url()
|
||||||
|
* information, which is held on to for the comparisons done in
|
||||||
|
* DefinitelyEquals().
|
||||||
|
*/
|
||||||
|
class nsStyleImageRequest {
|
||||||
|
public:
|
||||||
|
// Flags describing whether the imgRequestProxy must be tracked in the
|
||||||
|
// ImageTracker, whether LockImage/UnlockImage calls will be made
|
||||||
|
// when obtaining and releasing the imgRequestProxy, and whether
|
||||||
|
// RequestDiscard will be called on release.
|
||||||
|
enum class Mode : uint8_t {
|
||||||
|
// The imgRequestProxy will be added to the ImageTracker when resolved
|
||||||
|
// Without this flag, the nsStyleImageRequest itself will call LockImage/
|
||||||
|
// UnlockImage on the imgRequestProxy, rather than leaving locking to the
|
||||||
|
// ImageTracker to manage.
|
||||||
|
//
|
||||||
|
// This flag is currently used by all nsStyleImageRequests except
|
||||||
|
// those for list-style-image and cursor.
|
||||||
|
Track = 0x1,
|
||||||
|
|
||||||
|
// The imgRequestProxy will have its RequestDiscard method called when
|
||||||
|
// the nsStyleImageRequest is going away.
|
||||||
|
//
|
||||||
|
// This is currently used only for cursor images.
|
||||||
|
Discard = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Can be called from any thread, but Resolve() must be called later
|
||||||
|
// on the main thread before get() can be used.
|
||||||
|
nsStyleImageRequest(Mode aModeFlags, const mozilla::StyleComputedImageUrl&);
|
||||||
|
|
||||||
|
void Resolve(mozilla::dom::Document&,
|
||||||
|
const nsStyleImageRequest* aOldImageRequest);
|
||||||
|
bool IsResolved() const { return mResolved; }
|
||||||
|
|
||||||
|
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 URLValue objects in the two nsStyleImageRequests
|
||||||
|
// return true from URLValue::DefinitelyEqualURIs.
|
||||||
|
bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
|
||||||
|
|
||||||
|
const mozilla::StyleComputedImageUrl& GetImageValue() const {
|
||||||
|
return mImageURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIURI> GetImageURI() const;
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleImageRequest);
|
||||||
|
|
||||||
|
private:
|
||||||
|
~nsStyleImageRequest();
|
||||||
|
nsStyleImageRequest& operator=(const nsStyleImageRequest& aOther) = delete;
|
||||||
|
|
||||||
|
void MaybeTrackAndLock();
|
||||||
|
|
||||||
|
RefPtr<imgRequestProxy> mRequestProxy;
|
||||||
|
mozilla::StyleComputedImageUrl mImageURL;
|
||||||
|
RefPtr<mozilla::dom::ImageTracker> mImageTracker;
|
||||||
|
|
||||||
|
// Cache DocGroup for dispatching events in the destructor.
|
||||||
|
RefPtr<mozilla::dom::DocGroup> mDocGroup;
|
||||||
|
|
||||||
|
Mode mModeFlags;
|
||||||
|
bool mResolved;
|
||||||
|
};
|
||||||
|
|
||||||
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsStyleImageRequest::Mode)
|
||||||
|
|
||||||
enum nsStyleImageType {
|
enum nsStyleImageType {
|
||||||
eStyleImageType_Null,
|
eStyleImageType_Null,
|
||||||
eStyleImageType_Image,
|
eStyleImageType_Image,
|
||||||
|
@ -178,34 +268,36 @@ struct nsStyleImage {
|
||||||
nsStyleImage& operator=(const nsStyleImage& aOther);
|
nsStyleImage& operator=(const nsStyleImage& aOther);
|
||||||
|
|
||||||
void SetNull();
|
void SetNull();
|
||||||
void SetImageUrl(const mozilla::StyleComputedImageUrl&);
|
void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
|
||||||
void SetGradientData(mozilla::UniquePtr<mozilla::StyleGradient>);
|
void SetGradientData(mozilla::UniquePtr<mozilla::StyleGradient>);
|
||||||
void SetElementId(already_AddRefed<nsAtom> aElementId);
|
void SetElementId(already_AddRefed<nsAtom> aElementId);
|
||||||
void SetCropRect(mozilla::UniquePtr<CropRect> aCropRect);
|
void SetCropRect(mozilla::UniquePtr<CropRect> aCropRect);
|
||||||
|
|
||||||
void ResolveImage(mozilla::dom::Document& aDocument,
|
void ResolveImage(mozilla::dom::Document& aDocument,
|
||||||
const nsStyleImage* aOldImage) {
|
const nsStyleImage* aOldImage) {
|
||||||
if (mType == eStyleImageType_Image && !mImage.IsImageResolved()) {
|
MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
|
||||||
const auto* oldRequest =
|
if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
|
||||||
|
const nsStyleImageRequest* oldRequest =
|
||||||
(aOldImage && aOldImage->GetType() == eStyleImageType_Image)
|
(aOldImage && aOldImage->GetType() == eStyleImageType_Image)
|
||||||
? &aOldImage->ImageUrl()
|
? aOldImage->ImageRequest()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
mImage.ResolveImage(aDocument, oldRequest);
|
mImage->Resolve(aDocument, oldRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsStyleImageType GetType() const { return mType; }
|
nsStyleImageType GetType() const { return mType; }
|
||||||
const mozilla::StyleComputedImageUrl& ImageUrl() const {
|
nsStyleImageRequest* ImageRequest() const {
|
||||||
MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
|
MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
|
||||||
|
MOZ_ASSERT(mImage);
|
||||||
return mImage;
|
return mImage;
|
||||||
}
|
}
|
||||||
imgRequestProxy* GetImageData() const { return ImageUrl().GetImage(); }
|
imgRequestProxy* GetImageData() const { return ImageRequest()->get(); }
|
||||||
const mozilla::StyleGradient& GetGradient() const {
|
const mozilla::StyleGradient& GetGradient() const {
|
||||||
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
|
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
|
||||||
return *mGradient;
|
return *mGradient;
|
||||||
}
|
}
|
||||||
bool IsResolved() const {
|
bool IsResolved() const {
|
||||||
return mType != eStyleImageType_Image || ImageUrl().IsImageResolved();
|
return mType != eStyleImageType_Image || ImageRequest()->IsResolved();
|
||||||
}
|
}
|
||||||
const nsAtom* GetElementId() const {
|
const nsAtom* GetElementId() const {
|
||||||
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
|
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
|
||||||
|
@ -299,15 +391,15 @@ struct nsStyleImage {
|
||||||
// allocated since it is only used in border image case.
|
// allocated since it is only used in border image case.
|
||||||
mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
|
mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
|
||||||
|
|
||||||
// This is _currently_ used only in conjunction with eStyleImageType_Image.
|
|
||||||
mozilla::UniquePtr<CropRect> mCropRect;
|
|
||||||
|
|
||||||
nsStyleImageType mType;
|
nsStyleImageType mType;
|
||||||
union {
|
union {
|
||||||
mozilla::StyleComputedImageUrl mImage;
|
nsStyleImageRequest* mImage;
|
||||||
mozilla::StyleGradient* mGradient;
|
mozilla::StyleGradient* mGradient;
|
||||||
nsAtom* mElementId;
|
nsAtom* mElementId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This is _currently_ used only in conjunction with eStyleImageType_Image.
|
||||||
|
mozilla::UniquePtr<CropRect> mCropRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nsStyleImageLayers {
|
struct nsStyleImageLayers {
|
||||||
|
@ -828,10 +920,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList {
|
||||||
nsStyleList(const nsStyleList& aStyleList);
|
nsStyleList(const nsStyleList& aStyleList);
|
||||||
~nsStyleList();
|
~nsStyleList();
|
||||||
|
|
||||||
private:
|
|
||||||
nsStyleList& operator=(const nsStyleList& aOther) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void TriggerImageLoads(mozilla::dom::Document&, const nsStyleList*);
|
void TriggerImageLoads(mozilla::dom::Document&, const nsStyleList*);
|
||||||
static constexpr bool kHasTriggerImageLoads = true;
|
static constexpr bool kHasTriggerImageLoads = true;
|
||||||
|
|
||||||
|
@ -839,8 +927,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList {
|
||||||
const nsStyleDisplay& aOldDisplay) const;
|
const nsStyleDisplay& aOldDisplay) const;
|
||||||
|
|
||||||
imgRequestProxy* GetListStyleImage() const {
|
imgRequestProxy* GetListStyleImage() const {
|
||||||
return mListStyleImage.IsUrl() ? mListStyleImage.AsUrl().GetImage()
|
return mListStyleImage ? mListStyleImage->get() : nullptr;
|
||||||
: nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect GetImageRegion() const {
|
nsRect GetImageRegion() const {
|
||||||
|
@ -853,15 +940,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList {
|
||||||
already_AddRefed<nsIURI> GetListStyleImageURI() const;
|
already_AddRefed<nsIURI> GetListStyleImageURI() const;
|
||||||
|
|
||||||
uint8_t mListStylePosition;
|
uint8_t mListStylePosition;
|
||||||
|
RefPtr<nsStyleImageRequest> mListStyleImage;
|
||||||
|
|
||||||
mozilla::CounterStylePtr mCounterStyle;
|
mozilla::CounterStylePtr mCounterStyle;
|
||||||
mozilla::StyleQuotes mQuotes;
|
|
||||||
mozilla::StyleImageUrlOrNone mListStyleImage;
|
|
||||||
|
|
||||||
// the rect to use within an image.
|
private:
|
||||||
mozilla::StyleClipRectOrAuto mImageRegion;
|
nsStyleList& operator=(const nsStyleList& aOther) = delete;
|
||||||
// true in an <ol reversed> scope.
|
|
||||||
mozilla::StyleMozListReversed mMozListReversed;
|
public:
|
||||||
|
mozilla::StyleQuotes mQuotes;
|
||||||
|
mozilla::StyleClipRectOrAuto mImageRegion; // the rect to use within an image
|
||||||
|
mozilla::StyleMozListReversed
|
||||||
|
mMozListReversed; // true in an <ol reversed> scope
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
|
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
|
||||||
|
@ -1829,9 +1919,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent {
|
||||||
explicit nsStyleContent(const mozilla::dom::Document&);
|
explicit nsStyleContent(const mozilla::dom::Document&);
|
||||||
nsStyleContent(const nsStyleContent& aContent);
|
nsStyleContent(const nsStyleContent& aContent);
|
||||||
~nsStyleContent();
|
~nsStyleContent();
|
||||||
|
static constexpr bool kHasTriggerImageLoads = false;
|
||||||
void TriggerImageLoads(mozilla::dom::Document&, const nsStyleContent*);
|
|
||||||
static constexpr bool kHasTriggerImageLoads = true;
|
|
||||||
|
|
||||||
size_t ContentCount() const {
|
size_t ContentCount() const {
|
||||||
return mContent.IsItems() ? mContent.AsItems().Length() : 0;
|
return mContent.IsItems() ? mContent.AsItems().Length() : 0;
|
||||||
|
@ -1871,10 +1959,10 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset {
|
||||||
struct nsCursorImage {
|
struct nsCursorImage {
|
||||||
bool mHaveHotspot;
|
bool mHaveHotspot;
|
||||||
float mHotspotX, mHotspotY;
|
float mHotspotX, mHotspotY;
|
||||||
mozilla::StyleComputedImageUrl mImage;
|
RefPtr<nsStyleImageRequest> mImage;
|
||||||
|
|
||||||
explicit nsCursorImage(const mozilla::StyleComputedImageUrl&);
|
nsCursorImage();
|
||||||
nsCursorImage(const nsCursorImage&);
|
nsCursorImage(const nsCursorImage& aOther);
|
||||||
|
|
||||||
nsCursorImage& operator=(const nsCursorImage& aOther);
|
nsCursorImage& operator=(const nsCursorImage& aOther);
|
||||||
|
|
||||||
|
@ -1883,7 +1971,7 @@ struct nsCursorImage {
|
||||||
return !(*this == aOther);
|
return !(*this == aOther);
|
||||||
}
|
}
|
||||||
|
|
||||||
imgRequestProxy* GetImage() const { return mImage.GetImage(); }
|
imgRequestProxy* GetImage() const { return mImage->get(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUI {
|
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUI {
|
||||||
|
|
|
@ -876,16 +876,17 @@ void SVGMaskObserverList::ResolveImage(uint32_t aIndex) {
|
||||||
const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
|
const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
|
||||||
MOZ_ASSERT(aIndex < svgReset->mMask.mImageCount);
|
MOZ_ASSERT(aIndex < svgReset->mMask.mImageCount);
|
||||||
|
|
||||||
auto& image =
|
nsStyleImage& image =
|
||||||
const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
|
const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
|
||||||
|
|
||||||
if (!image.IsResolved()) {
|
if (!image.IsResolved()) {
|
||||||
MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
|
MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
|
||||||
image.ResolveImage(*mFrame->PresContext()->Document(), nullptr);
|
image.ResolveImage(*mFrame->PresContext()->Document(), nullptr);
|
||||||
|
|
||||||
Document* doc = mFrame->PresContext()->Document();
|
mozilla::css::ImageLoader* imageLoader =
|
||||||
|
mFrame->PresContext()->Document()->StyleImageLoader();
|
||||||
if (imgRequestProxy* req = image.GetImageData()) {
|
if (imgRequestProxy* req = image.GetImageData()) {
|
||||||
doc->StyleImageLoader()->AssociateRequestToFrame(req, mFrame, 0);
|
imageLoader->AssociateRequestToFrame(req, mFrame, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use crate::gecko_bindings::structs::{self, Matrix4x4Components};
|
||||||
use crate::gecko_bindings::structs::{nsStyleImage, nsresult};
|
use crate::gecko_bindings::structs::{nsStyleImage, nsresult};
|
||||||
use crate::stylesheets::RulesMutateError;
|
use crate::stylesheets::RulesMutateError;
|
||||||
use crate::values::computed::transform::Matrix3D;
|
use crate::values::computed::transform::Matrix3D;
|
||||||
|
use crate::values::computed::url::ComputedImageUrl;
|
||||||
use crate::values::computed::{Gradient, Image, TextAlign};
|
use crate::values::computed::{Gradient, Image, TextAlign};
|
||||||
use crate::values::generics::image::GenericImage;
|
use crate::values::generics::image::GenericImage;
|
||||||
use crate::values::generics::rect::Rect;
|
use crate::values::generics::rect::Rect;
|
||||||
|
@ -62,7 +63,7 @@ impl nsStyleImage {
|
||||||
match self.mType {
|
match self.mType {
|
||||||
nsStyleImageType::eStyleImageType_Null => None,
|
nsStyleImageType::eStyleImageType_Null => None,
|
||||||
nsStyleImageType::eStyleImageType_Image => {
|
nsStyleImageType::eStyleImageType_Image => {
|
||||||
let url = self.__bindgen_anon_1.mImage.as_ref().clone();
|
let url = self.get_image_url();
|
||||||
if self.mCropRect.mPtr.is_null() {
|
if self.mCropRect.mPtr.is_null() {
|
||||||
Some(GenericImage::Url(url))
|
Some(GenericImage::Url(url))
|
||||||
} else {
|
} else {
|
||||||
|
@ -87,6 +88,13 @@ impl nsStyleImage {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn get_image_url(&self) -> ComputedImageUrl {
|
||||||
|
let image_request = bindings::Gecko_GetImageRequest(self)
|
||||||
|
.as_ref()
|
||||||
|
.expect("Null image request?");
|
||||||
|
ComputedImageUrl::from_image_request(image_request)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod basic_shape {
|
pub mod basic_shape {
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
use crate::gecko_bindings::bindings;
|
use crate::gecko_bindings::bindings;
|
||||||
use crate::gecko_bindings::structs;
|
use crate::gecko_bindings::structs;
|
||||||
|
use crate::gecko_bindings::structs::nsStyleImageRequest;
|
||||||
|
use crate::gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::stylesheets::{CorsMode, UrlExtraData};
|
use crate::stylesheets::{CorsMode, UrlExtraData};
|
||||||
use crate::values::computed::{Context, ToComputedValue};
|
use crate::values::computed::{Context, ToComputedValue};
|
||||||
|
@ -148,52 +150,31 @@ struct LoadDataKey(*const LoadDataSource);
|
||||||
unsafe impl Sync for LoadDataKey {}
|
unsafe impl Sync for LoadDataKey {}
|
||||||
unsafe impl Send for LoadDataKey {}
|
unsafe impl Send for LoadDataKey {}
|
||||||
|
|
||||||
bitflags! {
|
/// The load data for a given URL. This is mutable from C++, for now at least.
|
||||||
/// Various bits of mutable state that are kept for image loads.
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct LoadDataFlags: u8 {
|
|
||||||
/// Whether we tried to resolve the uri at least once.
|
|
||||||
const TRIED_TO_RESOLVE_URI = 1 << 0;
|
|
||||||
/// Whether we tried to resolve the image at least once.
|
|
||||||
const TRIED_TO_RESOLVE_IMAGE = 1 << 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is usable and movable from multiple threads just fine, as long as it's
|
|
||||||
/// not cloned (it is not clonable), and the methods that mutate it run only on
|
|
||||||
/// the main thread (when all the other threads we care about are paused).
|
|
||||||
unsafe impl Sync for LoadData {}
|
|
||||||
unsafe impl Send for LoadData {}
|
|
||||||
|
|
||||||
/// The load data for a given URL. This is mutable from C++, and shouldn't be
|
|
||||||
/// accessed from rust for anything.
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LoadData {
|
pub struct LoadData {
|
||||||
/// A strong reference to the imgRequestProxy, if any, that should be
|
resolved: RefPtr<structs::nsIURI>,
|
||||||
/// released on drop.
|
load_id: u64,
|
||||||
///
|
tried_to_resolve: bool,
|
||||||
/// These are raw pointers because they are not safe to reference-count off
|
|
||||||
/// the main thread.
|
|
||||||
resolved_image: *mut structs::imgRequestProxy,
|
|
||||||
/// A strong reference to the resolved URI of this image.
|
|
||||||
resolved_uri: *mut structs::nsIURI,
|
|
||||||
/// A few flags that are set when resolving the image or such.
|
|
||||||
flags: LoadDataFlags,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for LoadData {
|
impl Drop for LoadData {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { bindings::Gecko_LoadData_Drop(self) }
|
if self.load_id != 0 {
|
||||||
|
unsafe {
|
||||||
|
bindings::Gecko_LoadData_DeregisterLoad(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LoadData {
|
impl Default for LoadData {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
resolved_image: std::ptr::null_mut(),
|
resolved: RefPtr::null(),
|
||||||
resolved_uri: std::ptr::null_mut(),
|
load_id: 0,
|
||||||
flags: LoadDataFlags::empty(),
|
tried_to_resolve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,6 +342,13 @@ impl ToCss for ComputedUrl {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct ComputedImageUrl(pub ComputedUrl);
|
pub struct ComputedImageUrl(pub ComputedUrl);
|
||||||
|
|
||||||
|
impl ComputedImageUrl {
|
||||||
|
/// Convert from nsStyleImageRequest to ComputedImageUrl.
|
||||||
|
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
|
||||||
|
image_request.mImageURL.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for ComputedImageUrl {
|
impl ToCss for ComputedImageUrl {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
|
|
|
@ -25,9 +25,14 @@ use crate::gecko_bindings::bindings::Gecko_CopyCounterStyle;
|
||||||
use crate::gecko_bindings::bindings::Gecko_CopyCursorArrayFrom;
|
use crate::gecko_bindings::bindings::Gecko_CopyCursorArrayFrom;
|
||||||
use crate::gecko_bindings::bindings::Gecko_CopyFontFamilyFrom;
|
use crate::gecko_bindings::bindings::Gecko_CopyFontFamilyFrom;
|
||||||
use crate::gecko_bindings::bindings::Gecko_CopyImageValueFrom;
|
use crate::gecko_bindings::bindings::Gecko_CopyImageValueFrom;
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_CopyListStyleImageFrom;
|
||||||
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
|
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_SetCursorArrayLength;
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_SetCursorImageValue;
|
||||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
|
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
|
||||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
|
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_SetListStyleImageNone;
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_SetListStyleImageImageValue;
|
||||||
use crate::gecko_bindings::bindings::Gecko_SetNullImageValue;
|
use crate::gecko_bindings::bindings::Gecko_SetNullImageValue;
|
||||||
use crate::gecko_bindings::structs;
|
use crate::gecko_bindings::structs;
|
||||||
use crate::gecko_bindings::structs::nsCSSPropertyID;
|
use crate::gecko_bindings::structs::nsCSSPropertyID;
|
||||||
|
@ -48,6 +53,7 @@ use crate::values::computed::BorderStyle;
|
||||||
use crate::values::computed::font::FontSize;
|
use crate::values::computed::font::FontSize;
|
||||||
use crate::values::generics::column::ColumnCount;
|
use crate::values::generics::column::ColumnCount;
|
||||||
use crate::values::generics::image::ImageLayer;
|
use crate::values::generics::image::ImageLayer;
|
||||||
|
use crate::values::generics::url::UrlOrNone;
|
||||||
|
|
||||||
|
|
||||||
pub mod style_structs {
|
pub mod style_structs {
|
||||||
|
@ -2102,7 +2108,43 @@ fn static_assert() {
|
||||||
<% impl_simple_image_array_property("blend_mode", "background", "mImage", "mBlendMode", "Background") %>
|
<% impl_simple_image_array_property("blend_mode", "background", "mImage", "mBlendMode", "Background") %>
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="List" skip_longhands="list-style-type">
|
<%self:impl_trait style_struct_name="List"
|
||||||
|
skip_longhands="list-style-image list-style-type">
|
||||||
|
|
||||||
|
pub fn set_list_style_image(&mut self, image: longhands::list_style_image::computed_value::T) {
|
||||||
|
match image {
|
||||||
|
UrlOrNone::None => {
|
||||||
|
unsafe {
|
||||||
|
Gecko_SetListStyleImageNone(&mut *self.gecko);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UrlOrNone::Url(ref url) => {
|
||||||
|
unsafe {
|
||||||
|
Gecko_SetListStyleImageImageValue(&mut *self.gecko, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_list_style_image_from(&mut self, other: &Self) {
|
||||||
|
unsafe { Gecko_CopyListStyleImageFrom(&mut *self.gecko, &*other.gecko); }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_list_style_image(&mut self, other: &Self) {
|
||||||
|
self.copy_list_style_image_from(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_list_style_image(&self) -> longhands::list_style_image::computed_value::T {
|
||||||
|
if self.gecko.mListStyleImage.mRawPtr.is_null() {
|
||||||
|
return UrlOrNone::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ref gecko_image_request = *self.gecko.mListStyleImage.mRawPtr;
|
||||||
|
UrlOrNone::Url(ComputedImageUrl::from_image_request(gecko_image_request))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
|
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
|
||||||
use nsstring::{nsACString, nsCStr};
|
use nsstring::{nsACString, nsCStr};
|
||||||
use self::longhands::list_style_type::computed_value::T;
|
use self::longhands::list_style_type::computed_value::T;
|
||||||
|
@ -2391,11 +2433,14 @@ clip-path
|
||||||
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
|
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
|
||||||
self.gecko.mCursor = v.keyword;
|
self.gecko.mCursor = v.keyword;
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_SetCursorArrayCapacity(&mut *self.gecko, v.images.len());
|
Gecko_SetCursorArrayLength(&mut *self.gecko, v.images.len());
|
||||||
}
|
}
|
||||||
for i in 0..v.images.len() {
|
for i in 0..v.images.len() {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_AppendCursorImage(&mut *self.gecko, &v.images[i].url);
|
Gecko_SetCursorImageValue(
|
||||||
|
&mut self.gecko.mCursorImages[i],
|
||||||
|
&v.images[i].url
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
match v.images[i].hotspot {
|
match v.images[i].hotspot {
|
||||||
|
@ -2428,7 +2473,10 @@ clip-path
|
||||||
let keyword = self.gecko.mCursor;
|
let keyword = self.gecko.mCursor;
|
||||||
|
|
||||||
let images = self.gecko.mCursorImages.iter().map(|gecko_cursor_image| {
|
let images = self.gecko.mCursorImages.iter().map(|gecko_cursor_image| {
|
||||||
let url = gecko_cursor_image.mImage.clone();
|
let url = unsafe {
|
||||||
|
let gecko_image_request = gecko_cursor_image.mImage.mRawPtr.as_ref().unwrap();
|
||||||
|
ComputedImageUrl::from_image_request(&gecko_image_request)
|
||||||
|
};
|
||||||
|
|
||||||
let hotspot =
|
let hotspot =
|
||||||
if gecko_cursor_image.mHaveHotspot {
|
if gecko_cursor_image.mHaveHotspot {
|
||||||
|
|
|
@ -170,7 +170,6 @@ include = [
|
||||||
"ComputedUrl",
|
"ComputedUrl",
|
||||||
"ComputedImageUrl",
|
"ComputedImageUrl",
|
||||||
"UrlOrNone",
|
"UrlOrNone",
|
||||||
"ImageUrlOrNone",
|
|
||||||
"Filter",
|
"Filter",
|
||||||
"Gradient",
|
"Gradient",
|
||||||
"GridTemplateAreas",
|
"GridTemplateAreas",
|
||||||
|
@ -207,7 +206,6 @@ renaming_overrides_prefixing = true
|
||||||
"nscolor" = "nscolor"
|
"nscolor" = "nscolor"
|
||||||
"nsAtom" = "nsAtom"
|
"nsAtom" = "nsAtom"
|
||||||
"nsIURI" = "nsIURI"
|
"nsIURI" = "nsIURI"
|
||||||
"imgRequestProxy" = "imgRequestProxy"
|
|
||||||
"nsCompatibility" = "nsCompatibility"
|
"nsCompatibility" = "nsCompatibility"
|
||||||
"SharedFontList" = "SharedFontList"
|
"SharedFontList" = "SharedFontList"
|
||||||
"nsSimpleContentList" = "nsSimpleContentList"
|
"nsSimpleContentList" = "nsSimpleContentList"
|
||||||
|
@ -653,11 +651,7 @@ renaming_overrides_prefixing = true
|
||||||
inline StyleCorsMode CorsMode() const;
|
inline StyleCorsMode CorsMode() const;
|
||||||
already_AddRefed<nsIURI> ResolveLocalRef(nsIURI* aBase) const;
|
already_AddRefed<nsIURI> ResolveLocalRef(nsIURI* aBase) const;
|
||||||
already_AddRefed<nsIURI> ResolveLocalRef(const nsIContent* aContent) const;
|
already_AddRefed<nsIURI> ResolveLocalRef(const nsIContent* aContent) const;
|
||||||
|
already_AddRefed<imgRequestProxy> LoadImage(mozilla::dom::Document&);
|
||||||
// Only relevant for images.
|
|
||||||
inline bool IsImageResolved() const;
|
|
||||||
inline imgRequestProxy* GetImage() const;
|
|
||||||
void ResolveImage(dom::Document&, const StyleComputedUrl* aOldImage);
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"GenericGradient" = """
|
"GenericGradient" = """
|
||||||
|
|
Загрузка…
Ссылка в новой задаче