687 lines
20 KiB
C++
687 lines
20 KiB
C++
/* -*- 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 Communicator client code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* 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 ***** */
|
|
#include "nsIDOMHTMLImageElement.h"
|
|
#include "nsIDOMNSHTMLImageElement.h"
|
|
#include "nsIDOMEventReceiver.h"
|
|
#include "nsGenericHTMLElement.h"
|
|
#include "nsImageLoadingContent.h"
|
|
#include "nsHTMLAtoms.h"
|
|
#include "nsStyleConsts.h"
|
|
#include "nsPresContext.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsMappedAttributes.h"
|
|
#include "nsIJSNativeInitializer.h"
|
|
#include "nsSize.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIDOMWindowInternal.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIScriptContext.h"
|
|
#include "nsIURL.h"
|
|
#include "nsIIOService.h"
|
|
#include "nsIURL.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsIFrame.h"
|
|
#include "nsIImageFrame.h"
|
|
#include "nsLayoutAtoms.h"
|
|
#include "nsNodeInfoManager.h"
|
|
#include "nsGUIEvent.h"
|
|
#include "nsContentPolicyUtils.h"
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "imgIContainer.h"
|
|
#include "imgILoader.h"
|
|
#include "imgIRequest.h"
|
|
#include "imgIDecoderObserver.h"
|
|
|
|
#include "nsILoadGroup.h"
|
|
|
|
#include "nsRuleData.h"
|
|
|
|
#include "nsIJSContextStack.h"
|
|
#include "nsIView.h"
|
|
#include "nsImageMapUtils.h"
|
|
#include "nsIDOMHTMLMapElement.h"
|
|
#include "nsEventDispatcher.h"
|
|
|
|
// XXX nav attrs: suppress
|
|
|
|
class nsHTMLImageElement : public nsGenericHTMLElement,
|
|
public nsImageLoadingContent,
|
|
public nsIDOMHTMLImageElement,
|
|
public nsIDOMNSHTMLImageElement,
|
|
public nsIJSNativeInitializer
|
|
{
|
|
public:
|
|
nsHTMLImageElement(nsINodeInfo *aNodeInfo);
|
|
virtual ~nsHTMLImageElement();
|
|
|
|
// nsISupports
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
// nsIDOMNode
|
|
NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
|
|
|
|
// nsIDOMElement
|
|
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
|
|
|
|
// nsIDOMHTMLElement
|
|
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
|
|
|
|
// nsIDOMHTMLImageElement
|
|
NS_DECL_NSIDOMHTMLIMAGEELEMENT
|
|
|
|
// nsIDOMNSHTMLImageElement
|
|
NS_DECL_NSIDOMNSHTMLIMAGEELEMENT
|
|
|
|
// nsIJSNativeInitializer
|
|
NS_IMETHOD Initialize(JSContext* aContext, JSObject *aObj,
|
|
PRUint32 argc, jsval *argv);
|
|
|
|
// nsIContent
|
|
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
|
nsIAtom* aAttribute,
|
|
const nsAString& aValue,
|
|
nsAttrValue& aResult);
|
|
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|
PRInt32 aModType) const;
|
|
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
|
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
|
|
|
|
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
|
|
|
PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
|
|
|
// SetAttr override. C++ is stupid, so have to override both
|
|
// overloaded methods.
|
|
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|
const nsAString& aValue, PRBool aNotify)
|
|
{
|
|
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
|
|
}
|
|
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|
nsIAtom* aPrefix, const nsAString& aValue,
|
|
PRBool aNotify);
|
|
|
|
// XXXbz What about UnsetAttr? We don't seem to unload images when
|
|
// that happens...
|
|
|
|
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|
nsIContent* aBindingParent,
|
|
PRBool aCompileEventHandlers);
|
|
|
|
virtual PRInt32 IntrinsicState() const;
|
|
|
|
protected:
|
|
void GetImageFrame(nsIImageFrame** aImageFrame);
|
|
nsPoint GetXY();
|
|
nsSize GetWidthHeight();
|
|
};
|
|
|
|
nsGenericHTMLElement*
|
|
NS_NewHTMLImageElement(nsINodeInfo *aNodeInfo, PRBool aFromParser)
|
|
{
|
|
/*
|
|
* nsHTMLImageElement's will be created without a nsINodeInfo passed in
|
|
* if someone says "var img = new Image();" in JavaScript, in a case like
|
|
* that we request the nsINodeInfo from the document's nodeinfo list.
|
|
*/
|
|
nsresult rv;
|
|
nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
|
|
if (!nodeInfo) {
|
|
nsCOMPtr<nsIDocument> doc =
|
|
do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
|
|
NS_ENSURE_TRUE(doc, nsnull);
|
|
|
|
rv = doc->NodeInfoManager()->GetNodeInfo(nsHTMLAtoms::img, nsnull,
|
|
kNameSpaceID_None,
|
|
getter_AddRefs(nodeInfo));
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
}
|
|
|
|
return new nsHTMLImageElement(nodeInfo);
|
|
}
|
|
|
|
nsHTMLImageElement::nsHTMLImageElement(nsINodeInfo *aNodeInfo)
|
|
: nsGenericHTMLElement(aNodeInfo)
|
|
{
|
|
}
|
|
|
|
nsHTMLImageElement::~nsHTMLImageElement()
|
|
{
|
|
}
|
|
|
|
|
|
NS_IMPL_ADDREF_INHERITED(nsHTMLImageElement, nsGenericElement)
|
|
NS_IMPL_RELEASE_INHERITED(nsHTMLImageElement, nsGenericElement)
|
|
|
|
|
|
// QueryInterface implementation for nsHTMLImageElement
|
|
NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLImageElement, nsGenericHTMLElement)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLImageElement)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLImageElement)
|
|
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
|
|
NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver)
|
|
NS_INTERFACE_MAP_ENTRY(nsIImageLoadingContent)
|
|
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLImageElement)
|
|
NS_HTML_CONTENT_INTERFACE_MAP_END
|
|
|
|
|
|
NS_IMPL_DOM_CLONENODE(nsHTMLImageElement)
|
|
|
|
|
|
NS_IMPL_STRING_ATTR(nsHTMLImageElement, Name, name)
|
|
NS_IMPL_STRING_ATTR(nsHTMLImageElement, Align, align)
|
|
NS_IMPL_STRING_ATTR(nsHTMLImageElement, Alt, alt)
|
|
NS_IMPL_STRING_ATTR(nsHTMLImageElement, Border, border)
|
|
NS_IMPL_INT_ATTR(nsHTMLImageElement, Hspace, hspace)
|
|
NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap)
|
|
NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc)
|
|
NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc)
|
|
NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src)
|
|
NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap)
|
|
NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace)
|
|
|
|
void
|
|
nsHTMLImageElement::GetImageFrame(nsIImageFrame** aImageFrame)
|
|
{
|
|
*aImageFrame = nsnull;
|
|
// If we have no parent, then we won't have a frame yet
|
|
if (!GetParent())
|
|
return;
|
|
|
|
nsIFrame* frame = GetPrimaryFrame(PR_TRUE);
|
|
|
|
if (frame) {
|
|
CallQueryInterface(frame, aImageFrame);
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetComplete(PRBool* aComplete)
|
|
{
|
|
NS_PRECONDITION(aComplete, "Null out param!");
|
|
*aComplete = PR_TRUE;
|
|
|
|
if (!mCurrentRequest) {
|
|
return NS_OK;
|
|
}
|
|
|
|
PRUint32 status;
|
|
mCurrentRequest->GetImageStatus(&status);
|
|
*aComplete =
|
|
(status &
|
|
(imgIRequest::STATUS_LOAD_COMPLETE | imgIRequest::STATUS_ERROR)) != 0;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsPoint
|
|
nsHTMLImageElement::GetXY()
|
|
{
|
|
nsPoint point(0, 0);
|
|
|
|
nsIDocument *document = GetCurrentDoc();
|
|
|
|
if (!document) {
|
|
return point;
|
|
}
|
|
|
|
// Get Presentation shell 0
|
|
nsIPresShell *presShell = document->GetShellAt(0);
|
|
if (!presShell) {
|
|
return point;
|
|
}
|
|
|
|
// Get the Presentation Context from the Shell
|
|
nsPresContext *context = presShell->GetPresContext();
|
|
if (!context) {
|
|
return point;
|
|
}
|
|
|
|
// Flush all pending notifications so that our frames are laid out correctly
|
|
document->FlushPendingNotifications(Flush_Layout);
|
|
|
|
// Get the Frame for this image
|
|
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
|
|
|
|
if (!frame) {
|
|
return point;
|
|
}
|
|
|
|
nsPoint origin(0, 0);
|
|
nsIView* parentView;
|
|
nsresult rv = frame->GetOffsetFromView(origin, &parentView);
|
|
if (NS_FAILED(rv)) {
|
|
return point;
|
|
}
|
|
|
|
// Get the scale from that Presentation Context
|
|
float scale;
|
|
scale = context->TwipsToPixels();
|
|
|
|
// Convert to pixels using that scale
|
|
point.x = NSTwipsToIntPixels(origin.x, scale);
|
|
point.y = NSTwipsToIntPixels(origin.y, scale);
|
|
|
|
return point;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetX(PRInt32* aX)
|
|
{
|
|
*aX = GetXY().x;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetY(PRInt32* aY)
|
|
{
|
|
*aY = GetXY().y;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsSize
|
|
nsHTMLImageElement::GetWidthHeight()
|
|
{
|
|
nsSize size(0,0);
|
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
|
if (doc) {
|
|
// Flush all pending notifications so that our frames are up to date.
|
|
// If we're not in a document, we don't have a frame anyway, so we
|
|
// don't care.
|
|
doc->FlushPendingNotifications(Flush_Layout);
|
|
}
|
|
|
|
nsIImageFrame* imageFrame;
|
|
GetImageFrame(&imageFrame);
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
if (imageFrame) {
|
|
CallQueryInterface(imageFrame, &frame);
|
|
NS_ASSERTION(frame,"Should not happen - image frame is not frame");
|
|
}
|
|
|
|
if (frame) {
|
|
// XXX we could put an accessor on nsIImageFrame to return its
|
|
// mComputedSize.....
|
|
size = frame->GetSize();
|
|
|
|
nsMargin margin;
|
|
frame->CalcBorderPadding(margin);
|
|
|
|
size.height -= margin.top + margin.bottom;
|
|
size.width -= margin.left + margin.right;
|
|
|
|
nsPresContext *context = GetPresContext();
|
|
if (context) {
|
|
float t2p;
|
|
t2p = context->TwipsToPixels();
|
|
|
|
size.width = NSTwipsToIntPixels(size.width, t2p);
|
|
size.height = NSTwipsToIntPixels(size.height, t2p);
|
|
}
|
|
} else {
|
|
const nsAttrValue* value;
|
|
nsCOMPtr<imgIContainer> image;
|
|
if (mCurrentRequest) {
|
|
mCurrentRequest->GetImage(getter_AddRefs(image));
|
|
}
|
|
|
|
if ((value = GetParsedAttr(nsHTMLAtoms::width)) &&
|
|
value->Type() == nsAttrValue::eInteger) {
|
|
size.width = value->GetIntegerValue();
|
|
} else if (image) {
|
|
image->GetWidth(&size.width);
|
|
}
|
|
|
|
if ((value = GetParsedAttr(nsHTMLAtoms::height)) &&
|
|
value->Type() == nsAttrValue::eInteger) {
|
|
size.height = value->GetIntegerValue();
|
|
} else if (image) {
|
|
image->GetHeight(&size.height);
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetHeight(PRInt32* aHeight)
|
|
{
|
|
*aHeight = GetWidthHeight().height;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::SetHeight(PRInt32 aHeight)
|
|
{
|
|
nsAutoString val;
|
|
val.AppendInt(aHeight);
|
|
|
|
return nsGenericHTMLElement::SetAttr(kNameSpaceID_None, nsHTMLAtoms::height,
|
|
val, PR_TRUE);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetWidth(PRInt32* aWidth)
|
|
{
|
|
*aWidth = GetWidthHeight().width;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::SetWidth(PRInt32 aWidth)
|
|
{
|
|
nsAutoString val;
|
|
val.AppendInt(aWidth);
|
|
|
|
return nsGenericHTMLElement::SetAttr(kNameSpaceID_None, nsHTMLAtoms::width,
|
|
val, PR_TRUE);
|
|
}
|
|
|
|
PRBool
|
|
nsHTMLImageElement::ParseAttribute(PRInt32 aNamespaceID,
|
|
nsIAtom* aAttribute,
|
|
const nsAString& aValue,
|
|
nsAttrValue& aResult)
|
|
{
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
if (aAttribute == nsHTMLAtoms::align) {
|
|
return ParseAlignValue(aValue, aResult);
|
|
}
|
|
if (aAttribute == nsHTMLAtoms::src) {
|
|
static const char* kWhitespace = " \n\r\t\b";
|
|
aResult.SetTo(nsContentUtils::TrimCharsInSet(kWhitespace, aValue));
|
|
return PR_TRUE;
|
|
}
|
|
if (ParseImageAttribute(aAttribute, aValue, aResult)) {
|
|
return PR_TRUE;
|
|
}
|
|
}
|
|
|
|
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
|
|
aResult);
|
|
}
|
|
|
|
static void
|
|
MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
|
nsRuleData* aData)
|
|
{
|
|
nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
|
|
nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
|
|
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
|
|
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
|
|
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
|
|
}
|
|
|
|
nsChangeHint
|
|
nsHTMLImageElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|
PRInt32 aModType) const
|
|
{
|
|
nsChangeHint retval =
|
|
nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
|
|
if (aAttribute == nsHTMLAtoms::usemap ||
|
|
aAttribute == nsHTMLAtoms::ismap) {
|
|
NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
NS_IMETHODIMP_(PRBool)
|
|
nsHTMLImageElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
|
{
|
|
static const MappedAttributeEntry* const map[] = {
|
|
sCommonAttributeMap,
|
|
sImageMarginSizeAttributeMap,
|
|
sImageBorderAttributeMap,
|
|
sImageAlignAttributeMap
|
|
};
|
|
|
|
return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
|
|
}
|
|
|
|
|
|
nsMapRuleToAttributesFunc
|
|
nsHTMLImageElement::GetAttributeMappingFunction() const
|
|
{
|
|
return &MapAttributesIntoRule;
|
|
}
|
|
|
|
|
|
nsresult
|
|
nsHTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|
{
|
|
// If we are a map and get a mouse click, don't let it be handled by
|
|
// the Generic Element as this could cause a click event to fire
|
|
// twice, once by the image frame for the map and once by the Anchor
|
|
// element. (bug 39723)
|
|
if (NS_MOUSE_LEFT_CLICK == aVisitor.mEvent->message) {
|
|
PRBool isMap = PR_FALSE;
|
|
GetIsMap(&isMap);
|
|
if (isMap) {
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
}
|
|
}
|
|
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
|
}
|
|
|
|
PRBool
|
|
nsHTMLImageElement::IsFocusable(PRInt32 *aTabIndex)
|
|
{
|
|
PRInt32 tabIndex;
|
|
GetTabIndex(&tabIndex);
|
|
|
|
if (IsInDoc()) {
|
|
nsAutoString usemap;
|
|
GetUseMap(usemap);
|
|
// XXXbz which document should this be using? sXBL/XBL2 issue! I
|
|
// think that GetOwnerDoc() is right, since we don't want to
|
|
// assume stuff about the document we're bound to.
|
|
nsCOMPtr<nsIDOMHTMLMapElement> imageMap =
|
|
nsImageMapUtils::FindImageMap(GetOwnerDoc(), usemap);
|
|
if (imageMap) {
|
|
if (aTabIndex) {
|
|
// Use tab index on individual map areas
|
|
*aTabIndex = (sTabFocusModel & eTabFocus_linksMask)? 0 : -1;
|
|
}
|
|
// Image map is not focusable itself, but flag as tabbable
|
|
// so that image map areas get walked into.
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
|
|
if (aTabIndex) {
|
|
// Can be in tab order if tabindex >=0 and form controls are tabbable.
|
|
*aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask)? tabIndex : -1;
|
|
}
|
|
|
|
return tabIndex >= 0;
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLImageElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|
nsIAtom* aPrefix, const nsAString& aValue,
|
|
PRBool aNotify)
|
|
{
|
|
// If we plan to call LoadImage, we want to do it first so that the
|
|
// image load kicks off _before_ the reflow triggered by the SetAttr. But if
|
|
// aNotify is false, we are coming from the parser or some such place; we'll
|
|
// get bound after all the attributes have been set, so we'll do the
|
|
// image load from BindToTree. Skip the LoadImage call in that case.
|
|
if (aNotify &&
|
|
aNameSpaceID == kNameSpaceID_None && aName == nsHTMLAtoms::src) {
|
|
|
|
// If caller is not chrome and dom.disable_image_src_set is true,
|
|
// prevent setting image.src by exiting early
|
|
if (nsContentUtils::GetBoolPref("dom.disable_image_src_set") &&
|
|
!nsContentUtils::IsCallerChrome()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<imgIRequest> oldCurrentRequest = mCurrentRequest;
|
|
|
|
// Force image loading here, so that we'll try to load the image from
|
|
// network if it's set to be not cacheable...
|
|
LoadImage(aValue, PR_TRUE, aNotify);
|
|
|
|
if (mCurrentRequest && !mPendingRequest &&
|
|
oldCurrentRequest != mCurrentRequest) {
|
|
// We have a current request, and it's not the same one as we used
|
|
// to have, and we have no pending request. So imglib already had
|
|
// that image. Reset the animation on it -- see bug 210001
|
|
nsCOMPtr<imgIContainer> container;
|
|
mCurrentRequest->GetImage(getter_AddRefs(container));
|
|
if (container) {
|
|
container->ResetAnimation();
|
|
}
|
|
}
|
|
}
|
|
|
|
return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
|
|
aNotify);
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|
nsIContent* aBindingParent,
|
|
PRBool aCompileEventHandlers)
|
|
{
|
|
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
|
|
aBindingParent,
|
|
aCompileEventHandlers);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Our base URI may have changed; claim that our URI changed, and the
|
|
// nsImageLoadingContent will decide whether a new image load is warranted.
|
|
nsAutoString uri;
|
|
if (GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, uri)) {
|
|
// Note: no need to notify here; since we're just now being bound
|
|
// we don't have any frames or anything yet.
|
|
LoadImage(uri, PR_FALSE, PR_FALSE);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
PRInt32
|
|
nsHTMLImageElement::IntrinsicState() const
|
|
{
|
|
return nsGenericHTMLElement::IntrinsicState() |
|
|
nsImageLoadingContent::ImageState();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::Initialize(JSContext* aContext, JSObject *aObj,
|
|
PRUint32 argc, jsval *argv)
|
|
{
|
|
if (argc <= 0) {
|
|
// Nothing to do here if we don't get any arguments.
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// The first (optional) argument is the width of the image
|
|
int32 width;
|
|
JSBool ret = JS_ValueToInt32(aContext, argv[0], &width);
|
|
NS_ENSURE_TRUE(ret, NS_ERROR_INVALID_ARG);
|
|
|
|
nsresult rv = SetIntAttr(nsHTMLAtoms::width, NS_STATIC_CAST(PRInt32, width));
|
|
|
|
if (NS_SUCCEEDED(rv) && (argc > 1)) {
|
|
// The second (optional) argument is the height of the image
|
|
int32 height;
|
|
ret = JS_ValueToInt32(aContext, argv[1], &height);
|
|
NS_ENSURE_TRUE(ret, NS_ERROR_INVALID_ARG);
|
|
|
|
rv = SetIntAttr(nsHTMLAtoms::height, NS_STATIC_CAST(PRInt32, height));
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetNaturalHeight(PRInt32* aNaturalHeight)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aNaturalHeight);
|
|
|
|
*aNaturalHeight = 0;
|
|
|
|
if (!mCurrentRequest) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<imgIContainer> image;
|
|
mCurrentRequest->GetImage(getter_AddRefs(image));
|
|
if (!image) {
|
|
return NS_OK;
|
|
}
|
|
|
|
image->GetHeight(aNaturalHeight);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLImageElement::GetNaturalWidth(PRInt32* aNaturalWidth)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aNaturalWidth);
|
|
|
|
*aNaturalWidth = 0;
|
|
|
|
if (!mCurrentRequest) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<imgIContainer> image;
|
|
mCurrentRequest->GetImage(getter_AddRefs(image));
|
|
if (!image) {
|
|
return NS_OK;
|
|
}
|
|
|
|
image->GetWidth(aNaturalWidth);
|
|
return NS_OK;
|
|
}
|
|
|
|
|