зеркало из https://github.com/mozilla/pjs.git
Bug 697230: Part 1 - Centralize style image observers. r=bz
This commit is contained in:
Родитель
7574f46ad9
Коммит
8abe613d4d
|
@ -116,6 +116,7 @@ class nsIObjectLoadingContent;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace css {
|
namespace css {
|
||||||
class Loader;
|
class Loader;
|
||||||
|
class ImageLoader;
|
||||||
} // namespace css
|
} // namespace css
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -125,8 +126,8 @@ class Element;
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#define NS_IDOCUMENT_IID \
|
#define NS_IDOCUMENT_IID \
|
||||||
{ 0x8e51e6d9, 0x914d, 0x46ba, \
|
{ 0xdb888523, 0x541f, 0x49e3, \
|
||||||
{ 0xb3, 0x11, 0x2f, 0x27, 0x3d, 0xe6, 0x0d, 0x19 } }
|
{ 0xa9, 0x71, 0xb5, 0xea, 0xd1, 0xf0, 0xc3, 0xcf } }
|
||||||
|
|
||||||
|
|
||||||
// Flag for AddStyleSheet().
|
// Flag for AddStyleSheet().
|
||||||
|
@ -643,6 +644,13 @@ public:
|
||||||
return mCSSLoader;
|
return mCSSLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get this document's StyleImageLoader. This is guaranteed to not return null.
|
||||||
|
*/
|
||||||
|
mozilla::css::ImageLoader* StyleImageLoader() const {
|
||||||
|
return mStyleImageLoader;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the channel that was passed to StartDocumentLoad or Reset for this
|
* Get the channel that was passed to StartDocumentLoad or Reset for this
|
||||||
* document. Note that this may be null in some cases (eg if
|
* document. Note that this may be null in some cases (eg if
|
||||||
|
@ -1739,6 +1747,7 @@ protected:
|
||||||
// The cleanup is handled by the nsDocument destructor.
|
// The cleanup is handled by the nsDocument destructor.
|
||||||
nsNodeInfoManager* mNodeInfoManager; // [STRONG]
|
nsNodeInfoManager* mNodeInfoManager; // [STRONG]
|
||||||
mozilla::css::Loader* mCSSLoader; // [STRONG]
|
mozilla::css::Loader* mCSSLoader; // [STRONG]
|
||||||
|
mozilla::css::ImageLoader* mStyleImageLoader; // [STRONG]
|
||||||
nsHTMLStyleSheet* mAttrStyleSheet;
|
nsHTMLStyleSheet* mAttrStyleSheet;
|
||||||
|
|
||||||
// The set of all object, embed, applet, video and audio elements for
|
// The set of all object, embed, applet, video and audio elements for
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIBaseWindow.h"
|
#include "nsIBaseWindow.h"
|
||||||
#include "mozilla/css/Loader.h"
|
#include "mozilla/css/Loader.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
#include "nsIDocShell.h"
|
#include "nsIDocShell.h"
|
||||||
#include "nsIDocShellTreeItem.h"
|
#include "nsIDocShellTreeItem.h"
|
||||||
#include "nsIScriptRuntime.h"
|
#include "nsIScriptRuntime.h"
|
||||||
|
@ -1649,6 +1650,11 @@ nsDocument::~nsDocument()
|
||||||
NS_RELEASE(mCSSLoader);
|
NS_RELEASE(mCSSLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mStyleImageLoader) {
|
||||||
|
mStyleImageLoader->DropDocumentReference();
|
||||||
|
NS_RELEASE(mStyleImageLoader);
|
||||||
|
}
|
||||||
|
|
||||||
// XXX Ideally we'd do this cleanup in the nsIDocument destructor.
|
// XXX Ideally we'd do this cleanup in the nsIDocument destructor.
|
||||||
if (mNodeInfoManager) {
|
if (mNodeInfoManager) {
|
||||||
mNodeInfoManager->DropDocumentReference();
|
mNodeInfoManager->DropDocumentReference();
|
||||||
|
@ -1983,7 +1989,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
nsresult
|
nsresult
|
||||||
nsDocument::Init()
|
nsDocument::Init()
|
||||||
{
|
{
|
||||||
if (mCSSLoader || mNodeInfoManager || mScriptLoader) {
|
if (mCSSLoader || mStyleImageLoader || mNodeInfoManager || mScriptLoader) {
|
||||||
return NS_ERROR_ALREADY_INITIALIZED;
|
return NS_ERROR_ALREADY_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2012,10 +2018,16 @@ nsDocument::Init()
|
||||||
// Assume we're not quirky, until we know otherwise
|
// Assume we're not quirky, until we know otherwise
|
||||||
mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
|
mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||||
|
|
||||||
|
mStyleImageLoader = new mozilla::css::ImageLoader(this);
|
||||||
|
NS_ADDREF(mStyleImageLoader);
|
||||||
|
|
||||||
|
nsresult rv = mStyleImageLoader->Init();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
mNodeInfoManager = new nsNodeInfoManager();
|
mNodeInfoManager = new nsNodeInfoManager();
|
||||||
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
nsresult rv = mNodeInfoManager->Init(this);
|
rv = mNodeInfoManager->Init(this);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// mNodeInfo keeps NodeInfoManager alive!
|
// mNodeInfo keeps NodeInfoManager alive!
|
||||||
|
|
|
@ -107,7 +107,6 @@ CPPSRCS = \
|
||||||
nsFrameManager.cpp \
|
nsFrameManager.cpp \
|
||||||
nsFrameTraversal.cpp \
|
nsFrameTraversal.cpp \
|
||||||
nsGenConList.cpp \
|
nsGenConList.cpp \
|
||||||
nsImageLoader.cpp \
|
|
||||||
nsLayoutDebugger.cpp \
|
nsLayoutDebugger.cpp \
|
||||||
nsLayoutHistoryState.cpp \
|
nsLayoutHistoryState.cpp \
|
||||||
nsLayoutUtils.cpp \
|
nsLayoutUtils.cpp \
|
||||||
|
|
|
@ -84,8 +84,10 @@
|
||||||
#include "gfxDrawable.h"
|
#include "gfxDrawable.h"
|
||||||
|
|
||||||
#include "nsCSSRenderingBorders.h"
|
#include "nsCSSRenderingBorders.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::css;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a small wrapper class to encapsulate image drawing that can draw an
|
* This is a small wrapper class to encapsulate image drawing that can draw an
|
||||||
|
@ -2419,10 +2421,20 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we get invalidated for loads of the image. We need to do
|
// Ensure we get invalidated for loads of the image. If this is not the
|
||||||
// this here because this might be the only code that knows about the
|
// frame's normal style context this is the only code that knows about the
|
||||||
// association of the style data with the frame.
|
// association of the style data with the frame.
|
||||||
aPresContext->SetupBackgroundImageLoaders(aForFrame, bg);
|
if (aBackgroundSC != aForFrame->GetStyleContext()) {
|
||||||
|
ImageLoader* loader = aPresContext->Document()->StyleImageLoader();
|
||||||
|
|
||||||
|
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||||
|
if (bg->mLayers[i].mImage.GetType() == eStyleImageType_Image) {
|
||||||
|
imgIRequest *image = bg->mLayers[i].mImage.GetImageData();
|
||||||
|
|
||||||
|
loader->AssociateRequestToFrame(image, aForFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We can skip painting the background color if a background image is opaque.
|
// We can skip painting the background color if a background image is opaque.
|
||||||
if (drawBackgroundColor &&
|
if (drawBackgroundColor &&
|
||||||
|
@ -2732,9 +2744,11 @@ DrawBorderImage(nsPresContext* aPresContext,
|
||||||
// XXX We shouldn't really... since if anybody is passing in a
|
// XXX We shouldn't really... since if anybody is passing in a
|
||||||
// different style, they'll potentially have the wrong size for the
|
// different style, they'll potentially have the wrong size for the
|
||||||
// border too.
|
// border too.
|
||||||
aPresContext->SetupBorderImageLoaders(aForFrame, &aStyleBorder);
|
|
||||||
|
|
||||||
imgIRequest *req = aStyleBorder.GetBorderImage();
|
imgIRequest *req = aStyleBorder.GetBorderImage();
|
||||||
|
ImageLoader* loader = aPresContext->Document()->StyleImageLoader();
|
||||||
|
|
||||||
|
// If this fails there's not much we can do ...
|
||||||
|
loader->AssociateRequestToFrame(req, aForFrame);
|
||||||
|
|
||||||
// Get the actual image.
|
// Get the actual image.
|
||||||
|
|
||||||
|
|
|
@ -1,284 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
||||||
*
|
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Stuart Parmenter <pavlov@netscape.com>
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
||||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
/* class to notify frames of background image loads */
|
|
||||||
|
|
||||||
#include "nsImageLoader.h"
|
|
||||||
|
|
||||||
#include "imgILoader.h"
|
|
||||||
|
|
||||||
#include "nsIURI.h"
|
|
||||||
#include "nsILoadGroup.h"
|
|
||||||
#include "nsNetUtil.h"
|
|
||||||
|
|
||||||
#include "nsPresContext.h"
|
|
||||||
#include "nsIPresShell.h"
|
|
||||||
#include "nsIFrame.h"
|
|
||||||
#include "nsIContent.h"
|
|
||||||
#include "nsIDocument.h"
|
|
||||||
|
|
||||||
#include "imgIContainer.h"
|
|
||||||
|
|
||||||
#include "nsStyleContext.h"
|
|
||||||
#include "nsGkAtoms.h"
|
|
||||||
#include "nsLayoutUtils.h"
|
|
||||||
|
|
||||||
// Paint forcing
|
|
||||||
#include "prenv.h"
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsImageLoader, imgIDecoderObserver, imgIContainerObserver)
|
|
||||||
|
|
||||||
nsImageLoader::nsImageLoader(nsIFrame *aFrame, PRUint32 aActions,
|
|
||||||
nsImageLoader *aNextLoader)
|
|
||||||
: mFrame(aFrame),
|
|
||||||
mActions(aActions),
|
|
||||||
mNextLoader(aNextLoader),
|
|
||||||
mRequestRegistered(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsImageLoader::~nsImageLoader()
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<nsImageLoader>
|
|
||||||
nsImageLoader::Create(nsIFrame *aFrame, imgIRequest *aRequest,
|
|
||||||
PRUint32 aActions, nsImageLoader *aNextLoader)
|
|
||||||
{
|
|
||||||
nsRefPtr<nsImageLoader> loader =
|
|
||||||
new nsImageLoader(aFrame, aActions, aNextLoader);
|
|
||||||
|
|
||||||
loader->Load(aRequest);
|
|
||||||
|
|
||||||
return loader.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsImageLoader::Destroy()
|
|
||||||
{
|
|
||||||
// Destroy the chain with only one level of recursion.
|
|
||||||
nsRefPtr<nsImageLoader> list = mNextLoader;
|
|
||||||
mNextLoader = nsnull;
|
|
||||||
while (list) {
|
|
||||||
nsRefPtr<nsImageLoader> todestroy = list;
|
|
||||||
list = todestroy->mNextLoader;
|
|
||||||
todestroy->mNextLoader = nsnull;
|
|
||||||
todestroy->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mRequest && mFrame) {
|
|
||||||
nsLayoutUtils::DeregisterImageRequest(mFrame->PresContext(), mRequest,
|
|
||||||
&mRequestRegistered);
|
|
||||||
}
|
|
||||||
|
|
||||||
mFrame = nsnull;
|
|
||||||
|
|
||||||
if (mRequest) {
|
|
||||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mRequest = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsImageLoader::Load(imgIRequest *aImage)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(!mRequest, "can't reuse image loaders");
|
|
||||||
NS_ASSERTION(mFrame, "not initialized");
|
|
||||||
NS_ASSERTION(aImage, "must have non-null image");
|
|
||||||
|
|
||||||
if (!mFrame)
|
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
|
||||||
|
|
||||||
if (!aImage)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
// Deregister mRequest from the refresh driver, since it is no longer
|
|
||||||
// going to be managed by this nsImageLoader.
|
|
||||||
nsPresContext* presContext = mFrame->PresContext();
|
|
||||||
|
|
||||||
nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
|
|
||||||
&mRequestRegistered);
|
|
||||||
|
|
||||||
// Make sure to clone into a temporary, then set mRequest, since
|
|
||||||
// cloning may notify and we don't want to trigger paints from this
|
|
||||||
// code.
|
|
||||||
nsCOMPtr<imgIRequest> newRequest;
|
|
||||||
nsresult rv = aImage->Clone(this, getter_AddRefs(newRequest));
|
|
||||||
mRequest.swap(newRequest);
|
|
||||||
|
|
||||||
if (mRequest) {
|
|
||||||
nsLayoutUtils::RegisterImageRequestIfAnimated(presContext, mRequest,
|
|
||||||
&mRequestRegistered);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsImageLoader::OnStartContainer(imgIRequest *aRequest,
|
|
||||||
imgIContainer *aImage)
|
|
||||||
{
|
|
||||||
NS_ABORT_IF_FALSE(aImage, "Who's calling us then?");
|
|
||||||
|
|
||||||
/* Get requested animation policy from the pres context:
|
|
||||||
* normal = 0
|
|
||||||
* one frame = 1
|
|
||||||
* one loop = 2
|
|
||||||
*/
|
|
||||||
aImage->SetAnimationMode(mFrame->PresContext()->ImageAnimationMode());
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsImageLoader::OnStopFrame(imgIRequest *aRequest,
|
|
||||||
PRUint32 aFrame)
|
|
||||||
{
|
|
||||||
if (!mFrame)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
if (!mRequest) {
|
|
||||||
// We're in the middle of a paint anyway
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take requested actions
|
|
||||||
if (mActions & ACTION_REDRAW_ON_DECODE) {
|
|
||||||
DoRedraw(nsnull);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsImageLoader::OnImageIsAnimated(imgIRequest *aRequest)
|
|
||||||
{
|
|
||||||
// Register with the refresh driver now that we are aware that
|
|
||||||
// we are animated.
|
|
||||||
nsLayoutUtils::RegisterImageRequest(mFrame->PresContext(),
|
|
||||||
aRequest, &mRequestRegistered);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsImageLoader::OnStopRequest(imgIRequest *aRequest,
|
|
||||||
bool aLastPart)
|
|
||||||
{
|
|
||||||
if (!mFrame)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
if (!mRequest) {
|
|
||||||
// We're in the middle of a paint anyway
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take requested actions
|
|
||||||
if (mActions & ACTION_REDRAW_ON_LOAD) {
|
|
||||||
DoRedraw(nsnull);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsImageLoader::FrameChanged(imgIRequest *aRequest,
|
|
||||||
imgIContainer *aContainer,
|
|
||||||
const nsIntRect *aDirtyRect)
|
|
||||||
{
|
|
||||||
if (!mFrame)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
if (!mRequest) {
|
|
||||||
// We're in the middle of a paint anyway
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ASSERTION(aRequest == mRequest, "This is a neat trick.");
|
|
||||||
|
|
||||||
nsRect r = aDirtyRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect()) ?
|
|
||||||
nsRect(nsPoint(0, 0), mFrame->GetSize()) :
|
|
||||||
aDirtyRect->ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
|
|
||||||
|
|
||||||
DoRedraw(&r);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsImageLoader::DoRedraw(const nsRect* aDamageRect)
|
|
||||||
{
|
|
||||||
// NOTE: It is not sufficient to invalidate only the size of the image:
|
|
||||||
// the image may be tiled!
|
|
||||||
// The best option is to call into the frame, however lacking this
|
|
||||||
// we have to at least invalidate the frame's bounds, hence
|
|
||||||
// as long as we have a frame we'll use its size.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Invalidate the entire frame
|
|
||||||
// XXX We really only need to invalidate the client area of the frame...
|
|
||||||
|
|
||||||
nsRect bounds(nsPoint(0, 0), mFrame->GetSize());
|
|
||||||
|
|
||||||
if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
|
|
||||||
// The canvas's background covers the whole viewport.
|
|
||||||
bounds = mFrame->GetVisualOverflowRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX this should be ok, but there is some crappy ass bug causing it not to work
|
|
||||||
// XXX seems related to the "body fixup rule" dealing with the canvas and body frames...
|
|
||||||
#if 0
|
|
||||||
// Invalidate the entire frame only if the frame has a tiled background
|
|
||||||
// image, otherwise just invalidate the intersection of the frame's bounds
|
|
||||||
// with the damaged rect.
|
|
||||||
nsStyleContext* styleContext;
|
|
||||||
mFrame->GetStyleContext(&styleContext);
|
|
||||||
const nsStyleBackground* bg = styleContext->GetStyleBackground();
|
|
||||||
|
|
||||||
if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) ||
|
|
||||||
(bg->mBackgroundRepeat == NS_STYLE_BG_REPEAT_OFF)) {
|
|
||||||
// The frame does not have a background image so we are free
|
|
||||||
// to invalidate only the intersection of the damage rect and
|
|
||||||
// the frame's bounds.
|
|
||||||
|
|
||||||
if (aDamageRect) {
|
|
||||||
bounds.IntersectRect(*aDamageRect, bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mFrame->GetStyleVisibility()->IsVisible()) {
|
|
||||||
mFrame->Invalidate(bounds);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
||||||
*
|
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Stuart Parmenter <pavlov@netscape.com>
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
||||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
/* class to notify frames of background and border image loads */
|
|
||||||
|
|
||||||
#include "nsStubImageDecoderObserver.h"
|
|
||||||
|
|
||||||
class nsIFrame;
|
|
||||||
class nsIURI;
|
|
||||||
|
|
||||||
#include "imgIRequest.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsAutoPtr.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Image loaders pass notifications for background and border image
|
|
||||||
* loading and animation on to the frames.
|
|
||||||
*
|
|
||||||
* Each frame's image loaders form a linked list.
|
|
||||||
*/
|
|
||||||
class nsImageLoader : public nsStubImageDecoderObserver
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
nsImageLoader(nsIFrame *aFrame, PRUint32 aActions,
|
|
||||||
nsImageLoader *aNextLoader);
|
|
||||||
virtual ~nsImageLoader();
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* Flags to specify actions that can be taken for the image at various
|
|
||||||
* times. Reflows always occur before redraws. "Decode" refers to one
|
|
||||||
* frame being available, whereas "load" refers to all the data being loaded
|
|
||||||
* from the network.
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
ACTION_REDRAW_ON_DECODE = 0x01,
|
|
||||||
ACTION_REDRAW_ON_LOAD = 0x02,
|
|
||||||
};
|
|
||||||
static already_AddRefed<nsImageLoader>
|
|
||||||
Create(nsIFrame *aFrame, imgIRequest *aRequest,
|
|
||||||
PRUint32 aActions, nsImageLoader *aNextLoader);
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
|
|
||||||
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
|
||||||
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
|
|
||||||
NS_IMETHOD OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame);
|
|
||||||
NS_IMETHOD OnStopRequest(imgIRequest *aRequest, bool aLastPart);
|
|
||||||
NS_IMETHOD OnImageIsAnimated(imgIRequest *aRequest);
|
|
||||||
// Do not override OnDataAvailable since background images are not
|
|
||||||
// displayed incrementally; they are displayed after the entire image
|
|
||||||
// has been loaded.
|
|
||||||
// Note: Images referenced by the <img> element are displayed
|
|
||||||
// incrementally in nsImageFrame.cpp.
|
|
||||||
|
|
||||||
// imgIContainerObserver (override nsStubImageDecoderObserver)
|
|
||||||
NS_IMETHOD FrameChanged(imgIRequest *aRequest,
|
|
||||||
imgIContainer *aContainer,
|
|
||||||
const nsIntRect *aDirtyRect);
|
|
||||||
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
imgIRequest *GetRequest() { return mRequest; }
|
|
||||||
nsImageLoader *GetNextLoader() { return mNextLoader; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsresult Load(imgIRequest *aImage);
|
|
||||||
/* if aDamageRect is nsnull, the whole frame is redrawn. */
|
|
||||||
void DoRedraw(const nsRect* aDamageRect);
|
|
||||||
|
|
||||||
nsIFrame *mFrame;
|
|
||||||
nsCOMPtr<imgIRequest> mRequest;
|
|
||||||
PRUint32 mActions;
|
|
||||||
nsRefPtr<nsImageLoader> mNextLoader;
|
|
||||||
|
|
||||||
// This is a boolean flag indicating whether or not the current image request
|
|
||||||
// has been registered with the refresh driver.
|
|
||||||
bool mRequestRegistered;
|
|
||||||
};
|
|
|
@ -48,7 +48,6 @@
|
||||||
#include "nsIContentViewer.h"
|
#include "nsIContentViewer.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsStyleSet.h"
|
#include "nsStyleSet.h"
|
||||||
#include "nsImageLoader.h"
|
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsIURL.h"
|
#include "nsIURL.h"
|
||||||
|
@ -97,6 +96,7 @@
|
||||||
#include "FrameLayerBuilder.h"
|
#include "FrameLayerBuilder.h"
|
||||||
#include "nsDOMMediaQueryList.h"
|
#include "nsDOMMediaQueryList.h"
|
||||||
#include "nsSMILAnimationController.h"
|
#include "nsSMILAnimationController.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
|
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
#include "nsBidiPresUtils.h"
|
#include "nsBidiPresUtils.h"
|
||||||
|
@ -194,14 +194,6 @@ IsVisualCharset(const nsCString& aCharset)
|
||||||
}
|
}
|
||||||
#endif // IBMBIDI
|
#endif // IBMBIDI
|
||||||
|
|
||||||
|
|
||||||
static PLDHashOperator
|
|
||||||
destroy_loads(nsIFrame* aKey, nsRefPtr<nsImageLoader>& aData, void* closure)
|
|
||||||
{
|
|
||||||
aData->Destroy();
|
|
||||||
return PL_DHASH_NEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "nsContentCID.h"
|
#include "nsContentCID.h"
|
||||||
|
|
||||||
// NOTE! nsPresContext::operator new() zeroes out all members, so don't
|
// NOTE! nsPresContext::operator new() zeroes out all members, so don't
|
||||||
|
@ -343,28 +335,12 @@ NS_INTERFACE_MAP_END
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPresContext)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPresContext)
|
||||||
|
|
||||||
static PLDHashOperator
|
|
||||||
TraverseImageLoader(nsIFrame* aKey, nsRefPtr<nsImageLoader>& aData,
|
|
||||||
void* aClosure)
|
|
||||||
{
|
|
||||||
nsCycleCollectionTraversalCallback *cb =
|
|
||||||
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
|
||||||
|
|
||||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mImageLoaders[i] item");
|
|
||||||
cb->NoteXPCOMChild(aData);
|
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument);
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument);
|
||||||
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // not xpcom
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // not xpcom
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mEventManager, nsIObserver);
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mEventManager, nsIObserver);
|
||||||
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
|
||||||
|
|
||||||
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
|
||||||
tmp->mImageLoaders[i].Enumerate(TraverseImageLoader, &cb);
|
|
||||||
|
|
||||||
// We own only the items in mDOMMediaQueryLists that have listeners;
|
// We own only the items in mDOMMediaQueryLists that have listeners;
|
||||||
// this reference is managed by their AddListener and RemoveListener
|
// this reference is managed by their AddListener and RemoveListener
|
||||||
// methods.
|
// methods.
|
||||||
|
@ -953,10 +929,6 @@ nsPresContext::Init(nsDeviceContext* aDeviceContext)
|
||||||
mDeviceContext->FlushFontCache();
|
mDeviceContext->FlushFontCache();
|
||||||
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
||||||
|
|
||||||
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
|
||||||
if (!mImageLoaders[i].Init())
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
mEventManager = new nsEventStateManager();
|
mEventManager = new nsEventStateManager();
|
||||||
NS_ADDREF(mEventManager);
|
NS_ADDREF(mEventManager);
|
||||||
|
|
||||||
|
@ -1130,18 +1102,6 @@ nsPresContext::SetShell(nsIPresShell* aShell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsPresContext::DestroyImageLoaders()
|
|
||||||
{
|
|
||||||
// Destroy image loaders. This is important to do when frames are being
|
|
||||||
// destroyed because imageloaders can have pointers to frames and we don't
|
|
||||||
// want those pointers to outlive the destruction of the frame arena.
|
|
||||||
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i) {
|
|
||||||
mImageLoaders[i].Enumerate(destroy_loads, nsnull);
|
|
||||||
mImageLoaders[i].Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPresContext::DoChangeCharSet(const nsCString& aCharSet)
|
nsPresContext::DoChangeCharSet(const nsCString& aCharSet)
|
||||||
{
|
{
|
||||||
|
@ -1252,18 +1212,6 @@ static void SetImgAnimModeOnImgReq(imgIRequest* aImgReq, PRUint16 aMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumeration call back for HashTable
|
|
||||||
static PLDHashOperator
|
|
||||||
set_animation_mode(nsIFrame* aKey, nsRefPtr<nsImageLoader>& aData, void* closure)
|
|
||||||
{
|
|
||||||
for (nsImageLoader *loader = aData; loader;
|
|
||||||
loader = loader->GetNextLoader()) {
|
|
||||||
imgIRequest* imgReq = loader->GetRequest();
|
|
||||||
SetImgAnimModeOnImgReq(imgReq, (PRUint16)NS_PTR_TO_INT32(closure));
|
|
||||||
}
|
|
||||||
return PL_DHASH_NEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IMPORTANT: Assumption is that all images for a Presentation
|
// IMPORTANT: Assumption is that all images for a Presentation
|
||||||
// have the same Animation Mode (pavlov said this was OK)
|
// have the same Animation Mode (pavlov said this was OK)
|
||||||
//
|
//
|
||||||
|
@ -1318,15 +1266,13 @@ nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode)
|
||||||
if (!IsDynamic())
|
if (!IsDynamic())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set the mode on the image loaders.
|
|
||||||
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
|
||||||
mImageLoaders[i].Enumerate(set_animation_mode, NS_INT32_TO_PTR(aMode));
|
|
||||||
|
|
||||||
// Now walk the content tree and set the animation mode
|
// Now walk the content tree and set the animation mode
|
||||||
// on all the images.
|
// on all the images.
|
||||||
if (mShell != nsnull) {
|
if (mShell != nsnull) {
|
||||||
nsIDocument *doc = mShell->GetDocument();
|
nsIDocument *doc = mShell->GetDocument();
|
||||||
if (doc) {
|
if (doc) {
|
||||||
|
doc->StyleImageLoader()->SetAnimationMode(aMode);
|
||||||
|
|
||||||
Element *rootElement = doc->GetRootElement();
|
Element *rootElement = doc->GetRootElement();
|
||||||
if (rootElement) {
|
if (rootElement) {
|
||||||
SetImgAnimations(rootElement, aMode);
|
SetImgAnimations(rootElement, aMode);
|
||||||
|
@ -1412,68 +1358,6 @@ nsPresContext::SetFullZoom(float aZoom)
|
||||||
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsPresContext::SetImageLoaders(nsIFrame* aTargetFrame,
|
|
||||||
ImageLoadType aType,
|
|
||||||
nsImageLoader* aImageLoaders)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(mShell || !aImageLoaders,
|
|
||||||
"Shouldn't add new image loader after the shell is gone");
|
|
||||||
|
|
||||||
nsRefPtr<nsImageLoader> oldLoaders;
|
|
||||||
mImageLoaders[aType].Get(aTargetFrame, getter_AddRefs(oldLoaders));
|
|
||||||
|
|
||||||
if (aImageLoaders) {
|
|
||||||
mImageLoaders[aType].Put(aTargetFrame, aImageLoaders);
|
|
||||||
} else if (oldLoaders) {
|
|
||||||
mImageLoaders[aType].Remove(aTargetFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldLoaders)
|
|
||||||
oldLoaders->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsPresContext::SetupBackgroundImageLoaders(nsIFrame* aFrame,
|
|
||||||
const nsStyleBackground* aStyleBackground)
|
|
||||||
{
|
|
||||||
nsRefPtr<nsImageLoader> loaders;
|
|
||||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, aStyleBackground) {
|
|
||||||
if (aStyleBackground->mLayers[i].mImage.GetType() == eStyleImageType_Image) {
|
|
||||||
PRUint32 actions = nsImageLoader::ACTION_REDRAW_ON_DECODE;
|
|
||||||
imgIRequest *image = aStyleBackground->mLayers[i].mImage.GetImageData();
|
|
||||||
loaders = nsImageLoader::Create(aFrame, image, actions, loaders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetImageLoaders(aFrame, BACKGROUND_IMAGE, loaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsPresContext::SetupBorderImageLoaders(nsIFrame* aFrame,
|
|
||||||
const nsStyleBorder* aStyleBorder)
|
|
||||||
{
|
|
||||||
// We get called the first time we try to draw a border-image, and
|
|
||||||
// also when the border image changes (including when it changes from
|
|
||||||
// non-null to null).
|
|
||||||
imgIRequest *borderImage = aStyleBorder->GetBorderImage();
|
|
||||||
if (!borderImage) {
|
|
||||||
SetImageLoaders(aFrame, BORDER_IMAGE, nsnull);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 actions = nsImageLoader::ACTION_REDRAW_ON_LOAD;
|
|
||||||
nsRefPtr<nsImageLoader> loader =
|
|
||||||
nsImageLoader::Create(aFrame, borderImage, actions, nsnull);
|
|
||||||
SetImageLoaders(aFrame, BORDER_IMAGE, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsPresContext::StopImagesFor(nsIFrame* aTargetFrame)
|
|
||||||
{
|
|
||||||
for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
|
|
||||||
SetImageLoaders(aTargetFrame, ImageLoadType(i), nsnull);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPresContext::SetContainer(nsISupports* aHandler)
|
nsPresContext::SetContainer(nsISupports* aHandler)
|
||||||
{
|
{
|
||||||
|
@ -2180,6 +2064,8 @@ NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
|
||||||
void
|
void
|
||||||
nsPresContext::NotifyDidPaintForSubtree()
|
nsPresContext::NotifyDidPaintForSubtree()
|
||||||
{
|
{
|
||||||
|
Document()->StyleImageLoader()->NotifyPaint();
|
||||||
|
|
||||||
if (!mFireAfterPaintEvents)
|
if (!mFireAfterPaintEvents)
|
||||||
return;
|
return;
|
||||||
mFireAfterPaintEvents = false;
|
mFireAfterPaintEvents = false;
|
||||||
|
|
|
@ -74,7 +74,6 @@
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "prclist.h"
|
#include "prclist.h"
|
||||||
|
|
||||||
class nsImageLoader;
|
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
class nsBidiPresUtils;
|
class nsBidiPresUtils;
|
||||||
#endif // IBMBIDI
|
#endif // IBMBIDI
|
||||||
|
@ -384,49 +383,6 @@ public:
|
||||||
bool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
|
bool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
|
||||||
PRUint8 GetFocusRingStyle() const { return mFocusRingStyle; }
|
PRUint8 GetFocusRingStyle() const { return mFocusRingStyle; }
|
||||||
|
|
||||||
/**
|
|
||||||
* The types of image load types that the pres context needs image
|
|
||||||
* loaders to track invalidation for.
|
|
||||||
*/
|
|
||||||
enum ImageLoadType {
|
|
||||||
BACKGROUND_IMAGE,
|
|
||||||
BORDER_IMAGE,
|
|
||||||
IMAGE_LOAD_TYPE_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the list of image loaders that track invalidation for a
|
|
||||||
* specific frame and type of image. This list will replace any
|
|
||||||
* previous list for that frame and image type (and null will remove
|
|
||||||
* any previous list).
|
|
||||||
*/
|
|
||||||
NS_HIDDEN_(void) SetImageLoaders(nsIFrame* aTargetFrame,
|
|
||||||
ImageLoadType aType,
|
|
||||||
nsImageLoader* aImageLoaders);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an appropriate SetImageLoaders call (including potentially
|
|
||||||
* with null aImageLoaders) given that aFrame draws its background
|
|
||||||
* based on aStyleBackground.
|
|
||||||
*/
|
|
||||||
NS_HIDDEN_(void) SetupBackgroundImageLoaders(nsIFrame* aFrame,
|
|
||||||
const nsStyleBackground*
|
|
||||||
aStyleBackground);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an appropriate SetImageLoaders call (including potentially
|
|
||||||
* with null aImageLoaders) given that aFrame draws its border
|
|
||||||
* based on aStyleBorder.
|
|
||||||
*/
|
|
||||||
NS_HIDDEN_(void) SetupBorderImageLoaders(nsIFrame* aFrame,
|
|
||||||
const nsStyleBorder* aStyleBorder);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when a frame is being destroyed to
|
|
||||||
* ensure that the image loads get disassociated from the prescontext
|
|
||||||
*/
|
|
||||||
NS_HIDDEN_(void) StopImagesFor(nsIFrame* aTargetFrame);
|
|
||||||
|
|
||||||
NS_HIDDEN_(void) SetContainer(nsISupports* aContainer);
|
NS_HIDDEN_(void) SetContainer(nsISupports* aContainer);
|
||||||
|
|
||||||
virtual NS_HIDDEN_(already_AddRefed<nsISupports>) GetContainerExternal() const;
|
virtual NS_HIDDEN_(already_AddRefed<nsISupports>) GetContainerExternal() const;
|
||||||
|
@ -953,8 +909,6 @@ public:
|
||||||
}
|
}
|
||||||
inline void ForgetUpdatePluginGeometryFrame(nsIFrame* aFrame);
|
inline void ForgetUpdatePluginGeometryFrame(nsIFrame* aFrame);
|
||||||
|
|
||||||
void DestroyImageLoaders();
|
|
||||||
|
|
||||||
bool GetContainsUpdatePluginGeometryFrame()
|
bool GetContainsUpdatePluginGeometryFrame()
|
||||||
{
|
{
|
||||||
return mContainsUpdatePluginGeometryFrame;
|
return mContainsUpdatePluginGeometryFrame;
|
||||||
|
@ -1131,10 +1085,6 @@ public:
|
||||||
nscoord mCurrentInflationContainerWidth;
|
nscoord mCurrentInflationContainerWidth;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsRefPtrHashtable<nsPtrHashKey<nsIFrame>, nsImageLoader>
|
|
||||||
mImageLoaders[IMAGE_LOAD_TYPE_COUNT];
|
|
||||||
|
|
||||||
nsWeakPtr mContainer;
|
nsWeakPtr mContainer;
|
||||||
|
|
||||||
PRCList mDOMMediaQueryLists;
|
PRCList mDOMMediaQueryLists;
|
||||||
|
|
|
@ -154,6 +154,7 @@
|
||||||
#include "nsHTMLMediaElement.h"
|
#include "nsHTMLMediaElement.h"
|
||||||
#endif
|
#endif
|
||||||
#include "nsSMILAnimationController.h"
|
#include "nsSMILAnimationController.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
|
|
||||||
#include "nsRefreshDriver.h"
|
#include "nsRefreshDriver.h"
|
||||||
|
|
||||||
|
@ -2112,11 +2113,10 @@ PresShell::FireResizeEvent()
|
||||||
void
|
void
|
||||||
PresShell::SetIgnoreFrameDestruction(bool aIgnore)
|
PresShell::SetIgnoreFrameDestruction(bool aIgnore)
|
||||||
{
|
{
|
||||||
if (mPresContext) {
|
if (mDocument) {
|
||||||
// We need to destroy the image loaders first, as they won't be
|
// We need to tell the ImageLoader to drop all its references to frames
|
||||||
// notified when frames are destroyed once this setting takes effect.
|
// because they're about to go away and it won't get notifications of that.
|
||||||
// (See bug 673984)
|
mDocument->StyleImageLoader()->ClearAll();
|
||||||
mPresContext->DestroyImageLoaders();
|
|
||||||
}
|
}
|
||||||
mIgnoreFrameDestruction = aIgnore;
|
mIgnoreFrameDestruction = aIgnore;
|
||||||
}
|
}
|
||||||
|
@ -2129,7 +2129,7 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
|
||||||
mPresContext->ForgetUpdatePluginGeometryFrame(aFrame);
|
mPresContext->ForgetUpdatePluginGeometryFrame(aFrame);
|
||||||
|
|
||||||
if (!mIgnoreFrameDestruction) {
|
if (!mIgnoreFrameDestruction) {
|
||||||
mPresContext->StopImagesFor(aFrame);
|
mDocument->StyleImageLoader()->DropRequestsForFrame(aFrame);
|
||||||
|
|
||||||
mFrameConstructor->NotifyDestroyingFrame(aFrame);
|
mFrameConstructor->NotifyDestroyingFrame(aFrame);
|
||||||
|
|
||||||
|
|
|
@ -129,10 +129,12 @@
|
||||||
|
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/LookAndFeel.h"
|
#include "mozilla/LookAndFeel.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::layers;
|
using namespace mozilla::layers;
|
||||||
using namespace mozilla::layout;
|
using namespace mozilla::layout;
|
||||||
|
using namespace mozilla::css;
|
||||||
|
|
||||||
// Struct containing cached metrics for box-wrapped frames.
|
// Struct containing cached metrics for box-wrapped frames.
|
||||||
struct nsBoxLayoutMetrics
|
struct nsBoxLayoutMetrics
|
||||||
|
@ -707,6 +709,8 @@ EqualImages(imgIRequest *aOldImage, imgIRequest *aNewImage)
|
||||||
/* virtual */ void
|
/* virtual */ void
|
||||||
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
{
|
{
|
||||||
|
ImageLoader* imageLoader = PresContext()->Document()->StyleImageLoader();
|
||||||
|
|
||||||
if (aOldStyleContext) {
|
if (aOldStyleContext) {
|
||||||
// If the old context had a background image image and new context
|
// If the old context had a background image image and new context
|
||||||
// does not have the same image, clear the image load notifier
|
// does not have the same image, clear the image load notifier
|
||||||
|
@ -719,13 +723,30 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
const nsStyleBackground *oldBG = aOldStyleContext->GetStyleBackground();
|
const nsStyleBackground *oldBG = aOldStyleContext->GetStyleBackground();
|
||||||
const nsStyleBackground *newBG = GetStyleBackground();
|
const nsStyleBackground *newBG = GetStyleBackground();
|
||||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, oldBG) {
|
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, oldBG) {
|
||||||
|
// If there is an image in oldBG that's not in newBG, drop it.
|
||||||
if (i >= newBG->mImageCount ||
|
if (i >= newBG->mImageCount ||
|
||||||
oldBG->mLayers[i].mImage != newBG->mLayers[i].mImage) {
|
oldBG->mLayers[i].mImage != newBG->mLayers[i].mImage) {
|
||||||
// stop the image loading for the frame, the image has changed
|
const nsStyleImage& oldImage = oldBG->mLayers[i].mImage;
|
||||||
PresContext()->SetImageLoaders(this,
|
if (oldImage.GetType() != eStyleImageType_Image) {
|
||||||
nsPresContext::BACKGROUND_IMAGE, nsnull);
|
continue;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
imageLoader->DisassociateRequestFromFrame(oldImage.GetImageData(),
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, newBG) {
|
||||||
|
// If there is an image in newBG that's not in oldBG, add it.
|
||||||
|
if (i >= oldBG->mImageCount ||
|
||||||
|
newBG->mLayers[i].mImage != oldBG->mLayers[i].mImage) {
|
||||||
|
const nsStyleImage& newImage = newBG->mLayers[i].mImage;
|
||||||
|
if (newImage.GetType() != eStyleImageType_Image) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageLoader->AssociateRequestToFrame(newImage.GetImageData(), this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we detect a change on margin, padding or border, we store the old
|
// If we detect a change on margin, padding or border, we store the old
|
||||||
|
@ -766,6 +787,7 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
imgIRequest *oldBorderImage = aOldStyleContext
|
imgIRequest *oldBorderImage = aOldStyleContext
|
||||||
? aOldStyleContext->GetStyleBorder()->GetBorderImage()
|
? aOldStyleContext->GetStyleBorder()->GetBorderImage()
|
||||||
: nsnull;
|
: nsnull;
|
||||||
|
imgIRequest *newBorderImage = GetStyleBorder()->GetBorderImage();
|
||||||
// For border-images, we can't be as conservative (we need to set the
|
// For border-images, we can't be as conservative (we need to set the
|
||||||
// new loaders if there has been any change) since the CalcDifference
|
// new loaders if there has been any change) since the CalcDifference
|
||||||
// call depended on the result of GetActualBorder() and that result
|
// call depended on the result of GetActualBorder() and that result
|
||||||
|
@ -779,9 +801,14 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
// is loaded) and paint. We also don't really care about any callers
|
// is loaded) and paint. We also don't really care about any callers
|
||||||
// who try to paint borders with a different style context, because
|
// who try to paint borders with a different style context, because
|
||||||
// they won't have the correct size for the border either.
|
// they won't have the correct size for the border either.
|
||||||
if (!EqualImages(oldBorderImage, GetStyleBorder()->GetBorderImage())) {
|
if (!EqualImages(oldBorderImage, newBorderImage)) {
|
||||||
// stop and restart the image loading/notification
|
// stop and restart the image loading/notification
|
||||||
PresContext()->SetupBorderImageLoaders(this, GetStyleBorder());
|
if (oldBorderImage) {
|
||||||
|
imageLoader->DisassociateRequestFromFrame(oldBorderImage, this);
|
||||||
|
}
|
||||||
|
if (newBorderImage) {
|
||||||
|
imageLoader->AssociateRequestToFrame(newBorderImage, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the page contains markup that overrides text direction, and
|
// If the page contains markup that overrides text direction, and
|
||||||
|
|
|
@ -0,0 +1,449 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* A class that handles style system image loads (other image loads are handled
|
||||||
|
* by the nodes in the content tree).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsLayoutUtils.h"
|
||||||
|
#include "nsNetError.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace css {
|
||||||
|
|
||||||
|
/* static */ PLDHashOperator
|
||||||
|
ImageLoader::SetAnimationModeEnumerator(nsISupports* aKey, FrameSet* aValue,
|
||||||
|
void* aClosure)
|
||||||
|
{
|
||||||
|
imgIRequest* request = static_cast<imgIRequest*>(aKey);
|
||||||
|
|
||||||
|
PRUint16* mode = static_cast<PRUint16*>(aClosure);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
nsCOMPtr<imgIRequest> debugRequest = do_QueryInterface(aKey);
|
||||||
|
NS_ASSERTION(debugRequest == request, "This is bad");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nsCOMPtr<imgIContainer> container;
|
||||||
|
request->GetImage(getter_AddRefs(container));
|
||||||
|
if (!container) {
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This can fail if the image is in error, and we don't care.
|
||||||
|
container->SetAnimationMode(*mode);
|
||||||
|
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ImageLoader::Init()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mDocument);
|
||||||
|
|
||||||
|
if (!mRequestToFrameMap.Init() ||
|
||||||
|
!mFrameToRequestMap.Init() ||
|
||||||
|
!mImages.Init()) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::DropDocumentReference()
|
||||||
|
{
|
||||||
|
ClearAll();
|
||||||
|
mDocument = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest,
|
||||||
|
nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mRequestToFrameMap.IsInitialized() &&
|
||||||
|
mFrameToRequestMap.IsInitialized() &&
|
||||||
|
mImages.IsInitialized());
|
||||||
|
|
||||||
|
nsCOMPtr<imgIDecoderObserver> observer;
|
||||||
|
aRequest->GetDecoderObserver(getter_AddRefs(observer));
|
||||||
|
if (!observer) {
|
||||||
|
// 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.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(observer == this);
|
||||||
|
|
||||||
|
FrameSet* frameSet = nsnull;
|
||||||
|
if (mRequestToFrameMap.Get(aRequest, &frameSet)) {
|
||||||
|
NS_ASSERTION(frameSet, "This should never be null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!frameSet) {
|
||||||
|
nsAutoPtr<FrameSet> newFrameSet(new FrameSet());
|
||||||
|
|
||||||
|
bool result = mRequestToFrameMap.Put(aRequest, newFrameSet);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameSet = newFrameSet.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestSet* requestSet = nsnull;
|
||||||
|
if (mFrameToRequestMap.Get(aFrame, &requestSet)) {
|
||||||
|
NS_ASSERTION(requestSet, "This should never be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestSet) {
|
||||||
|
nsAutoPtr<RequestSet> newRequestSet(new RequestSet());
|
||||||
|
|
||||||
|
bool result = mFrameToRequestMap.Put(aFrame, newRequestSet);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestSet = newRequestSet.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add these to the sets, but only if they're not already there.
|
||||||
|
PRUint32 i;
|
||||||
|
if (!frameSet->GreatestIndexLtEq(aFrame, i)) {
|
||||||
|
frameSet->InsertElementAt(i, aFrame);
|
||||||
|
}
|
||||||
|
if (!requestSet->GreatestIndexLtEq(aRequest, i)) {
|
||||||
|
requestSet->InsertElementAt(i, aRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::MaybeRegisterCSSImage(nsCSSValue::Image* aImage)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aImage, "This should never be null!");
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
aImage->mRequests.GetWeak(mDocument, &found);
|
||||||
|
if (found) {
|
||||||
|
// This document already has a request.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgIRequest* canonicalRequest = aImage->mRequests.GetWeak(nsnull);
|
||||||
|
if (!canonicalRequest) {
|
||||||
|
// The image was blocked or something.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<imgIRequest> 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->Clone(this, getter_AddRefs(request));
|
||||||
|
mInClone = false;
|
||||||
|
|
||||||
|
aImage->mRequests.Put(mDocument, request);
|
||||||
|
|
||||||
|
AddImage(aImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::DeregisterCSSImage(nsCSSValue::Image* aImage)
|
||||||
|
{
|
||||||
|
RemoveImage(aImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::DisassociateRequestFromFrame(imgIRequest* aRequest,
|
||||||
|
nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
FrameSet* frameSet = nsnull;
|
||||||
|
RequestSet* requestSet = nsnull;
|
||||||
|
|
||||||
|
MOZ_ASSERT(mRequestToFrameMap.IsInitialized() &&
|
||||||
|
mFrameToRequestMap.IsInitialized() &&
|
||||||
|
mImages.IsInitialized());
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
nsCOMPtr<imgIDecoderObserver> observer;
|
||||||
|
aRequest->GetDecoderObserver(getter_AddRefs(observer));
|
||||||
|
MOZ_ASSERT(!observer || observer == this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mRequestToFrameMap.Get(aRequest, &frameSet);
|
||||||
|
mFrameToRequestMap.Get(aFrame, &requestSet);
|
||||||
|
|
||||||
|
if (frameSet) {
|
||||||
|
frameSet->RemoveElementSorted(aFrame);
|
||||||
|
}
|
||||||
|
if (requestSet) {
|
||||||
|
requestSet->RemoveElementSorted(aRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameSet && !frameSet->Length()) {
|
||||||
|
mRequestToFrameMap.Remove(aRequest);
|
||||||
|
|
||||||
|
nsPresContext* presContext = GetPresContext();
|
||||||
|
if (presContext) {
|
||||||
|
nsLayoutUtils::DeregisterImageRequest(presContext,
|
||||||
|
aRequest,
|
||||||
|
nsnull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestSet && !requestSet->Length()) {
|
||||||
|
mFrameToRequestMap.Remove(aFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::DropRequestsForFrame(nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
RequestSet* requestSet = nsnull;
|
||||||
|
if (!mFrameToRequestMap.Get(aFrame, &requestSet)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(requestSet, "This should never be null");
|
||||||
|
|
||||||
|
RequestSet frozenRequestSet(*requestSet);
|
||||||
|
for (RequestSet::size_type i = frozenRequestSet.Length(); i != 0; --i) {
|
||||||
|
imgIRequest* request = frozenRequestSet.ElementAt(i - 1);
|
||||||
|
|
||||||
|
DisassociateRequestFromFrame(request, aFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::SetAnimationMode(PRUint16 aMode)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aMode == imgIContainer::kNormalAnimMode ||
|
||||||
|
aMode == imgIContainer::kDontAnimMode ||
|
||||||
|
aMode == imgIContainer::kLoopOnceAnimMode,
|
||||||
|
"Wrong Animation Mode is being set!");
|
||||||
|
|
||||||
|
mRequestToFrameMap.EnumerateRead(SetAnimationModeEnumerator, &aMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
ClearImageHashSet(nsPtrHashKey<nsCSSValue::Image>* aKey, void* aClosure)
|
||||||
|
{
|
||||||
|
nsIDocument* doc = static_cast<nsIDocument*>(aClosure);
|
||||||
|
nsCSSValue::Image* image = aKey->GetKey();
|
||||||
|
|
||||||
|
imgIRequest* request = image->mRequests.GetWeak(doc);
|
||||||
|
if (request) {
|
||||||
|
request->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
image->mRequests.Remove(doc);
|
||||||
|
|
||||||
|
return PL_DHASH_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::ClearAll()
|
||||||
|
{
|
||||||
|
mRequestToFrameMap.Clear();
|
||||||
|
mFrameToRequestMap.Clear();
|
||||||
|
mImages.EnumerateEntries(&ClearImageHashSet, mDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::LoadImage(nsIURI* aURI, nsIPrincipal* aOriginPrincipal,
|
||||||
|
nsIURI* aReferrer, nsCSSValue::Image* aImage)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aImage->mRequests.Count() == 0, "Huh?");
|
||||||
|
|
||||||
|
aImage->mRequests.Put(nsnull, nsnull);
|
||||||
|
|
||||||
|
if (!aURI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nsContentUtils::CanLoadImage(aURI, mDocument, mDocument,
|
||||||
|
aOriginPrincipal)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<imgIRequest> request;
|
||||||
|
nsContentUtils::LoadImage(aURI, mDocument, aOriginPrincipal, aReferrer,
|
||||||
|
nsnull, nsIRequest::LOAD_NORMAL,
|
||||||
|
getter_AddRefs(request));
|
||||||
|
|
||||||
|
if (!request) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<imgIRequest> clonedRequest;
|
||||||
|
mInClone = true;
|
||||||
|
nsresult rv = request->Clone(this, getter_AddRefs(clonedRequest));
|
||||||
|
mInClone = false;
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aImage->mRequests.Put(nsnull, request);
|
||||||
|
aImage->mRequests.Put(mDocument, clonedRequest);
|
||||||
|
|
||||||
|
AddImage(aImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::AddImage(nsCSSValue::Image* aImage)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(!mImages.Contains(aImage), "Huh?");
|
||||||
|
if (!mImages.PutEntry(aImage)) {
|
||||||
|
NS_RUNTIMEABORT("OOM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::RemoveImage(nsCSSValue::Image* aImage)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mImages.Contains(aImage), "Huh?");
|
||||||
|
mImages.RemoveEntry(aImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsPresContext*
|
||||||
|
ImageLoader::GetPresContext()
|
||||||
|
{
|
||||||
|
if (!mDocument) {
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIPresShell* shell = mDocument->GetShell();
|
||||||
|
if (!shell) {
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shell->GetPresContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::DoRedraw(FrameSet* aFrameSet)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFrameSet, "Must have a frame set");
|
||||||
|
NS_ASSERTION(mDocument, "Should have returned earlier!");
|
||||||
|
NS_ASSERTION(mHavePainted, "Should have returned earlier!");
|
||||||
|
|
||||||
|
FrameSet::size_type length = aFrameSet->Length();
|
||||||
|
for (FrameSet::size_type i = 0; i < length; i++) {
|
||||||
|
nsIFrame* frame = aFrameSet->ElementAt(i);
|
||||||
|
|
||||||
|
// NOTE: It is not sufficient to invalidate only the size of the image:
|
||||||
|
// the image may be tiled!
|
||||||
|
// The best option is to call into the frame, however lacking this
|
||||||
|
// we have to at least invalidate the frame's bounds, hence
|
||||||
|
// as long as we have a frame we'll use its size.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Invalidate the entire frame
|
||||||
|
// XXX We really only need to invalidate the client area of the frame...
|
||||||
|
|
||||||
|
nsRect bounds(nsPoint(0, 0), frame->GetSize());
|
||||||
|
|
||||||
|
if (frame->GetType() == nsGkAtoms::canvasFrame) {
|
||||||
|
// The canvas's background covers the whole viewport.
|
||||||
|
bounds = frame->GetVisualOverflowRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame->GetStyleVisibility()->IsVisible()) {
|
||||||
|
frame->Invalidate(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF(ImageLoader)
|
||||||
|
NS_IMPL_RELEASE(ImageLoader)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(ImageLoader)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(imgIContainerObserver)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ImageLoader::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage)
|
||||||
|
{
|
||||||
|
nsPresContext* presContext = GetPresContext();
|
||||||
|
if (!presContext) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
aImage->SetAnimationMode(presContext->ImageAnimationMode());
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ImageLoader::OnImageIsAnimated(imgIRequest* aRequest)
|
||||||
|
{
|
||||||
|
// NB: Don't ignore this when cloning, it's our only chance to register
|
||||||
|
// the request with the refresh driver.
|
||||||
|
if (!mDocument) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register with the refresh driver now that we are aware that
|
||||||
|
// we are animated.
|
||||||
|
nsPresContext* presContext = GetPresContext();
|
||||||
|
if (presContext) {
|
||||||
|
nsLayoutUtils::RegisterImageRequest(presContext,
|
||||||
|
aRequest,
|
||||||
|
nsnull);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ImageLoader::OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame)
|
||||||
|
{
|
||||||
|
if (!mDocument || !mHavePainted || mInClone) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameSet* frameSet = nsnull;
|
||||||
|
if (!mRequestToFrameMap.Get(aRequest, &frameSet)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(frameSet, "This should never be null!");
|
||||||
|
|
||||||
|
DoRedraw(frameSet);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ImageLoader::FrameChanged(imgIRequest *aRequest,
|
||||||
|
imgIContainer *aContainer,
|
||||||
|
const nsIntRect *aDirtyRect)
|
||||||
|
{
|
||||||
|
if (!mDocument || !mHavePainted || mInClone) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameSet* frameSet = nsnull;
|
||||||
|
if (!mRequestToFrameMap.Get(aRequest, &frameSet)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(frameSet, "This should never be null!");
|
||||||
|
|
||||||
|
DoRedraw(frameSet);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace css
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,124 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// A class that handles style system image loads (other image loads are handled
|
||||||
|
// by the nodes in the content tree).
|
||||||
|
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
#include "nsClassHashtable.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
|
#include "nsInterfaceHashtable.h"
|
||||||
|
#include "nsCSSValue.h"
|
||||||
|
#include "imgIRequest.h"
|
||||||
|
#include "nsStubImageDecoderObserver.h"
|
||||||
|
|
||||||
|
class nsIFrame;
|
||||||
|
class nsIDocument;
|
||||||
|
class nsPresContext;
|
||||||
|
class nsIURI;
|
||||||
|
class nsIPrincipal;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace css {
|
||||||
|
|
||||||
|
class ImageLoader : public nsStubImageDecoderObserver {
|
||||||
|
public:
|
||||||
|
ImageLoader(nsIDocument* aDocument)
|
||||||
|
: mDocument(aDocument),
|
||||||
|
mHavePainted(false),
|
||||||
|
mInClone(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
||||||
|
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
|
||||||
|
NS_IMETHOD OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame);
|
||||||
|
NS_IMETHOD OnImageIsAnimated(imgIRequest *aRequest);
|
||||||
|
// Do not override OnDataAvailable since background images are not
|
||||||
|
// displayed incrementally; they are displayed after the entire image
|
||||||
|
// has been loaded.
|
||||||
|
|
||||||
|
// imgIContainerObserver (override nsStubImageDecoderObserver)
|
||||||
|
NS_IMETHOD FrameChanged(imgIRequest* aRequest,
|
||||||
|
imgIContainer *aContainer,
|
||||||
|
const nsIntRect *aDirtyRect);
|
||||||
|
|
||||||
|
nsresult Init();
|
||||||
|
|
||||||
|
inline void NotifyPaint()
|
||||||
|
{
|
||||||
|
mHavePainted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DropDocumentReference();
|
||||||
|
|
||||||
|
void MaybeRegisterCSSImage(nsCSSValue::Image* aImage);
|
||||||
|
void DeregisterCSSImage(nsCSSValue::Image* aImage);
|
||||||
|
|
||||||
|
void AssociateRequestToFrame(imgIRequest* aRequest,
|
||||||
|
nsIFrame* aFrame);
|
||||||
|
|
||||||
|
void DisassociateRequestFromFrame(imgIRequest* aRequest,
|
||||||
|
nsIFrame* aFrame);
|
||||||
|
|
||||||
|
void DropRequestsForFrame(nsIFrame* aFrame);
|
||||||
|
|
||||||
|
void SetAnimationMode(PRUint16 aMode);
|
||||||
|
|
||||||
|
void ClearAll();
|
||||||
|
|
||||||
|
void LoadImage(nsIURI* aURI, nsIPrincipal* aPrincipal, nsIURI* aReferrer,
|
||||||
|
nsCSSValue::Image* aCSSValue);
|
||||||
|
|
||||||
|
void DestroyRequest(imgIRequest* aRequest);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// We need to be able to look up the frames associated with a request (for
|
||||||
|
// delivering notifications) and the requests associated with a frame (when
|
||||||
|
// the frame goes away). Thus we maintain hashtables going both ways. These
|
||||||
|
// should always be in sync.
|
||||||
|
|
||||||
|
typedef nsTArray<nsIFrame*> FrameSet;
|
||||||
|
typedef nsTArray<nsCOMPtr<imgIRequest> > RequestSet;
|
||||||
|
typedef nsTHashtable<nsPtrHashKey<nsCSSValue::Image> > ImageHashSet;
|
||||||
|
typedef nsClassHashtable<nsISupportsHashKey,
|
||||||
|
FrameSet> RequestToFrameMap;
|
||||||
|
typedef nsClassHashtable<nsPtrHashKey<nsIFrame>,
|
||||||
|
RequestSet> FrameToRequestMap;
|
||||||
|
|
||||||
|
void AddImage(nsCSSValue::Image* aCSSImage);
|
||||||
|
void RemoveImage(nsCSSValue::Image* aCSSImage);
|
||||||
|
|
||||||
|
nsPresContext* GetPresContext();
|
||||||
|
|
||||||
|
void DoRedraw(FrameSet* aFrameSet);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
SetAnimationModeEnumerator(nsISupports* aKey, FrameSet* aValue,
|
||||||
|
void* aClosure);
|
||||||
|
|
||||||
|
// A map of imgIRequests to the nsIFrames that are using them.
|
||||||
|
RequestToFrameMap mRequestToFrameMap;
|
||||||
|
|
||||||
|
// A map of nsIFrames to the imgIRequests they use.
|
||||||
|
FrameToRequestMap mFrameToRequestMap;
|
||||||
|
|
||||||
|
// A weak pointer to our document. Nulled out by DropDocumentReference.
|
||||||
|
nsIDocument* mDocument;
|
||||||
|
|
||||||
|
// The set of all nsCSSValue::Images (whether they're associated a frame or
|
||||||
|
// not). We'll need this when we go away to remove any requests associated
|
||||||
|
// with our document from those Images.
|
||||||
|
ImageHashSet mImages;
|
||||||
|
|
||||||
|
// Have we painted yet? If not, no need to deliver notifications.
|
||||||
|
bool mHavePainted;
|
||||||
|
|
||||||
|
// Are we cloning? If so, ignore any notifications we get.
|
||||||
|
bool mInClone;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace css
|
||||||
|
} // namespace mozilla
|
|
@ -101,6 +101,7 @@ EXPORTS = \
|
||||||
EXPORTS_mozilla/css = \
|
EXPORTS_mozilla/css = \
|
||||||
Declaration.h \
|
Declaration.h \
|
||||||
GroupRule.h \
|
GroupRule.h \
|
||||||
|
ImageLoader.h \
|
||||||
ImportRule.h \
|
ImportRule.h \
|
||||||
Loader.h \
|
Loader.h \
|
||||||
NameSpaceRule.h \
|
NameSpaceRule.h \
|
||||||
|
@ -114,6 +115,7 @@ CPPSRCS = \
|
||||||
nsCSSDataBlock.cpp \
|
nsCSSDataBlock.cpp \
|
||||||
Declaration.cpp \
|
Declaration.cpp \
|
||||||
nsCSSKeywords.cpp \
|
nsCSSKeywords.cpp \
|
||||||
|
ImageLoader.cpp \
|
||||||
Loader.cpp \
|
Loader.cpp \
|
||||||
nsAnimationManager.cpp \
|
nsAnimationManager.cpp \
|
||||||
nsCSSParser.cpp \
|
nsCSSParser.cpp \
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#include "nsCSSDataBlock.h"
|
#include "nsCSSDataBlock.h"
|
||||||
#include "mozilla/css/Declaration.h"
|
#include "mozilla/css/Declaration.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
#include "nsRuleData.h"
|
#include "nsRuleData.h"
|
||||||
#include "nsStyleSet.h"
|
#include "nsStyleSet.h"
|
||||||
#include "nsStyleContext.h"
|
#include "nsStyleContext.h"
|
||||||
|
@ -79,16 +80,25 @@ ShouldIgnoreColors(nsRuleData *aRuleData)
|
||||||
static void
|
static void
|
||||||
TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument)
|
TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aDocument);
|
||||||
|
|
||||||
if (aValue.GetUnit() == eCSSUnit_URL) {
|
if (aValue.GetUnit() == eCSSUnit_URL) {
|
||||||
aValue.StartImageLoad(aDocument);
|
aValue.StartImageLoad(aDocument);
|
||||||
}
|
}
|
||||||
|
else if (aValue.GetUnit() == eCSSUnit_Image) {
|
||||||
|
// If we already have a request, see if this document needs to clone it.
|
||||||
|
imgIRequest* request = aValue.GetImageValue(nsnull);
|
||||||
|
|
||||||
|
if (request) {
|
||||||
|
aDocument->StyleImageLoader()->MaybeRegisterCSSImage(aValue.GetImageStructValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
|
else if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
|
||||||
nsCSSValue::Array* arguments = aValue.GetArrayValue();
|
nsCSSValue::Array* arguments = aValue.GetArrayValue();
|
||||||
NS_ABORT_IF_FALSE(arguments->Count() == 6, "unexpected num of arguments");
|
NS_ABORT_IF_FALSE(arguments->Count() == 6, "unexpected num of arguments");
|
||||||
|
|
||||||
const nsCSSValue& image = arguments->Item(1);
|
const nsCSSValue& image = arguments->Item(1);
|
||||||
if (image.GetUnit() == eCSSUnit_URL)
|
TryToStartImageLoadOnValue(image, aDocument);
|
||||||
image.StartImageLoad(aDocument);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "nsStyleUtil.h"
|
#include "nsStyleUtil.h"
|
||||||
#include "CSSCalc.h"
|
#include "CSSCalc.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
|
|
||||||
namespace css = mozilla::css;
|
namespace css = mozilla::css;
|
||||||
|
|
||||||
|
@ -272,10 +273,10 @@ double nsCSSValue::GetAngleValueInRadians() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imgIRequest* nsCSSValue::GetImageValue() const
|
imgIRequest* nsCSSValue::GetImageValue(nsIDocument* aDocument) const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Image, "not an Image value");
|
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Image, "not an Image value");
|
||||||
return mValue.mImage->mRequest;
|
return mValue.mImage->mRequests.GetWeak(aDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord nsCSSValue::GetFixedLength(nsPresContext* aPresContext) const
|
nscoord nsCSSValue::GetFixedLength(nsPresContext* aPresContext) const
|
||||||
|
@ -1679,17 +1680,43 @@ nsCSSValue::Image::Image(nsIURI* aURI, nsStringBuffer* aString,
|
||||||
if (aDocument->GetOriginalDocument()) {
|
if (aDocument->GetOriginalDocument()) {
|
||||||
aDocument = aDocument->GetOriginalDocument();
|
aDocument = aDocument->GetOriginalDocument();
|
||||||
}
|
}
|
||||||
if (aURI &&
|
|
||||||
nsContentUtils::CanLoadImage(aURI, aDocument, aDocument,
|
if (!mRequests.Init()) {
|
||||||
aOriginPrincipal)) {
|
NS_RUNTIMEABORT("out of memory");
|
||||||
nsContentUtils::LoadImage(aURI, aDocument, aOriginPrincipal, aReferrer,
|
|
||||||
nsnull, nsIRequest::LOAD_NORMAL,
|
|
||||||
getter_AddRefs(mRequest));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aDocument->StyleImageLoader()->LoadImage(aURI, aOriginPrincipal, aReferrer,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
ClearRequestHashtable(nsISupports* aKey, nsCOMPtr<imgIRequest>& aValue,
|
||||||
|
void* aClosure)
|
||||||
|
{
|
||||||
|
nsCSSValue::Image* image = static_cast<nsCSSValue::Image*>(aClosure);
|
||||||
|
nsIDocument* doc = static_cast<nsIDocument*>(aKey);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDocument> slowDoc = do_QueryInterface(aKey);
|
||||||
|
MOZ_ASSERT(slowDoc == doc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (doc) {
|
||||||
|
doc->StyleImageLoader()->DeregisterCSSImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aValue) {
|
||||||
|
aValue->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PL_DHASH_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSValue::Image::~Image()
|
nsCSSValue::Image::~Image()
|
||||||
{
|
{
|
||||||
|
mRequests.Enumerate(&ClearRequestHashtable, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSValueGradientStop::nsCSSValueGradientStop()
|
nsCSSValueGradientStop::nsCSSValueGradientStop()
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "nsCSSProperty.h"
|
#include "nsCSSProperty.h"
|
||||||
#include "nsColor.h"
|
#include "nsColor.h"
|
||||||
#include "nsCoord.h"
|
#include "nsCoord.h"
|
||||||
|
#include "nsInterfaceHashtable.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsStringBuffer.h"
|
#include "nsStringBuffer.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
@ -58,6 +59,8 @@ class nsIDocument;
|
||||||
class nsIPrincipal;
|
class nsIPrincipal;
|
||||||
class nsPresContext;
|
class nsPresContext;
|
||||||
class nsIURI;
|
class nsIURI;
|
||||||
|
template <class T>
|
||||||
|
class nsPtrHashKey;
|
||||||
|
|
||||||
// Deletes a linked list iteratively to avoid blowing up the stack (bug 456196).
|
// Deletes a linked list iteratively to avoid blowing up the stack (bug 456196).
|
||||||
#define NS_CSS_DELETE_LIST_MEMBER(type_, ptr_, member_) \
|
#define NS_CSS_DELETE_LIST_MEMBER(type_, ptr_, member_) \
|
||||||
|
@ -386,6 +389,12 @@ public:
|
||||||
return mValue.mURL;
|
return mValue.mURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image* GetImageStructValue() const
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Image, "not an Image value");
|
||||||
|
return mValue.mImage;
|
||||||
|
}
|
||||||
|
|
||||||
const PRUnichar* GetOriginalURLValue() const
|
const PRUnichar* GetOriginalURLValue() const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
||||||
|
@ -398,7 +407,7 @@ public:
|
||||||
// Not making this inline because that would force us to include
|
// Not making this inline because that would force us to include
|
||||||
// imgIRequest.h, which leads to REQUIRES hell, since this header is included
|
// imgIRequest.h, which leads to REQUIRES hell, since this header is included
|
||||||
// all over.
|
// all over.
|
||||||
imgIRequest* GetImageValue() const;
|
imgIRequest* GetImageValue(nsIDocument* aDocument) const;
|
||||||
|
|
||||||
nscoord GetFixedLength(nsPresContext* aPresContext) const;
|
nscoord GetFixedLength(nsPresContext* aPresContext) const;
|
||||||
nscoord GetPixelLength() const;
|
nscoord GetPixelLength() const;
|
||||||
|
@ -517,7 +526,7 @@ public:
|
||||||
|
|
||||||
// Inherit operator== from nsCSSValue::URL
|
// Inherit operator== from nsCSSValue::URL
|
||||||
|
|
||||||
nsCOMPtr<imgIRequest> mRequest; // null == image load blocked or somehow failed
|
nsInterfaceHashtable<nsISupportsHashKey, imgIRequest> mRequests;
|
||||||
|
|
||||||
// Override AddRef and Release to not only log ourselves correctly, but
|
// Override AddRef and Release to not only log ourselves correctly, but
|
||||||
// also so that we delete correctly without a virtual destructor
|
// also so that we delete correctly without a virtual destructor
|
||||||
|
|
|
@ -103,6 +103,12 @@ using namespace mozilla::dom;
|
||||||
method_(req); \
|
method_(req); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NS_SET_IMAGE_REQUEST_WITH_DOC(method_, context_, requestgetter_) \
|
||||||
|
{ \
|
||||||
|
nsIDocument* doc = (context_)->PresContext()->Document(); \
|
||||||
|
NS_SET_IMAGE_REQUEST(method_, context_, requestgetter_(doc)) \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For storage of an |nsRuleNode|'s children in a PLDHashTable.
|
* For storage of an |nsRuleNode|'s children in a PLDHashTable.
|
||||||
*/
|
*/
|
||||||
|
@ -933,9 +939,9 @@ static void SetStyleImageToImageRect(nsStyleContext* aStyleContext,
|
||||||
|
|
||||||
// <uri>
|
// <uri>
|
||||||
if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
|
if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
|
||||||
NS_SET_IMAGE_REQUEST(aResult.SetImageData,
|
NS_SET_IMAGE_REQUEST_WITH_DOC(aResult.SetImageData,
|
||||||
aStyleContext,
|
aStyleContext,
|
||||||
arr->Item(1).GetImageValue())
|
arr->Item(1).GetImageValue)
|
||||||
} else {
|
} else {
|
||||||
NS_WARNING("nsCSSValue::Image::Image() failed?");
|
NS_WARNING("nsCSSValue::Image::Image() failed?");
|
||||||
}
|
}
|
||||||
|
@ -965,9 +971,9 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
|
||||||
|
|
||||||
switch (aValue.GetUnit()) {
|
switch (aValue.GetUnit()) {
|
||||||
case eCSSUnit_Image:
|
case eCSSUnit_Image:
|
||||||
NS_SET_IMAGE_REQUEST(aResult.SetImageData,
|
NS_SET_IMAGE_REQUEST_WITH_DOC(aResult.SetImageData,
|
||||||
aStyleContext,
|
aStyleContext,
|
||||||
aValue.GetImageValue())
|
aValue.GetImageValue)
|
||||||
break;
|
break;
|
||||||
case eCSSUnit_Function:
|
case eCSSUnit_Function:
|
||||||
if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
|
if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
|
||||||
|
@ -3625,9 +3631,10 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
|
||||||
cursorUnit).get());
|
cursorUnit).get());
|
||||||
const nsCSSValueList* list = cursorValue->GetListValue();
|
const nsCSSValueList* list = cursorValue->GetListValue();
|
||||||
const nsCSSValueList* list2 = list;
|
const nsCSSValueList* list2 = list;
|
||||||
|
nsIDocument* doc = aContext->PresContext()->Document();
|
||||||
PRUint32 arrayLength = 0;
|
PRUint32 arrayLength = 0;
|
||||||
for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext)
|
for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext)
|
||||||
if (list->mValue.GetArrayValue()->Item(0).GetImageValue())
|
if (list->mValue.GetArrayValue()->Item(0).GetImageValue(doc))
|
||||||
++arrayLength;
|
++arrayLength;
|
||||||
|
|
||||||
if (arrayLength != 0) {
|
if (arrayLength != 0) {
|
||||||
|
@ -3639,7 +3646,7 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
|
||||||
list2->mValue.GetUnit() == eCSSUnit_Array;
|
list2->mValue.GetUnit() == eCSSUnit_Array;
|
||||||
list2 = list2->mNext) {
|
list2 = list2->mNext) {
|
||||||
nsCSSValue::Array *arr = list2->mValue.GetArrayValue();
|
nsCSSValue::Array *arr = list2->mValue.GetArrayValue();
|
||||||
imgIRequest *req = arr->Item(0).GetImageValue();
|
imgIRequest *req = arr->Item(0).GetImageValue(doc);
|
||||||
if (req) {
|
if (req) {
|
||||||
item->SetImage(req);
|
item->SetImage(req);
|
||||||
if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
|
if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
|
||||||
|
@ -5727,11 +5734,13 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
|
||||||
// border-image-source
|
// border-image-source
|
||||||
const nsCSSValue* borderImageSource = aRuleData->ValueForBorderImageSource();
|
const nsCSSValue* borderImageSource = aRuleData->ValueForBorderImageSource();
|
||||||
if (borderImageSource->GetUnit() == eCSSUnit_Image) {
|
if (borderImageSource->GetUnit() == eCSSUnit_Image) {
|
||||||
NS_SET_IMAGE_REQUEST(border->SetBorderImage, aContext,
|
NS_SET_IMAGE_REQUEST_WITH_DOC(border->SetBorderImage,
|
||||||
borderImageSource->GetImageValue());
|
aContext,
|
||||||
|
borderImageSource->GetImageValue);
|
||||||
} else if (borderImageSource->GetUnit() == eCSSUnit_Inherit) {
|
} else if (borderImageSource->GetUnit() == eCSSUnit_Inherit) {
|
||||||
canStoreInRuleTree = false;
|
canStoreInRuleTree = false;
|
||||||
NS_SET_IMAGE_REQUEST(border->SetBorderImage, aContext,
|
NS_SET_IMAGE_REQUEST(border->SetBorderImage,
|
||||||
|
aContext,
|
||||||
parentBorder->GetBorderImage());
|
parentBorder->GetBorderImage());
|
||||||
} else if (borderImageSource->GetUnit() == eCSSUnit_Initial ||
|
} else if (borderImageSource->GetUnit() == eCSSUnit_Initial ||
|
||||||
borderImageSource->GetUnit() == eCSSUnit_None) {
|
borderImageSource->GetUnit() == eCSSUnit_None) {
|
||||||
|
@ -5982,9 +5991,9 @@ nsRuleNode::ComputeListData(void* aStartStruct,
|
||||||
// list-style-image: url, none, inherit
|
// list-style-image: url, none, inherit
|
||||||
const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
|
const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
|
||||||
if (eCSSUnit_Image == imageValue->GetUnit()) {
|
if (eCSSUnit_Image == imageValue->GetUnit()) {
|
||||||
NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
|
NS_SET_IMAGE_REQUEST_WITH_DOC(list->SetListStyleImage,
|
||||||
aContext,
|
aContext,
|
||||||
imageValue->GetImageValue())
|
imageValue->GetImageValue)
|
||||||
}
|
}
|
||||||
else if (eCSSUnit_None == imageValue->GetUnit() ||
|
else if (eCSSUnit_None == imageValue->GetUnit() ||
|
||||||
eCSSUnit_Initial == imageValue->GetUnit()) {
|
eCSSUnit_Initial == imageValue->GetUnit()) {
|
||||||
|
@ -6303,7 +6312,9 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
|
||||||
}
|
}
|
||||||
data.mType = type;
|
data.mType = type;
|
||||||
if (type == eStyleContentType_Image) {
|
if (type == eStyleContentType_Image) {
|
||||||
NS_SET_IMAGE_REQUEST(data.SetImage, aContext, value.GetImageValue());
|
NS_SET_IMAGE_REQUEST_WITH_DOC(data.SetImage,
|
||||||
|
aContext,
|
||||||
|
value.GetImageValue);
|
||||||
}
|
}
|
||||||
else if (type <= eStyleContentType_Attr) {
|
else if (type <= eStyleContentType_Attr) {
|
||||||
value.GetStringValue(buffer);
|
value.GetStringValue(buffer);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче