mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Load background images from style instead of from painting. This makes us
start loading the background images when we resolve style on an object that needs them instead of when we scroll down and see it for the first time. Bug 57607, r=pavlov, sr=dbaron
This commit is contained in:
parent
401ebf9a1a
commit
134fed8856
@ -59,6 +59,9 @@ class nsIThreadJSContextStack;
|
||||
class nsIParserService;
|
||||
class nsIIOService;
|
||||
class nsIURI;
|
||||
class imgIDecoderObserver;
|
||||
class imgIRequest;
|
||||
class imgILoader;
|
||||
|
||||
class nsContentUtils
|
||||
{
|
||||
@ -290,6 +293,33 @@ public:
|
||||
nsIDocument** aDocument,
|
||||
nsIPrincipal** aPrincipal);
|
||||
|
||||
/**
|
||||
* Method to do security and content policy checks on the image URI
|
||||
*
|
||||
* @param aURI uri of the image to be loaded
|
||||
* @param aContext the context the image is loaded in (eg an element)
|
||||
* @param aLoadingDocument the document we belong to
|
||||
* @throws NS_ERROR_IMAGE_BLOCKED if the load is blocked. This is
|
||||
* subject to change. See nsIContentPolicy.
|
||||
*/
|
||||
static nsresult CanLoadImage(nsIURI* aURI,
|
||||
nsISupports* aContext,
|
||||
nsIDocument* aLoadingDocument);
|
||||
/**
|
||||
* Method to start an image load. This does not do any security checks.
|
||||
*
|
||||
* @param aURI uri of the image to be loaded
|
||||
* @param aLoadingDocument the document we belong to
|
||||
* @param aObserver the observer for the image load
|
||||
* @param aLoadFlags the load flags to use. See nsIRequest
|
||||
* @return the imgIRequest for the image load
|
||||
*/
|
||||
static nsresult LoadImage(nsIURI* aURI,
|
||||
nsIDocument* aLoadingDocument,
|
||||
imgIDecoderObserver* aObserver,
|
||||
PRInt32 aLoadFlags,
|
||||
imgIRequest** aRequest);
|
||||
|
||||
private:
|
||||
static nsresult doReparentContentWrapper(nsIContent *aChild,
|
||||
nsIDocument *aNewDocument,
|
||||
@ -312,6 +342,8 @@ private:
|
||||
|
||||
static nsIIOService *sIOService;
|
||||
|
||||
static imgILoader* sImgLoader;
|
||||
|
||||
static PRBool sInitialized;
|
||||
};
|
||||
|
||||
|
@ -78,6 +78,11 @@
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "imgIDecoderObserver.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "imgILoader.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
|
||||
static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
|
||||
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
|
||||
@ -89,6 +94,7 @@ nsIThreadJSContextStack *nsContentUtils::sThreadJSContextStack = nsnull;
|
||||
nsIParserService *nsContentUtils::sParserService = nsnull;
|
||||
nsINameSpaceManager *nsContentUtils::sNameSpaceManager = nsnull;
|
||||
nsIIOService *nsContentUtils::sIOService = nsnull;
|
||||
imgILoader *nsContentUtils::sImgLoader = nsnull;
|
||||
|
||||
PRBool nsContentUtils::sInitialized = PR_FALSE;
|
||||
|
||||
@ -132,6 +138,13 @@ nsContentUtils::Init()
|
||||
sIOService = nsnull;
|
||||
}
|
||||
|
||||
// Ignore failure and just don't load images
|
||||
rv = CallGetService("@mozilla.org/image/loader;1", &sImgLoader);
|
||||
if (NS_FAILED(rv)) {
|
||||
// no image loading for us. Oh, well.
|
||||
sImgLoader = nsnull;
|
||||
}
|
||||
|
||||
sInitialized = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
@ -402,6 +415,7 @@ nsContentUtils::Shutdown()
|
||||
NS_IF_RELEASE(sNameSpaceManager);
|
||||
NS_IF_RELEASE(sParserService);
|
||||
NS_IF_RELEASE(sIOService);
|
||||
NS_IF_RELEASE(sImgLoader);
|
||||
}
|
||||
|
||||
// static
|
||||
@ -1655,6 +1669,71 @@ nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,
|
||||
NS_ERROR_DOM_NAMESPACE_ERR : NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
|
||||
nsIDocument* aLoadingDocument)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have a URI");
|
||||
NS_PRECONDITION(aLoadingDocument, "Must have a document");
|
||||
|
||||
// XXXbz Do security manager check here!
|
||||
|
||||
// Check with content policy
|
||||
nsIScriptGlobalObject* globalScript = aLoadingDocument->GetScriptGlobalObject();
|
||||
|
||||
if (!globalScript) {
|
||||
// just let it load. Documents loaded as data should take care to
|
||||
// prevent image loading themselves.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(globalScript));
|
||||
|
||||
PRBool shouldLoad = PR_TRUE;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::IMAGE, aURI,
|
||||
aContext,
|
||||
domWin, &shouldLoad);
|
||||
if (NS_SUCCEEDED(rv) && !shouldLoad) {
|
||||
return NS_ERROR_IMAGE_BLOCKED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
|
||||
imgIDecoderObserver* aObserver,
|
||||
PRInt32 aLoadFlags, imgIRequest** aRequest)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have a URI");
|
||||
NS_PRECONDITION(aLoadingDocument, "Must have a document");
|
||||
NS_PRECONDITION(aRequest, "Null out param");
|
||||
|
||||
if (!sImgLoader) {
|
||||
// nothing we can do here
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
|
||||
NS_WARN_IF_FALSE(loadGroup, "Could not get loadgroup; onload may fire too early");
|
||||
|
||||
nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
|
||||
|
||||
// XXXbz using "documentURI" for the initialDocumentURI is not quite
|
||||
// right, but the best we can do here...
|
||||
return sImgLoader->LoadImage(aURI, /* uri to load */
|
||||
documentURI, /* initialDocumentURI */
|
||||
documentURI, /* referrer */
|
||||
loadGroup, /* loadgroup */
|
||||
aObserver, /* imgIDecoderObserver */
|
||||
aLoadingDocument, /* uniquification key */
|
||||
aLoadFlags, /* load flags */
|
||||
nsnull, /* cache key */
|
||||
nsnull, /* existing request*/
|
||||
aRequest);
|
||||
}
|
||||
|
||||
void
|
||||
nsCxPusher::Push(nsISupports *aCurrentTarget)
|
||||
{
|
||||
|
@ -66,6 +66,8 @@
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
// Statics
|
||||
imgILoader* nsImageLoadingContent::sImgLoader = nsnull;
|
||||
nsIIOService* nsImageLoadingContent::sIOService = nsnull;
|
||||
@ -407,7 +409,7 @@ nsImageLoadingContent::ImageURIChanged(const nsACString& aNewURI)
|
||||
// not to show the broken image icon. If the load is blocked by the
|
||||
// content policy or security manager, we will want to cancel with
|
||||
// the error code from those.
|
||||
nsresult cancelResult = CanLoadImage(imageURI, doc);
|
||||
nsresult cancelResult = nsContentUtils::CanLoadImage(imageURI, this, doc);
|
||||
if (NS_SUCCEEDED(cancelResult)) {
|
||||
cancelResult = NS_ERROR_IMAGE_SRC_CHANGED;
|
||||
}
|
||||
@ -421,11 +423,6 @@ nsImageLoadingContent::ImageURIChanged(const nsACString& aNewURI)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
NS_WARN_IF_FALSE(loadGroup, "Could not get loadgroup; onload may fire too early");
|
||||
|
||||
nsIURI *documentURI = doc->GetDocumentURI();
|
||||
|
||||
nsCOMPtr<imgIRequest> & req = mCurrentRequest ? mPendingRequest : mCurrentRequest;
|
||||
|
||||
// It may be that one of our frames has replaced itself with alt text... This
|
||||
@ -436,18 +433,8 @@ nsImageLoadingContent::ImageURIChanged(const nsACString& aNewURI)
|
||||
// that have changed to alt text on us yet.
|
||||
PRBool mayNeedReframe = mHaveHadObserver && !mCurrentRequest;
|
||||
|
||||
// XXXbz using "documentURI" for the initialDocumentURI is not quite
|
||||
// right, but the best we can do here...
|
||||
rv = sImgLoader->LoadImage(imageURI, /* uri to load */
|
||||
documentURI, /* initialDocumentURI */
|
||||
documentURI, /* referrer */
|
||||
loadGroup, /* loadgroup */
|
||||
this, /* imgIDecoderObserver */
|
||||
doc, /* uniquification key */
|
||||
nsIRequest::LOAD_NORMAL, /* load flags */
|
||||
nsnull, /* cache key */
|
||||
nsnull, /* existing request*/
|
||||
getter_AddRefs(req));
|
||||
rv = nsContentUtils::LoadImage(imageURI, doc, this, nsIRequest::LOAD_NORMAL,
|
||||
getter_AddRefs(req));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -517,34 +504,6 @@ nsImageLoadingContent::CancelImageRequests(nsresult aReason)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::CanLoadImage(nsIURI* aURI, nsIDocument* aDocument)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Null URI");
|
||||
NS_PRECONDITION(aDocument, "Null document!");
|
||||
|
||||
// Check with the content-policy things to make sure this load is permitted.
|
||||
|
||||
nsIScriptGlobalObject *globalScript = aDocument->GetScriptGlobalObject();
|
||||
if (!globalScript) {
|
||||
// just let it load. Documents loaded as data should take care to
|
||||
// prevent image loading themselves.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(globalScript));
|
||||
|
||||
PRBool shouldLoad = PR_TRUE;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::IMAGE, aURI, this,
|
||||
domWin, &shouldLoad);
|
||||
if (NS_SUCCEEDED(rv) && !shouldLoad) {
|
||||
return NS_ERROR_IMAGE_BLOCKED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsIDocument*
|
||||
nsImageLoadingContent::GetOurDocument()
|
||||
{
|
||||
|
@ -119,14 +119,6 @@ private:
|
||||
*/
|
||||
void CancelImageRequests(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Method to do security and content policy checks on the image URI
|
||||
*
|
||||
* @param aURI uri of the image to be loaded
|
||||
* @param aDocument the document we belong to
|
||||
*/
|
||||
nsresult CanLoadImage(nsIURI* aURI, nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* helper to get the document for this content (from the nodeinfo
|
||||
* and such). Not named GetDocument to prevent ambiguous method
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "nsSize.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
/*
|
||||
* For storage of an |nsRuleNode|'s children in a linked list.
|
||||
@ -2942,9 +2943,9 @@ nsRuleNode::ComputeBackgroundData(nsStyleStruct* aStartStruct,
|
||||
bg->mBackgroundFlags |= NS_STYLE_BG_COLOR_TRANSPARENT;
|
||||
}
|
||||
|
||||
// background-image: url, none, inherit
|
||||
if (eCSSUnit_URL == colorData.mBackImage.GetUnit()) {
|
||||
bg->mBackgroundImage = colorData.mBackImage.GetURLValue();
|
||||
// background-image: url (stored as image), none, inherit
|
||||
if (eCSSUnit_Image == colorData.mBackImage.GetUnit()) {
|
||||
bg->mBackgroundImage = colorData.mBackImage.GetImageValue();
|
||||
bg->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE;
|
||||
}
|
||||
else if (eCSSUnit_None == colorData.mBackImage.GetUnit()) {
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nsRuleNode.h"
|
||||
#include "nsUnitConversion.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
// #define NOISY_DEBUG
|
||||
@ -532,6 +533,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
URICString(imgIRequest* aImageRequest) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (aImageRequest) {
|
||||
aImageRequest->GetURI(getter_AddRefs(uri));
|
||||
}
|
||||
if (uri) {
|
||||
uri->GetSpec(*this);
|
||||
} else {
|
||||
Assign("[none]");
|
||||
}
|
||||
}
|
||||
|
||||
URICString& operator=(const URICString& aOther) {
|
||||
Assign(aOther);
|
||||
return *this;
|
||||
|
@ -2965,23 +2965,18 @@ nsGenericHTMLElement::MapBackgroundAttributesInto(const nsMappedAttributes* aAtt
|
||||
// as well as elements with _baseHref set. We need to be able
|
||||
// to get to the element somehow, or store the base URI in the
|
||||
// attributes.
|
||||
nsIPresShell *shell = aData->mPresContext->GetPresShell();
|
||||
if (shell) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsresult rv = shell->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_SUCCEEDED(rv) && doc) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = nsContentUtils::NewURIWithDocumentCharset(
|
||||
getter_AddRefs(uri), spec, doc, doc->GetBaseURI());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCSSValue::URL *url = new nsCSSValue::URL(uri, spec.get());
|
||||
if (url) {
|
||||
if (url->mString)
|
||||
aData->mColorData->mBackImage.SetURLValue(url);
|
||||
else
|
||||
delete url;
|
||||
}
|
||||
nsIDocument* doc = aData->mPresContext->GetDocument();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
|
||||
getter_AddRefs(uri), spec, doc, doc->GetBaseURI());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCSSValue::Image *img = new nsCSSValue::Image(uri, spec.get(), doc);
|
||||
if (img) {
|
||||
if (img->mString) {
|
||||
aData->mColorData->mBackImage.SetImageValue(img);
|
||||
}
|
||||
else
|
||||
delete img;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ REQUIRES = xpcom \
|
||||
view \
|
||||
intl \
|
||||
pref \
|
||||
imglib2 \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -185,6 +185,10 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
if (target->GetUnit() == eCSSUnit_Null) {
|
||||
const nsCSSValue *val = ValueAtCursor(cursor);
|
||||
NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
|
||||
if (iProp == eCSSProperty_background_image &&
|
||||
val->GetUnit() == eCSSUnit_URL) {
|
||||
val->StartImageLoad(aRuleData->mPresContext->GetDocument());
|
||||
}
|
||||
*target = *val;
|
||||
if (iProp == eCSSProperty_font_family) {
|
||||
// XXX Are there other things like this?
|
||||
|
@ -415,7 +415,7 @@ PRBool nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty, const n
|
||||
|
||||
aResult.Append(PRUnichar(')'));
|
||||
}
|
||||
else if (eCSSUnit_URL == unit) {
|
||||
else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
|
||||
aResult.Append(NS_LITERAL_STRING("url(") +
|
||||
nsDependentString(aValue.GetOriginalURLValue()) +
|
||||
NS_LITERAL_STRING(")"));
|
||||
@ -441,6 +441,7 @@ PRBool nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty, const n
|
||||
|
||||
case eCSSUnit_String: break;
|
||||
case eCSSUnit_URL: break;
|
||||
case eCSSUnit_Image: break;
|
||||
case eCSSUnit_Attr:
|
||||
case eCSSUnit_Counter:
|
||||
case eCSSUnit_Counters: aResult.Append(PRUnichar(')')); break;
|
||||
|
@ -39,6 +39,12 @@
|
||||
#include "nsString.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
// Paint forcing
|
||||
#include "prenv.h"
|
||||
|
||||
//#include "nsStyleConsts.h"
|
||||
|
||||
@ -97,6 +103,13 @@ nsCSSValue::nsCSSValue(nsCSSValue::URL* aValue)
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(nsCSSValue::Image* aValue)
|
||||
: mUnit(eCSSUnit_Image)
|
||||
{
|
||||
mValue.mImage = aValue;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
||||
: mUnit(aCopy.mUnit)
|
||||
{
|
||||
@ -118,6 +131,10 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
||||
mValue.mURL = aCopy.mValue.mURL;
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit){
|
||||
mValue.mImage = aCopy.mValue.mImage;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
else {
|
||||
mValue.mFloat = aCopy.mValue.mFloat;
|
||||
}
|
||||
@ -147,6 +164,10 @@ nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy)
|
||||
mValue.mURL = aCopy.mValue.mURL;
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit){
|
||||
mValue.mImage = aCopy.mValue.mImage;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
else {
|
||||
mValue.mFloat = aCopy.mValue.mFloat;
|
||||
}
|
||||
@ -175,6 +196,9 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
||||
else if (eCSSUnit_URL == mUnit) {
|
||||
return *mValue.mURL == *aOther.mValue.mURL;
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit) {
|
||||
return *mValue.mImage == *aOther.mValue.mImage;
|
||||
}
|
||||
else {
|
||||
return mValue.mFloat == aOther.mValue.mFloat;
|
||||
}
|
||||
@ -182,6 +206,12 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
imgIRequest* nsCSSValue::GetImageValue() const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_Image, "not an Image value");
|
||||
return mValue.mImage->mRequest;
|
||||
}
|
||||
|
||||
nscoord nsCSSValue::GetLengthTwips() const
|
||||
{
|
||||
NS_ASSERTION(IsFixedLengthUnit(), "not a fixed length unit");
|
||||
@ -275,6 +305,14 @@ void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue)
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
|
||||
void nsCSSValue::SetImageValue(nsCSSValue::Image* aValue)
|
||||
{
|
||||
Reset();
|
||||
mUnit = eCSSUnit_Image;
|
||||
mValue.mImage = aValue;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
|
||||
void nsCSSValue::SetAutoValue()
|
||||
{
|
||||
Reset();
|
||||
@ -305,6 +343,52 @@ void nsCSSValue::SetNormalValue()
|
||||
mUnit = eCSSUnit_Normal;
|
||||
}
|
||||
|
||||
void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
|
||||
{
|
||||
NS_PRECONDITION(eCSSUnit_URL == mUnit, "Not a URL value!");
|
||||
nsCSSValue::Image* image =
|
||||
new nsCSSValue::Image(mValue.mURL->mURI,
|
||||
mValue.mURL->mString,
|
||||
aDocument);
|
||||
if (image) {
|
||||
if (image->mString) {
|
||||
nsCSSValue* writable = NS_CONST_CAST(nsCSSValue*, this);
|
||||
writable->SetImageValue(image);
|
||||
} else {
|
||||
delete image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSValue::Image::Image(nsIURI* aURI, const PRUnichar* aString,
|
||||
nsIDocument* aDocument)
|
||||
: URL(aURI, aString)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSValue::Image);
|
||||
|
||||
// Check for failed mString allocation first
|
||||
if (!mString)
|
||||
return;
|
||||
|
||||
// If Paint Forcing is enabled, then force all background image loads to
|
||||
// complete before firing onload for the document
|
||||
static PRInt32 loadFlag = PR_GetEnv("MOZ_FORCE_PAINT_AFTER_ONLOAD")
|
||||
? (PRInt32)nsIRequest::LOAD_NORMAL
|
||||
: (PRInt32)nsIRequest::LOAD_BACKGROUND;
|
||||
|
||||
if (mURI &&
|
||||
NS_SUCCEEDED(nsContentUtils::CanLoadImage(mURI, nsnull, aDocument))) {
|
||||
nsContentUtils::LoadImage(mURI, aDocument, nsnull,
|
||||
loadFlag,
|
||||
getter_AddRefs(mRequest));
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSValue::Image::~Image()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsCSSValue::Image);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
@ -319,14 +403,15 @@ void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
aBuffer.Append(NS_LITERAL_STRING(": "));
|
||||
}
|
||||
|
||||
switch (mUnit) {
|
||||
case eCSSUnit_Image:
|
||||
case eCSSUnit_URL: aBuffer.Append(NS_LITERAL_STRING("url(")); break;
|
||||
case eCSSUnit_Attr: aBuffer.Append(NS_LITERAL_STRING("attr(")); break;
|
||||
case eCSSUnit_Counter: aBuffer.Append(NS_LITERAL_STRING("counter(")); break;
|
||||
case eCSSUnit_Counters: aBuffer.Append(NS_LITERAL_STRING("counters(")); break;
|
||||
default: break;
|
||||
}
|
||||
if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Counters)) {
|
||||
switch (mUnit) {
|
||||
case eCSSUnit_URL: aBuffer.Append(NS_LITERAL_STRING("url(")); break;
|
||||
case eCSSUnit_Attr: aBuffer.Append(NS_LITERAL_STRING("attr(")); break;
|
||||
case eCSSUnit_Counter: aBuffer.Append(NS_LITERAL_STRING("counter(")); break;
|
||||
case eCSSUnit_Counters: aBuffer.Append(NS_LITERAL_STRING("counters(")); break;
|
||||
default: break;
|
||||
}
|
||||
if (nsnull != mValue.mString) {
|
||||
aBuffer.Append(PRUnichar('"'));
|
||||
aBuffer.Append(mValue.mString);
|
||||
@ -379,6 +464,9 @@ void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
else if (eCSSUnit_URL == mUnit) {
|
||||
aBuffer.Append(mValue.mURL->mString);
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit) {
|
||||
aBuffer.Append(mValue.mImage->mString);
|
||||
}
|
||||
else if (eCSSUnit_Percent == mUnit) {
|
||||
nsAutoString floatString;
|
||||
floatString.AppendFloat(mValue.mFloat * 100.0f);
|
||||
@ -399,6 +487,7 @@ void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
case eCSSUnit_Normal: aBuffer.Append(NS_LITERAL_STRING("normal")); break;
|
||||
case eCSSUnit_String: break;
|
||||
case eCSSUnit_URL:
|
||||
case eCSSUnit_Image:
|
||||
case eCSSUnit_Attr:
|
||||
case eCSSUnit_Counter:
|
||||
case eCSSUnit_Counters: aBuffer.Append(NS_LITERAL_STRING(")")); break;
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include "nsUnitConversion.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
class imgIRequest;
|
||||
class nsIDocument;
|
||||
|
||||
enum nsCSSUnit {
|
||||
eCSSUnit_Null = 0, // (n/a) null unit, value is not specified
|
||||
@ -59,6 +63,7 @@ enum nsCSSUnit {
|
||||
eCSSUnit_Counter = 12, // (PRUnichar*) a counter(string,[string]) value
|
||||
eCSSUnit_Counters = 13, // (PRUnichar*) a counters(string,string[,string]) value
|
||||
eCSSUnit_URL = 14, // (nsCSSValue::URL*) value
|
||||
eCSSUnit_Image = 15, // (nsCSSValue::Image*) value
|
||||
eCSSUnit_Integer = 50, // (int) simple value
|
||||
eCSSUnit_Enumerated = 51, // (int) value has enumerated meaning
|
||||
eCSSUnit_Color = 80, // (color) an RGBA value
|
||||
@ -118,6 +123,9 @@ public:
|
||||
struct URL;
|
||||
friend struct URL;
|
||||
|
||||
struct Image;
|
||||
friend struct Image;
|
||||
|
||||
// for valueless units only (null, auto, inherit, none, normal)
|
||||
nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null)
|
||||
: mUnit(aUnit)
|
||||
@ -134,6 +142,7 @@ public:
|
||||
nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit);
|
||||
nsCSSValue(nscolor aValue);
|
||||
nsCSSValue(URL* aValue);
|
||||
nsCSSValue(Image* aValue);
|
||||
nsCSSValue(const nsCSSValue& aCopy);
|
||||
~nsCSSValue();
|
||||
|
||||
@ -204,16 +213,25 @@ public:
|
||||
|
||||
nsIURI* GetURLValue() const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value");
|
||||
return mValue.mURL->mURI;
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
||||
"not a URL value");
|
||||
return mUnit == eCSSUnit_URL ?
|
||||
mValue.mURL->mURI : mValue.mImage->mURI;
|
||||
}
|
||||
|
||||
const PRUnichar* GetOriginalURLValue() const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value");
|
||||
return mValue.mURL->mString;
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
||||
"not a URL value");
|
||||
return mUnit == eCSSUnit_URL ?
|
||||
mValue.mURL->mString : mValue.mImage->mString;
|
||||
}
|
||||
|
||||
// Not making this inline because that would force us to include
|
||||
// imgIRequest.h, which leads to REQUIRES hell, since this header is included
|
||||
// all over.
|
||||
imgIRequest* GetImageValue() const;
|
||||
|
||||
nscoord GetLengthTwips() const;
|
||||
|
||||
void Reset() // sets to null
|
||||
@ -223,6 +241,8 @@ public:
|
||||
nsCRT::free(mValue.mString);
|
||||
} else if (eCSSUnit_URL == mUnit) {
|
||||
mValue.mURL->Release();
|
||||
} else if (eCSSUnit_Image == mUnit) {
|
||||
mValue.mImage->Release();
|
||||
}
|
||||
mUnit = eCSSUnit_Null;
|
||||
mValue.mInt = 0;
|
||||
@ -234,11 +254,13 @@ public:
|
||||
void SetStringValue(const nsAString& aValue, nsCSSUnit aUnit);
|
||||
void SetColorValue(nscolor aValue);
|
||||
void SetURLValue(nsCSSValue::URL* aURI);
|
||||
void SetImageValue(nsCSSValue::Image* aImage);
|
||||
void SetAutoValue();
|
||||
void SetInheritValue();
|
||||
void SetInitialValue();
|
||||
void SetNoneValue();
|
||||
void SetNormalValue();
|
||||
void StartImageLoad(nsIDocument* aDocument) const; // Not really const, but pretending
|
||||
|
||||
#ifdef DEBUG
|
||||
void AppendToString(nsAString& aBuffer, nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const;
|
||||
@ -282,10 +304,28 @@ public:
|
||||
|
||||
void AddRef() { ++mRefCnt; }
|
||||
void Release() { if (--mRefCnt == 0) delete this; }
|
||||
private:
|
||||
protected:
|
||||
nsrefcnt mRefCnt;
|
||||
};
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsCSSValue::Image)
|
||||
|
||||
struct nsCSSValue::Image : public nsCSSValue::URL {
|
||||
// Not making the constructor and destructor inline because that would
|
||||
// force us to include imgIRequest.h, which leads to REQUIRES hell, since
|
||||
// this header is included all over.
|
||||
Image(nsIURI* aURI, const PRUnichar* aString, nsIDocument* aDocument);
|
||||
~Image();
|
||||
|
||||
// Inherit operator== from nsCSSValue::URL
|
||||
|
||||
nsCOMPtr<imgIRequest> mRequest; // null == image load blocked or somehow failed
|
||||
|
||||
// Override AddRef/Release so we delete ourselves via the right pointer.
|
||||
void AddRef() { ++mRefCnt; }
|
||||
void Release() { if (--mRefCnt == 0) delete this; }
|
||||
};
|
||||
|
||||
protected:
|
||||
nsCSSUnit mUnit;
|
||||
union {
|
||||
@ -294,6 +334,7 @@ protected:
|
||||
PRUnichar* mString;
|
||||
nscolor mColor;
|
||||
URL* mURL;
|
||||
Image* mImage;
|
||||
} mValue;
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,7 @@
|
||||
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
#if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon)
|
||||
#define DEBUG_ComputedDOMStyle
|
||||
@ -723,7 +724,11 @@ nsComputedDOMStyle::GetBackgroundImage(nsIFrame *aFrame,
|
||||
if (color->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) {
|
||||
val->SetIdent(nsLayoutAtoms::none);
|
||||
} else {
|
||||
val->SetURI(color->mBackgroundImage);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (color->mBackgroundImage) {
|
||||
color->mBackgroundImage->GetURI(getter_AddRefs(uri));
|
||||
}
|
||||
val->SetURI(uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nsIURI.h"
|
||||
|
||||
class nsIFrame;
|
||||
class imgIRequest;
|
||||
|
||||
enum nsStyleStructID {
|
||||
|
||||
@ -147,7 +148,7 @@ struct nsStyleColor : public nsStyleStruct {
|
||||
struct nsStyleBackground : public nsStyleStruct {
|
||||
nsStyleBackground(nsIPresContext* aPresContext);
|
||||
nsStyleBackground(const nsStyleBackground& aOther);
|
||||
~nsStyleBackground() {};
|
||||
~nsStyleBackground();
|
||||
|
||||
NS_DEFINE_STATIC_STYLESTRUCTID_ACCESSOR(eStyleStruct_Background)
|
||||
|
||||
@ -183,7 +184,7 @@ struct nsStyleBackground : public nsStyleStruct {
|
||||
mBackgroundYPosition; // [reset]
|
||||
|
||||
nscolor mBackgroundColor; // [reset]
|
||||
nsCOMPtr<nsIURI> mBackgroundImage; // [reset]
|
||||
nsCOMPtr<imgIRequest> mBackgroundImage; // [reset]
|
||||
|
||||
PRBool IsTransparent() const
|
||||
{
|
||||
|
@ -37,6 +37,7 @@ REQUIRES = xpcom \
|
||||
dom \
|
||||
necko \
|
||||
unicharutil \
|
||||
imglib2 \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -55,6 +55,8 @@
|
||||
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
#include "imgIRequest.h"
|
||||
|
||||
inline PRBool IsFixedUnit(nsStyleUnit aUnit, PRBool aEnumOK)
|
||||
{
|
||||
return PRBool((aUnit == eStyleUnit_Null) ||
|
||||
@ -162,6 +164,22 @@ static PRBool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
|
||||
eq);
|
||||
}
|
||||
|
||||
static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
|
||||
{
|
||||
if (aImage1 == aImage2) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (!aImage1 || !aImage2) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri1, uri2;
|
||||
aImage1->GetURI(getter_AddRefs(uri1));
|
||||
aImage2->GetURI(getter_AddRefs(uri2));
|
||||
return EqualURIs(uri1, uri2);
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleFont
|
||||
//
|
||||
@ -1019,6 +1037,10 @@ nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
|
||||
{
|
||||
}
|
||||
|
||||
nsStyleBackground::~nsStyleBackground()
|
||||
{
|
||||
}
|
||||
|
||||
nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
|
||||
{
|
||||
if (mBackgroundAttachment != aOther.mBackgroundAttachment
|
||||
@ -1036,7 +1058,7 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther)
|
||||
(mBackgroundClip == aOther.mBackgroundClip) &&
|
||||
(mBackgroundInlinePolicy == aOther.mBackgroundInlinePolicy) &&
|
||||
(mBackgroundOrigin == aOther.mBackgroundOrigin) &&
|
||||
EqualURIs(mBackgroundImage, aOther.mBackgroundImage) &&
|
||||
EqualImages(mBackgroundImage, aOther.mBackgroundImage) &&
|
||||
((!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_PERCENT) ||
|
||||
(mBackgroundXPosition.mFloat == aOther.mBackgroundXPosition.mFloat)) &&
|
||||
(!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_LENGTH) ||
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "nsLayoutErrors.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
#include "nsFrameManager.h"
|
||||
|
||||
@ -1420,14 +1421,20 @@ nsFrameManager::ReResolveStyleContext(nsIPresContext *aPresContext,
|
||||
const nsStyleBackground* oldColor = oldContext->GetStyleBackground();
|
||||
const nsStyleBackground* newColor = newContext->GetStyleBackground();
|
||||
|
||||
PRBool equal;
|
||||
if (oldColor->mBackgroundImage &&
|
||||
(!newColor->mBackgroundImage ||
|
||||
NS_FAILED(oldColor->mBackgroundImage->Equals(
|
||||
newColor->mBackgroundImage, &equal)) ||
|
||||
!equal)) {
|
||||
// stop the image loading for the frame, the image has changed
|
||||
aPresContext->StopImagesFor(aFrame);
|
||||
if (oldColor->mBackgroundImage) {
|
||||
PRBool stopImages = !newColor->mBackgroundImage;
|
||||
if (!stopImages) {
|
||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||
oldColor->mBackgroundImage->GetURI(getter_AddRefs(oldURI));
|
||||
newColor->mBackgroundImage->GetURI(getter_AddRefs(newURI));
|
||||
PRBool equal;
|
||||
stopImages =
|
||||
NS_FAILED(oldURI->Equals(newURI, &equal)) || !equal;
|
||||
}
|
||||
if (stopImages) {
|
||||
// stop the image loading for the frame, the image has changed
|
||||
aPresContext->StopImagesFor(aFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
oldContext->Release();
|
||||
|
@ -83,51 +83,31 @@ nsImageLoader::Destroy()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoader::Load(nsIURI *aURI)
|
||||
nsImageLoader::Load(imgIRequest *aImage)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (!aURI)
|
||||
if (!aImage)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIPresShell *shell = mPresContext->GetPresShell();
|
||||
if (!shell) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsresult rv = shell->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Get the document's loadgroup
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
|
||||
if (mRequest) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
mRequest->GetURI(getter_AddRefs(oldURI));
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
aImage->GetURI(getter_AddRefs(newURI));
|
||||
PRBool eq = PR_FALSE;
|
||||
aURI->Equals(oldURI, &eq);
|
||||
if (eq) {
|
||||
nsresult rv = newURI->Equals(oldURI, &eq);
|
||||
if (NS_SUCCEEDED(rv) && eq) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Now cancel the old request so it won't hold a stale ref to us.
|
||||
mRequest->Cancel(NS_ERROR_FAILURE);
|
||||
mRequest = nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// If Paint Forcing is enabled, then force all background image loads
|
||||
// to complete before firing onload for the document
|
||||
static PRInt32 loadFlag
|
||||
= PR_GetEnv("MOZ_FORCE_PAINT_AFTER_ONLOAD")
|
||||
? (PRInt32)nsIRequest::LOAD_NORMAL
|
||||
: (PRInt32)nsIRequest::LOAD_BACKGROUND;
|
||||
|
||||
// XXX: initialDocumentURI is NULL!
|
||||
return il->LoadImage(aURI, nsnull, doc->GetDocumentURI(), loadGroup,
|
||||
this, doc, loadFlag, nsnull, nsnull,
|
||||
getter_AddRefs(mRequest));
|
||||
return aImage->Clone(this, getter_AddRefs(mRequest));
|
||||
}
|
||||
|
||||
|
||||
@ -188,6 +168,11 @@ NS_IMETHODIMP nsImageLoader::OnStopFrame(imgIRequest *aRequest,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mRequest) {
|
||||
// We're in the middle of a paint anyway
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Draw the background image
|
||||
RedrawDirtyFrame(nsnull);
|
||||
return NS_OK;
|
||||
@ -213,6 +198,11 @@ NS_IMETHODIMP nsImageLoader::FrameChanged(imgIContainer *aContainer,
|
||||
if (!mFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mRequest) {
|
||||
// We're in the middle of a paint anyway
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRect r(*dirtyRect);
|
||||
|
||||
float p2t;
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
NS_DECL_IMGICONTAINEROBSERVER
|
||||
|
||||
void Init(nsIFrame *aFrame, nsIPresContext *aPresContext);
|
||||
nsresult Load(nsIURI *aURI);
|
||||
nsresult Load(imgIRequest *aImage);
|
||||
|
||||
void Destroy();
|
||||
|
||||
|
@ -945,7 +945,7 @@ nsPresContext::GetScaledPixelsToTwips(float* aResult) const
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPresContext::LoadImage(nsIURI* aURL,
|
||||
nsPresContext::LoadImage(imgIRequest* aImage,
|
||||
nsIFrame* aTargetFrame,//may be null (precached image)
|
||||
imgIRequest **aRequest)
|
||||
{
|
||||
@ -955,30 +955,6 @@ nsPresContext::LoadImage(nsIURI* aURL,
|
||||
nsImageLoader *loader = NS_REINTERPRET_CAST(nsImageLoader*, mImageLoaders.Get(&key)); // addrefs
|
||||
|
||||
if (!loader) {
|
||||
nsIContent* content = aTargetFrame->GetContent();
|
||||
|
||||
// Check with the content-policy things to make sure this load is permitted.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(content));
|
||||
|
||||
if (content && element) {
|
||||
nsCOMPtr<nsIDocument> document = content->GetDocument();
|
||||
|
||||
// If there is no document, skip the policy check
|
||||
// XXXldb This really means the document is being destroyed, so
|
||||
// perhaps we're better off skipping the load entirely.
|
||||
if (document) {
|
||||
nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(document->GetScriptGlobalObject()));
|
||||
if (domWin) {
|
||||
PRBool shouldLoad = PR_TRUE;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::IMAGE,
|
||||
aURL, element, domWin, &shouldLoad);
|
||||
if (NS_SUCCEEDED(rv) && !shouldLoad)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loader = new nsImageLoader();
|
||||
if (!loader)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -989,7 +965,7 @@ nsPresContext::LoadImage(nsIURI* aURL,
|
||||
mImageLoaders.Put(&key, loader);
|
||||
}
|
||||
|
||||
loader->Load(aURL);
|
||||
loader->Load(aImage);
|
||||
|
||||
NS_IF_ADDREF(*aRequest = loader->GetRequest());
|
||||
|
||||
|
@ -260,7 +260,7 @@ public:
|
||||
* method will be invoked (via the ViewManager) so that the
|
||||
* appropriate damage repair is done.
|
||||
*/
|
||||
virtual nsresult LoadImage(nsIURI* aURL,
|
||||
virtual nsresult LoadImage(imgIRequest* aImage,
|
||||
nsIFrame* aTargetFrame,
|
||||
imgIRequest **aRequest) = 0;
|
||||
|
||||
|
@ -260,7 +260,7 @@ public:
|
||||
* method will be invoked (via the ViewManager) so that the
|
||||
* appropriate damage repair is done.
|
||||
*/
|
||||
virtual nsresult LoadImage(nsIURI* aURL,
|
||||
virtual nsresult LoadImage(imgIRequest* aImage,
|
||||
nsIFrame* aTargetFrame,
|
||||
imgIRequest **aRequest) = 0;
|
||||
|
||||
|
@ -260,7 +260,7 @@ public:
|
||||
* method will be invoked (via the ViewManager) so that the
|
||||
* appropriate damage repair is done.
|
||||
*/
|
||||
virtual nsresult LoadImage(nsIURI* aURL,
|
||||
virtual nsresult LoadImage(imgIRequest* aImage,
|
||||
nsIFrame* aTargetFrame,
|
||||
imgIRequest **aRequest) = 0;
|
||||
|
||||
|
@ -83,51 +83,31 @@ nsImageLoader::Destroy()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoader::Load(nsIURI *aURI)
|
||||
nsImageLoader::Load(imgIRequest *aImage)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (!aURI)
|
||||
if (!aImage)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIPresShell *shell = mPresContext->GetPresShell();
|
||||
if (!shell) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsresult rv = shell->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Get the document's loadgroup
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
|
||||
if (mRequest) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
mRequest->GetURI(getter_AddRefs(oldURI));
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
aImage->GetURI(getter_AddRefs(newURI));
|
||||
PRBool eq = PR_FALSE;
|
||||
aURI->Equals(oldURI, &eq);
|
||||
if (eq) {
|
||||
nsresult rv = newURI->Equals(oldURI, &eq);
|
||||
if (NS_SUCCEEDED(rv) && eq) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Now cancel the old request so it won't hold a stale ref to us.
|
||||
mRequest->Cancel(NS_ERROR_FAILURE);
|
||||
mRequest = nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// If Paint Forcing is enabled, then force all background image loads
|
||||
// to complete before firing onload for the document
|
||||
static PRInt32 loadFlag
|
||||
= PR_GetEnv("MOZ_FORCE_PAINT_AFTER_ONLOAD")
|
||||
? (PRInt32)nsIRequest::LOAD_NORMAL
|
||||
: (PRInt32)nsIRequest::LOAD_BACKGROUND;
|
||||
|
||||
// XXX: initialDocumentURI is NULL!
|
||||
return il->LoadImage(aURI, nsnull, doc->GetDocumentURI(), loadGroup,
|
||||
this, doc, loadFlag, nsnull, nsnull,
|
||||
getter_AddRefs(mRequest));
|
||||
return aImage->Clone(this, getter_AddRefs(mRequest));
|
||||
}
|
||||
|
||||
|
||||
@ -188,6 +168,11 @@ NS_IMETHODIMP nsImageLoader::OnStopFrame(imgIRequest *aRequest,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mRequest) {
|
||||
// We're in the middle of a paint anyway
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Draw the background image
|
||||
RedrawDirtyFrame(nsnull);
|
||||
return NS_OK;
|
||||
@ -213,6 +198,11 @@ NS_IMETHODIMP nsImageLoader::FrameChanged(imgIContainer *aContainer,
|
||||
if (!mFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mRequest) {
|
||||
// We're in the middle of a paint anyway
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRect r(*dirtyRect);
|
||||
|
||||
float p2t;
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
NS_DECL_IMGICONTAINEROBSERVER
|
||||
|
||||
void Init(nsIFrame *aFrame, nsIPresContext *aPresContext);
|
||||
nsresult Load(nsIURI *aURI);
|
||||
nsresult Load(imgIRequest *aImage);
|
||||
|
||||
void Destroy();
|
||||
|
||||
|
@ -945,7 +945,7 @@ nsPresContext::GetScaledPixelsToTwips(float* aResult) const
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPresContext::LoadImage(nsIURI* aURL,
|
||||
nsPresContext::LoadImage(imgIRequest* aImage,
|
||||
nsIFrame* aTargetFrame,//may be null (precached image)
|
||||
imgIRequest **aRequest)
|
||||
{
|
||||
@ -955,30 +955,6 @@ nsPresContext::LoadImage(nsIURI* aURL,
|
||||
nsImageLoader *loader = NS_REINTERPRET_CAST(nsImageLoader*, mImageLoaders.Get(&key)); // addrefs
|
||||
|
||||
if (!loader) {
|
||||
nsIContent* content = aTargetFrame->GetContent();
|
||||
|
||||
// Check with the content-policy things to make sure this load is permitted.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(content));
|
||||
|
||||
if (content && element) {
|
||||
nsCOMPtr<nsIDocument> document = content->GetDocument();
|
||||
|
||||
// If there is no document, skip the policy check
|
||||
// XXXldb This really means the document is being destroyed, so
|
||||
// perhaps we're better off skipping the load entirely.
|
||||
if (document) {
|
||||
nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(document->GetScriptGlobalObject()));
|
||||
if (domWin) {
|
||||
PRBool shouldLoad = PR_TRUE;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::IMAGE,
|
||||
aURL, element, domWin, &shouldLoad);
|
||||
if (NS_SUCCEEDED(rv) && !shouldLoad)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loader = new nsImageLoader();
|
||||
if (!loader)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -989,7 +965,7 @@ nsPresContext::LoadImage(nsIURI* aURL,
|
||||
mImageLoaders.Put(&key, loader);
|
||||
}
|
||||
|
||||
loader->Load(aURL);
|
||||
loader->Load(aImage);
|
||||
|
||||
NS_IF_ADDREF(*aRequest = loader->GetRequest());
|
||||
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
virtual const nsFont* GetDefaultFont(PRUint8 aFontID) const;
|
||||
NS_IMETHOD GetCachedIntPref(PRUint32 aPrefType, PRInt32& aValue);
|
||||
|
||||
virtual nsresult LoadImage(nsIURI* aURL,
|
||||
virtual nsresult LoadImage(imgIRequest* aImage,
|
||||
nsIFrame* aTargetFrame,
|
||||
imgIRequest **aRequest);
|
||||
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "nsLayoutErrors.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
#include "nsFrameManager.h"
|
||||
|
||||
@ -1420,14 +1421,20 @@ nsFrameManager::ReResolveStyleContext(nsIPresContext *aPresContext,
|
||||
const nsStyleBackground* oldColor = oldContext->GetStyleBackground();
|
||||
const nsStyleBackground* newColor = newContext->GetStyleBackground();
|
||||
|
||||
PRBool equal;
|
||||
if (oldColor->mBackgroundImage &&
|
||||
(!newColor->mBackgroundImage ||
|
||||
NS_FAILED(oldColor->mBackgroundImage->Equals(
|
||||
newColor->mBackgroundImage, &equal)) ||
|
||||
!equal)) {
|
||||
// stop the image loading for the frame, the image has changed
|
||||
aPresContext->StopImagesFor(aFrame);
|
||||
if (oldColor->mBackgroundImage) {
|
||||
PRBool stopImages = !newColor->mBackgroundImage;
|
||||
if (!stopImages) {
|
||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||
oldColor->mBackgroundImage->GetURI(getter_AddRefs(oldURI));
|
||||
newColor->mBackgroundImage->GetURI(getter_AddRefs(newURI));
|
||||
PRBool equal;
|
||||
stopImages =
|
||||
NS_FAILED(oldURI->Equals(newURI, &equal)) || !equal;
|
||||
}
|
||||
if (stopImages) {
|
||||
// stop the image loading for the frame, the image has changed
|
||||
aPresContext->StopImagesFor(aFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
oldContext->Release();
|
||||
|
@ -185,6 +185,10 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
if (target->GetUnit() == eCSSUnit_Null) {
|
||||
const nsCSSValue *val = ValueAtCursor(cursor);
|
||||
NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
|
||||
if (iProp == eCSSProperty_background_image &&
|
||||
val->GetUnit() == eCSSUnit_URL) {
|
||||
val->StartImageLoad(aRuleData->mPresContext->GetDocument());
|
||||
}
|
||||
*target = *val;
|
||||
if (iProp == eCSSProperty_font_family) {
|
||||
// XXX Are there other things like this?
|
||||
|
@ -415,7 +415,7 @@ PRBool nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty, const n
|
||||
|
||||
aResult.Append(PRUnichar(')'));
|
||||
}
|
||||
else if (eCSSUnit_URL == unit) {
|
||||
else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
|
||||
aResult.Append(NS_LITERAL_STRING("url(") +
|
||||
nsDependentString(aValue.GetOriginalURLValue()) +
|
||||
NS_LITERAL_STRING(")"));
|
||||
@ -441,6 +441,7 @@ PRBool nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty, const n
|
||||
|
||||
case eCSSUnit_String: break;
|
||||
case eCSSUnit_URL: break;
|
||||
case eCSSUnit_Image: break;
|
||||
case eCSSUnit_Attr:
|
||||
case eCSSUnit_Counter:
|
||||
case eCSSUnit_Counters: aResult.Append(PRUnichar(')')); break;
|
||||
|
@ -39,6 +39,12 @@
|
||||
#include "nsString.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
// Paint forcing
|
||||
#include "prenv.h"
|
||||
|
||||
//#include "nsStyleConsts.h"
|
||||
|
||||
@ -97,6 +103,13 @@ nsCSSValue::nsCSSValue(nsCSSValue::URL* aValue)
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(nsCSSValue::Image* aValue)
|
||||
: mUnit(eCSSUnit_Image)
|
||||
{
|
||||
mValue.mImage = aValue;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
||||
: mUnit(aCopy.mUnit)
|
||||
{
|
||||
@ -118,6 +131,10 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
||||
mValue.mURL = aCopy.mValue.mURL;
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit){
|
||||
mValue.mImage = aCopy.mValue.mImage;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
else {
|
||||
mValue.mFloat = aCopy.mValue.mFloat;
|
||||
}
|
||||
@ -147,6 +164,10 @@ nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy)
|
||||
mValue.mURL = aCopy.mValue.mURL;
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit){
|
||||
mValue.mImage = aCopy.mValue.mImage;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
else {
|
||||
mValue.mFloat = aCopy.mValue.mFloat;
|
||||
}
|
||||
@ -175,6 +196,9 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
||||
else if (eCSSUnit_URL == mUnit) {
|
||||
return *mValue.mURL == *aOther.mValue.mURL;
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit) {
|
||||
return *mValue.mImage == *aOther.mValue.mImage;
|
||||
}
|
||||
else {
|
||||
return mValue.mFloat == aOther.mValue.mFloat;
|
||||
}
|
||||
@ -182,6 +206,12 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
imgIRequest* nsCSSValue::GetImageValue() const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_Image, "not an Image value");
|
||||
return mValue.mImage->mRequest;
|
||||
}
|
||||
|
||||
nscoord nsCSSValue::GetLengthTwips() const
|
||||
{
|
||||
NS_ASSERTION(IsFixedLengthUnit(), "not a fixed length unit");
|
||||
@ -275,6 +305,14 @@ void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue)
|
||||
mValue.mURL->AddRef();
|
||||
}
|
||||
|
||||
void nsCSSValue::SetImageValue(nsCSSValue::Image* aValue)
|
||||
{
|
||||
Reset();
|
||||
mUnit = eCSSUnit_Image;
|
||||
mValue.mImage = aValue;
|
||||
mValue.mImage->AddRef();
|
||||
}
|
||||
|
||||
void nsCSSValue::SetAutoValue()
|
||||
{
|
||||
Reset();
|
||||
@ -305,6 +343,52 @@ void nsCSSValue::SetNormalValue()
|
||||
mUnit = eCSSUnit_Normal;
|
||||
}
|
||||
|
||||
void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
|
||||
{
|
||||
NS_PRECONDITION(eCSSUnit_URL == mUnit, "Not a URL value!");
|
||||
nsCSSValue::Image* image =
|
||||
new nsCSSValue::Image(mValue.mURL->mURI,
|
||||
mValue.mURL->mString,
|
||||
aDocument);
|
||||
if (image) {
|
||||
if (image->mString) {
|
||||
nsCSSValue* writable = NS_CONST_CAST(nsCSSValue*, this);
|
||||
writable->SetImageValue(image);
|
||||
} else {
|
||||
delete image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSValue::Image::Image(nsIURI* aURI, const PRUnichar* aString,
|
||||
nsIDocument* aDocument)
|
||||
: URL(aURI, aString)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSValue::Image);
|
||||
|
||||
// Check for failed mString allocation first
|
||||
if (!mString)
|
||||
return;
|
||||
|
||||
// If Paint Forcing is enabled, then force all background image loads to
|
||||
// complete before firing onload for the document
|
||||
static PRInt32 loadFlag = PR_GetEnv("MOZ_FORCE_PAINT_AFTER_ONLOAD")
|
||||
? (PRInt32)nsIRequest::LOAD_NORMAL
|
||||
: (PRInt32)nsIRequest::LOAD_BACKGROUND;
|
||||
|
||||
if (mURI &&
|
||||
NS_SUCCEEDED(nsContentUtils::CanLoadImage(mURI, nsnull, aDocument))) {
|
||||
nsContentUtils::LoadImage(mURI, aDocument, nsnull,
|
||||
loadFlag,
|
||||
getter_AddRefs(mRequest));
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSValue::Image::~Image()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsCSSValue::Image);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
@ -319,14 +403,15 @@ void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
aBuffer.Append(NS_LITERAL_STRING(": "));
|
||||
}
|
||||
|
||||
switch (mUnit) {
|
||||
case eCSSUnit_Image:
|
||||
case eCSSUnit_URL: aBuffer.Append(NS_LITERAL_STRING("url(")); break;
|
||||
case eCSSUnit_Attr: aBuffer.Append(NS_LITERAL_STRING("attr(")); break;
|
||||
case eCSSUnit_Counter: aBuffer.Append(NS_LITERAL_STRING("counter(")); break;
|
||||
case eCSSUnit_Counters: aBuffer.Append(NS_LITERAL_STRING("counters(")); break;
|
||||
default: break;
|
||||
}
|
||||
if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Counters)) {
|
||||
switch (mUnit) {
|
||||
case eCSSUnit_URL: aBuffer.Append(NS_LITERAL_STRING("url(")); break;
|
||||
case eCSSUnit_Attr: aBuffer.Append(NS_LITERAL_STRING("attr(")); break;
|
||||
case eCSSUnit_Counter: aBuffer.Append(NS_LITERAL_STRING("counter(")); break;
|
||||
case eCSSUnit_Counters: aBuffer.Append(NS_LITERAL_STRING("counters(")); break;
|
||||
default: break;
|
||||
}
|
||||
if (nsnull != mValue.mString) {
|
||||
aBuffer.Append(PRUnichar('"'));
|
||||
aBuffer.Append(mValue.mString);
|
||||
@ -379,6 +464,9 @@ void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
else if (eCSSUnit_URL == mUnit) {
|
||||
aBuffer.Append(mValue.mURL->mString);
|
||||
}
|
||||
else if (eCSSUnit_Image == mUnit) {
|
||||
aBuffer.Append(mValue.mImage->mString);
|
||||
}
|
||||
else if (eCSSUnit_Percent == mUnit) {
|
||||
nsAutoString floatString;
|
||||
floatString.AppendFloat(mValue.mFloat * 100.0f);
|
||||
@ -399,6 +487,7 @@ void nsCSSValue::AppendToString(nsAString& aBuffer,
|
||||
case eCSSUnit_Normal: aBuffer.Append(NS_LITERAL_STRING("normal")); break;
|
||||
case eCSSUnit_String: break;
|
||||
case eCSSUnit_URL:
|
||||
case eCSSUnit_Image:
|
||||
case eCSSUnit_Attr:
|
||||
case eCSSUnit_Counter:
|
||||
case eCSSUnit_Counters: aBuffer.Append(NS_LITERAL_STRING(")")); break;
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include "nsUnitConversion.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
class imgIRequest;
|
||||
class nsIDocument;
|
||||
|
||||
enum nsCSSUnit {
|
||||
eCSSUnit_Null = 0, // (n/a) null unit, value is not specified
|
||||
@ -59,6 +63,7 @@ enum nsCSSUnit {
|
||||
eCSSUnit_Counter = 12, // (PRUnichar*) a counter(string,[string]) value
|
||||
eCSSUnit_Counters = 13, // (PRUnichar*) a counters(string,string[,string]) value
|
||||
eCSSUnit_URL = 14, // (nsCSSValue::URL*) value
|
||||
eCSSUnit_Image = 15, // (nsCSSValue::Image*) value
|
||||
eCSSUnit_Integer = 50, // (int) simple value
|
||||
eCSSUnit_Enumerated = 51, // (int) value has enumerated meaning
|
||||
eCSSUnit_Color = 80, // (color) an RGBA value
|
||||
@ -118,6 +123,9 @@ public:
|
||||
struct URL;
|
||||
friend struct URL;
|
||||
|
||||
struct Image;
|
||||
friend struct Image;
|
||||
|
||||
// for valueless units only (null, auto, inherit, none, normal)
|
||||
nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null)
|
||||
: mUnit(aUnit)
|
||||
@ -134,6 +142,7 @@ public:
|
||||
nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit);
|
||||
nsCSSValue(nscolor aValue);
|
||||
nsCSSValue(URL* aValue);
|
||||
nsCSSValue(Image* aValue);
|
||||
nsCSSValue(const nsCSSValue& aCopy);
|
||||
~nsCSSValue();
|
||||
|
||||
@ -204,16 +213,25 @@ public:
|
||||
|
||||
nsIURI* GetURLValue() const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value");
|
||||
return mValue.mURL->mURI;
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
||||
"not a URL value");
|
||||
return mUnit == eCSSUnit_URL ?
|
||||
mValue.mURL->mURI : mValue.mImage->mURI;
|
||||
}
|
||||
|
||||
const PRUnichar* GetOriginalURLValue() const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value");
|
||||
return mValue.mURL->mString;
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
||||
"not a URL value");
|
||||
return mUnit == eCSSUnit_URL ?
|
||||
mValue.mURL->mString : mValue.mImage->mString;
|
||||
}
|
||||
|
||||
// Not making this inline because that would force us to include
|
||||
// imgIRequest.h, which leads to REQUIRES hell, since this header is included
|
||||
// all over.
|
||||
imgIRequest* GetImageValue() const;
|
||||
|
||||
nscoord GetLengthTwips() const;
|
||||
|
||||
void Reset() // sets to null
|
||||
@ -223,6 +241,8 @@ public:
|
||||
nsCRT::free(mValue.mString);
|
||||
} else if (eCSSUnit_URL == mUnit) {
|
||||
mValue.mURL->Release();
|
||||
} else if (eCSSUnit_Image == mUnit) {
|
||||
mValue.mImage->Release();
|
||||
}
|
||||
mUnit = eCSSUnit_Null;
|
||||
mValue.mInt = 0;
|
||||
@ -234,11 +254,13 @@ public:
|
||||
void SetStringValue(const nsAString& aValue, nsCSSUnit aUnit);
|
||||
void SetColorValue(nscolor aValue);
|
||||
void SetURLValue(nsCSSValue::URL* aURI);
|
||||
void SetImageValue(nsCSSValue::Image* aImage);
|
||||
void SetAutoValue();
|
||||
void SetInheritValue();
|
||||
void SetInitialValue();
|
||||
void SetNoneValue();
|
||||
void SetNormalValue();
|
||||
void StartImageLoad(nsIDocument* aDocument) const; // Not really const, but pretending
|
||||
|
||||
#ifdef DEBUG
|
||||
void AppendToString(nsAString& aBuffer, nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const;
|
||||
@ -282,10 +304,28 @@ public:
|
||||
|
||||
void AddRef() { ++mRefCnt; }
|
||||
void Release() { if (--mRefCnt == 0) delete this; }
|
||||
private:
|
||||
protected:
|
||||
nsrefcnt mRefCnt;
|
||||
};
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsCSSValue::Image)
|
||||
|
||||
struct nsCSSValue::Image : public nsCSSValue::URL {
|
||||
// Not making the constructor and destructor inline because that would
|
||||
// force us to include imgIRequest.h, which leads to REQUIRES hell, since
|
||||
// this header is included all over.
|
||||
Image(nsIURI* aURI, const PRUnichar* aString, nsIDocument* aDocument);
|
||||
~Image();
|
||||
|
||||
// Inherit operator== from nsCSSValue::URL
|
||||
|
||||
nsCOMPtr<imgIRequest> mRequest; // null == image load blocked or somehow failed
|
||||
|
||||
// Override AddRef/Release so we delete ourselves via the right pointer.
|
||||
void AddRef() { ++mRefCnt; }
|
||||
void Release() { if (--mRefCnt == 0) delete this; }
|
||||
};
|
||||
|
||||
protected:
|
||||
nsCSSUnit mUnit;
|
||||
union {
|
||||
@ -294,6 +334,7 @@ protected:
|
||||
PRUnichar* mString;
|
||||
nscolor mColor;
|
||||
URL* mURL;
|
||||
Image* mImage;
|
||||
} mValue;
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,7 @@
|
||||
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
#if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon)
|
||||
#define DEBUG_ComputedDOMStyle
|
||||
@ -723,7 +724,11 @@ nsComputedDOMStyle::GetBackgroundImage(nsIFrame *aFrame,
|
||||
if (color->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) {
|
||||
val->SetIdent(nsLayoutAtoms::none);
|
||||
} else {
|
||||
val->SetURI(color->mBackgroundImage);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (color->mBackgroundImage) {
|
||||
color->mBackgroundImage->GetURI(getter_AddRefs(uri));
|
||||
}
|
||||
val->SetURI(uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "nsSize.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
/*
|
||||
* For storage of an |nsRuleNode|'s children in a linked list.
|
||||
@ -2942,9 +2943,9 @@ nsRuleNode::ComputeBackgroundData(nsStyleStruct* aStartStruct,
|
||||
bg->mBackgroundFlags |= NS_STYLE_BG_COLOR_TRANSPARENT;
|
||||
}
|
||||
|
||||
// background-image: url, none, inherit
|
||||
if (eCSSUnit_URL == colorData.mBackImage.GetUnit()) {
|
||||
bg->mBackgroundImage = colorData.mBackImage.GetURLValue();
|
||||
// background-image: url (stored as image), none, inherit
|
||||
if (eCSSUnit_Image == colorData.mBackImage.GetUnit()) {
|
||||
bg->mBackgroundImage = colorData.mBackImage.GetImageValue();
|
||||
bg->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE;
|
||||
}
|
||||
else if (eCSSUnit_None == colorData.mBackImage.GetUnit()) {
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nsRuleNode.h"
|
||||
#include "nsUnitConversion.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
// #define NOISY_DEBUG
|
||||
@ -532,6 +533,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
URICString(imgIRequest* aImageRequest) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (aImageRequest) {
|
||||
aImageRequest->GetURI(getter_AddRefs(uri));
|
||||
}
|
||||
if (uri) {
|
||||
uri->GetSpec(*this);
|
||||
} else {
|
||||
Assign("[none]");
|
||||
}
|
||||
}
|
||||
|
||||
URICString& operator=(const URICString& aOther) {
|
||||
Assign(aOther);
|
||||
return *this;
|
||||
|
@ -55,6 +55,8 @@
|
||||
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
#include "imgIRequest.h"
|
||||
|
||||
inline PRBool IsFixedUnit(nsStyleUnit aUnit, PRBool aEnumOK)
|
||||
{
|
||||
return PRBool((aUnit == eStyleUnit_Null) ||
|
||||
@ -162,6 +164,22 @@ static PRBool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
|
||||
eq);
|
||||
}
|
||||
|
||||
static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
|
||||
{
|
||||
if (aImage1 == aImage2) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (!aImage1 || !aImage2) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri1, uri2;
|
||||
aImage1->GetURI(getter_AddRefs(uri1));
|
||||
aImage2->GetURI(getter_AddRefs(uri2));
|
||||
return EqualURIs(uri1, uri2);
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleFont
|
||||
//
|
||||
@ -1019,6 +1037,10 @@ nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
|
||||
{
|
||||
}
|
||||
|
||||
nsStyleBackground::~nsStyleBackground()
|
||||
{
|
||||
}
|
||||
|
||||
nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
|
||||
{
|
||||
if (mBackgroundAttachment != aOther.mBackgroundAttachment
|
||||
@ -1036,7 +1058,7 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther)
|
||||
(mBackgroundClip == aOther.mBackgroundClip) &&
|
||||
(mBackgroundInlinePolicy == aOther.mBackgroundInlinePolicy) &&
|
||||
(mBackgroundOrigin == aOther.mBackgroundOrigin) &&
|
||||
EqualURIs(mBackgroundImage, aOther.mBackgroundImage) &&
|
||||
EqualImages(mBackgroundImage, aOther.mBackgroundImage) &&
|
||||
((!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_PERCENT) ||
|
||||
(mBackgroundXPosition.mFloat == aOther.mBackgroundXPosition.mFloat)) &&
|
||||
(!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_LENGTH) ||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nsIURI.h"
|
||||
|
||||
class nsIFrame;
|
||||
class imgIRequest;
|
||||
|
||||
enum nsStyleStructID {
|
||||
|
||||
@ -147,7 +148,7 @@ struct nsStyleColor : public nsStyleStruct {
|
||||
struct nsStyleBackground : public nsStyleStruct {
|
||||
nsStyleBackground(nsIPresContext* aPresContext);
|
||||
nsStyleBackground(const nsStyleBackground& aOther);
|
||||
~nsStyleBackground() {};
|
||||
~nsStyleBackground();
|
||||
|
||||
NS_DEFINE_STATIC_STYLESTRUCTID_ACCESSOR(eStyleStruct_Background)
|
||||
|
||||
@ -183,7 +184,7 @@ struct nsStyleBackground : public nsStyleStruct {
|
||||
mBackgroundYPosition; // [reset]
|
||||
|
||||
nscolor mBackgroundColor; // [reset]
|
||||
nsCOMPtr<nsIURI> mBackgroundImage; // [reset]
|
||||
nsCOMPtr<imgIRequest> mBackgroundImage; // [reset]
|
||||
|
||||
PRBool IsTransparent() const
|
||||
{
|
||||
|
@ -69,5 +69,13 @@ interface imgIRequest : nsIRequest
|
||||
readonly attribute imgIDecoderObserver decoderObserver;
|
||||
|
||||
readonly attribute string mimeType;
|
||||
|
||||
/**
|
||||
* Clone this request; the returned request will have aObserver as the
|
||||
* observer. aObserver will be notified synchronously (before the clone()
|
||||
* call returns) with all the notifications that have already been dispatched
|
||||
* for this image load.
|
||||
*/
|
||||
imgIRequest clone(in imgIDecoderObserver aObserver);
|
||||
};
|
||||
|
||||
|
@ -306,6 +306,32 @@ NS_IMETHODIMP imgRequestProxy::GetMimeType(char **aMimeType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
|
||||
imgIRequest** aClone)
|
||||
{
|
||||
NS_PRECONDITION(aClone, "Null out param");
|
||||
*aClone = nsnull;
|
||||
imgRequestProxy* clone = new imgRequestProxy();
|
||||
if (!clone) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ADDREF(clone);
|
||||
|
||||
// It is important to call |SetLoadFlags()| before calling |Init()| because
|
||||
// |Init()| adds the request to the loadgroup.
|
||||
clone->SetLoadFlags(mLoadFlags);
|
||||
nsresult rv = clone->Init(mOwner, mLoadGroup, aObserver);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(clone);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Send the notifications to the clone's observer
|
||||
mOwner->NotifyProxyListener(clone);
|
||||
|
||||
*aClone = clone;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** imgIContainerObserver methods **/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user