Mozilla/mozilla/layout/html/base/src/nsHTMLImage.cpp
kipp 957f7882a1 Avoid scaling image when rendering the broken-image image
git-svn-id: svn://10.0.0.236/trunk@3089 18797224-902f-48f8-a5cc-f745e15eee43
1998-06-03 18:56:11 +00:00

792 lines
22 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsHTMLParts.h"
#include "nsHTMLImage.h"
#include "nsHTMLTagContent.h"
#include "nsString.h"
#include "nsLeafFrame.h"
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIFrameImageLoader.h"
#include "nsIPresShell.h"
#include "nsHTMLIIDs.h"
#include "nsIImage.h"
#include "nsIWidget.h"
#include "nsHTMLAtoms.h"
#include "nsIHTMLAttributes.h"
#include "nsIDocument.h"
#include "nsIHTMLDocument.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
#include "nsIImageMap.h"
#include "nsILinkHandler.h"
#include "nsIURL.h"
#include "nsCSSLayout.h"
#include "nsHTMLFrame.h"
#define BROKEN_IMAGE_URL "resource:/res/html/broken-image.gif"
static NS_DEFINE_IID(kIHTMLDocumentIID, NS_IHTMLDOCUMENT_IID);
class ImageFrame : public nsLeafFrame {
public:
ImageFrame(nsIContent* aContent, nsIFrame* aParentFrame);
NS_IMETHOD DeleteFrame();
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_METHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD GetCursorAt(nsIPresContext& aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame,
PRInt32& aCursor);
protected:
virtual ~ImageFrame();
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsReflowMetrics& aDesiredSize);
nsIImageMap* GetImageMap();
nsHTMLImageLoader mImageLoader;
nsIImageMap* mImageMap;
void TriggerLink(nsIPresContext& aPresContext,
const nsString& aURLSpec,
const nsString& aTargetSpec,
PRBool aClick);
};
class ImagePart : public nsHTMLTagContent {
public:
ImagePart(nsIAtom* aTag);
virtual nsresult CreateFrame(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsIFrame*& aResult);
virtual void SetAttribute(nsIAtom* aAttribute, const nsString& aValue);
virtual nsContentAttr GetAttribute(nsIAtom* aAttribute,
nsHTMLValue& aResult) const;
virtual void UnsetAttribute(nsIAtom* aAttribute);
virtual void MapAttributesInto(nsIStyleContext* aContext,
nsIPresContext* aPresContext);
PRPackedBool mIsMap;
PRUint8 mSuppress;
PRUint8 mAlign;
nsString* mAltText;
nsString* mSrc;
nsString* mLowSrc;
nsString* mUseMap;
protected:
virtual ~ImagePart();
virtual nsContentAttr AttributeToString(nsIAtom* aAttribute,
nsHTMLValue& aValue,
nsString& aResult) const;
};
// Value's for mSuppress
#define SUPPRESS_UNSET 0
#define DONT_SUPPRESS 1
#define SUPPRESS 2
#define DEFAULT_SUPPRESS 3
// Default alignment value (so we can tell an unset value from a set value)
#define ALIGN_UNSET PRUint8(-1)
//----------------------------------------------------------------------
nsHTMLImageLoader::nsHTMLImageLoader()
{
mImageLoader = nsnull;
mLoadImageFailed = PR_FALSE;
mLoadBrokenImageFailed = PR_FALSE;
mURLSpec = nsnull;
}
nsHTMLImageLoader::~nsHTMLImageLoader()
{
NS_IF_RELEASE(mImageLoader);
if (nsnull != mURLSpec) {
delete mURLSpec;
}
}
nsIImage*
nsHTMLImageLoader::GetImage()
{
nsIImage* image = nsnull;
if (nsnull != mImageLoader) {
mImageLoader->GetImage(image);
}
return image;
}
nsresult
nsHTMLImageLoader::SetURL(const nsString& aURLSpec)
{
if (nsnull != mURLSpec) {
delete mURLSpec;
}
mURLSpec = new nsString(aURLSpec);
if (nsnull == mURLSpec) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
nsresult
nsHTMLImageLoader::LoadImage(nsIPresContext* aPresContext,
nsIFrame* aForFrame,
PRBool aNeedSizeUpdate,
PRIntn& aLoadStatus)
{
aLoadStatus = NS_IMAGE_LOAD_STATUS_NONE;
// Get absolute url the first time through
nsresult rv;
nsAutoString src;
if (mLoadImageFailed || (nsnull == mURLSpec)) {
src.Append(BROKEN_IMAGE_URL);
} else {
nsAutoString baseURL;
// Get documentURL
nsIPresShell* shell;
shell = aPresContext->GetShell();
nsIDocument* doc = shell->GetDocument();
nsIURL* docURL = doc->GetDocumentURL();
// Create an absolute URL
nsresult rv = NS_MakeAbsoluteURL(docURL, baseURL, *mURLSpec, src);
// Release references
NS_RELEASE(shell);
NS_RELEASE(docURL);
NS_RELEASE(doc);
if (NS_OK != rv) {
return rv;
}
}
if (nsnull == mImageLoader) {
// Start image loading
rv = aPresContext->LoadImage(src, aForFrame, aNeedSizeUpdate,
mImageLoader);
if (NS_OK != rv) {
return rv;
}
}
// Examine current image load status
mImageLoader->GetImageLoadStatus(aLoadStatus);
if (0 != (aLoadStatus & NS_IMAGE_LOAD_STATUS_ERROR)) {
NS_RELEASE(mImageLoader);
if (mLoadImageFailed) {
// We are doomed. Loading the broken image has just failed.
mLoadBrokenImageFailed = PR_TRUE;
}
else {
// Try again, this time using the broke-image url
mLoadImageFailed = PR_TRUE;
return LoadImage(aPresContext, aForFrame, aNeedSizeUpdate, aLoadStatus);
}
}
return NS_OK;
}
void
nsHTMLImageLoader::GetDesiredSize(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsReflowMetrics& aDesiredSize)
{
nsSize styleSize;
PRIntn ss = nsCSSLayout::GetStyleSize(aPresContext, aReflowState, styleSize);
PRIntn loadStatus;
if (0 != ss) {
if (NS_SIZE_HAS_BOTH == ss) {
LoadImage(aPresContext, aReflowState.frame, PR_FALSE, loadStatus);
aDesiredSize.width = styleSize.width;
aDesiredSize.height = styleSize.height;
}
else {
// Preserve aspect ratio of image with unbound dimension.
LoadImage(aPresContext, aReflowState.frame, PR_TRUE, loadStatus);
if ((0 == (loadStatus & NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE)) ||
(nsnull == mImageLoader)) {
// Provide a dummy size for now; later on when the image size
// shows up we will reflow to the new size.
aDesiredSize.width = 0;
aDesiredSize.height = 0;
}
else {
float p2t = aPresContext->GetPixelsToTwips();
nsSize imageSize;
mImageLoader->GetSize(imageSize);
float imageWidth = imageSize.width * p2t;
float imageHeight = imageSize.height * p2t;
if (0.0f != imageHeight) {
if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
// We have a width, and an auto height. Compute height
// from width.
aDesiredSize.width = styleSize.width;
aDesiredSize.height =
nscoord(styleSize.width * imageHeight / imageWidth);
}
else {
// We have a height and an auto width. Compute width from
// height.
aDesiredSize.height = styleSize.height;
aDesiredSize.width =
nscoord(styleSize.height * imageWidth / imageHeight);
}
}
else {
// Screwy image
aDesiredSize.width = 0;
aDesiredSize.height = 0;
}
}
}
}
else {
LoadImage(aPresContext, aReflowState.frame, PR_TRUE, loadStatus);
if ((0 == (loadStatus & NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE)) ||
(nsnull == mImageLoader)) {
// Provide a dummy size for now; later on when the image size
// shows up we will reflow to the new size.
aDesiredSize.width = 0;
aDesiredSize.height = 0;
} else {
float p2t = aPresContext->GetPixelsToTwips();
nsSize imageSize;
mImageLoader->GetSize(imageSize);
aDesiredSize.width = nscoord(imageSize.width * p2t);
aDesiredSize.height = nscoord(imageSize.height * p2t);
}
}
}
//----------------------------------------------------------------------
ImageFrame::ImageFrame(nsIContent* aContent, nsIFrame* aParentFrame)
: nsLeafFrame(aContent, aParentFrame)
{
}
ImageFrame::~ImageFrame()
{
}
NS_METHOD
ImageFrame::DeleteFrame()
{
NS_IF_RELEASE(mImageMap);
// Release image loader first so that it's refcnt can go to zero
mImageLoader.DestroyLoader();
return nsLeafFrame::DeleteFrame();
}
void
ImageFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsReflowMetrics& aDesiredSize)
{
nsHTMLFrame::CreateViewForFrame(aPresContext, this, mStyleContext, PR_TRUE);
// Setup url before starting the image load
nsAutoString src;
if (eContentAttr_HasValue == mContent->GetAttribute("SRC", src)) {
mImageLoader.SetURL(src);
}
mImageLoader.GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
}
NS_METHOD
ImageFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
if ((0 == mRect.width) || (0 == mRect.height)) {
// Do not render when given a zero area. This avoids some useless
// scaling work while we wait for our image dimensions to arrive
// asynchronously.
return NS_OK;
}
nsStyleDisplay* disp =
(nsStyleDisplay*)mStyleContext->GetData(eStyleStruct_Display);
if (disp->mVisible) {
// First paint background and borders
nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect);
// XXX when we don't have the image, draw the we-don't-have-an-image look
nsIImage* image = mImageLoader.GetImage();
if (nsnull == image) {
// No image yet
return NS_OK;
}
// Now render the image into our inner area (the area without the
// borders and padding)
nsRect inner;
GetInnerArea(&aPresContext, inner);
if (mImageLoader.GetLoadImageFailed()) {
float p2t = aPresContext.GetPixelsToTwips();
inner.width = nscoord(p2t * image->GetWidth());
inner.height = nscoord(p2t * image->GetHeight());
}
aRenderingContext.DrawImage(image, inner);
}
if (GetShowFrameBorders()) {
nsIImageMap* map = GetImageMap();
if (nsnull != map) {
aRenderingContext.SetColor(NS_RGB(0, 0, 0));
map->Draw(aPresContext, aRenderingContext);
}
}
return NS_OK;
}
nsIImageMap*
ImageFrame::GetImageMap()
{
if (nsnull == mImageMap) {
ImagePart* part = (ImagePart*)mContent;
if (nsnull == part->mUseMap) {
return nsnull;
}
nsIDocument* doc = nsnull;
mContent->GetDocument(doc);
if (nsnull == doc) {
return nsnull;
}
nsAutoString mapName(*part->mUseMap);
if (mapName.First() == '#') {
mapName.Cut(0, 1);
}
nsIHTMLDocument* hdoc;
nsresult rv = doc->QueryInterface(kIHTMLDocumentIID, (void**)&hdoc);
NS_RELEASE(doc);
if (NS_OK == rv) {
nsIImageMap* map;
rv = hdoc->GetImageMap(mapName, &map);
NS_RELEASE(hdoc);
if (NS_OK == rv) {
mImageMap = map;
}
}
}
NS_IF_ADDREF(mImageMap);
return mImageMap;
}
void
ImageFrame::TriggerLink(nsIPresContext& aPresContext,
const nsString& aURLSpec,
const nsString& aTargetSpec,
PRBool aClick)
{
nsILinkHandler* handler;
if (NS_OK == aPresContext.GetLinkHandler(&handler)) {
if (aClick) {
handler->OnLinkClick(this, aURLSpec, aTargetSpec);
}
else {
handler->OnOverLink(this, aURLSpec, aTargetSpec);
}
}
}
// XXX what should clicks on transparent pixels do?
NS_METHOD
ImageFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
nsIImageMap* map;
aEventStatus = nsEventStatus_eIgnore;
switch (aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_MOVE:
map = GetImageMap();
if (nsnull != map) {
nsIURL* docURL = nsnull;
nsIDocument* doc = nsnull;
mContent->GetDocument(doc);
if (nsnull != doc) {
docURL = doc->GetDocumentURL();
NS_RELEASE(doc);
}
// Translate coordinates to pixels
float t2p = aPresContext.GetTwipsToPixels();
nscoord x = nscoord(t2p * aEvent->point.x);
nscoord y = nscoord(t2p * aEvent->point.y);
// Ask map if the x,y coordinates are in a clickable area
PRBool suppress;
nsAutoString absURL, target, altText;
nsresult r = map->IsInside(x, y, docURL, absURL, target, altText,
&suppress);
NS_IF_RELEASE(docURL);
NS_RELEASE(map);
if (NS_OK == r) {
// We hit a clickable area. Time to go somewhere...
TriggerLink(aPresContext, absURL, target,
aEvent->message == NS_MOUSE_LEFT_BUTTON_UP);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;
}
// FALL THROUGH
default:
// Let default event handler deal with it
return nsLeafFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
return NS_OK;
}
NS_METHOD
ImageFrame::GetCursorAt(nsIPresContext& aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame,
PRInt32& aCursor)
{
// The default cursor is to have no cursor
aCursor = NS_STYLE_CURSOR_INHERIT;
nsStyleColor* styleColor = (nsStyleColor*)
mStyleContext->GetData(eStyleStruct_Color);
if (styleColor->mCursor != NS_STYLE_CURSOR_INHERIT) {
// If we have a particular cursor, use it
*aFrame = this;
aCursor = (PRInt32) styleColor->mCursor;
}
nsIImageMap* map = GetImageMap();
if (nsnull != map) {
aCursor = NS_STYLE_CURSOR_DEFAULT;
float t2p = aPresContext.GetTwipsToPixels();
nscoord x = nscoord(t2p * aPoint.x);
nscoord y = nscoord(t2p * aPoint.y);
if (NS_OK == map->IsInside(x, y)) {
aCursor = NS_STYLE_CURSOR_HAND;
}
NS_RELEASE(map);
}
return NS_OK;
}
//----------------------------------------------------------------------
ImagePart::ImagePart(nsIAtom* aTag)
: nsHTMLTagContent(aTag)
{
mAlign = ALIGN_UNSET;
mSuppress = SUPPRESS_UNSET;
}
ImagePart::~ImagePart()
{
if (nsnull != mAltText) delete mAltText;
if (nsnull != mSrc) delete mSrc;
if (nsnull != mLowSrc) delete mLowSrc;
if (nsnull != mUseMap) delete mUseMap;
}
void ImagePart::SetAttribute(nsIAtom* aAttribute, const nsString& aString)
{
if (aAttribute == nsHTMLAtoms::ismap) {
mIsMap = PR_TRUE;
return;
}
if (aAttribute == nsHTMLAtoms::usemap) {
nsAutoString src(aString);
src.StripWhitespace();
if (nsnull == mUseMap) {
mUseMap = new nsString(src);
} else {
*mUseMap = src;
}
return;
}
if (aAttribute == nsHTMLAtoms::align) {
nsHTMLValue val;
if (ParseAlignParam(aString, val)) {
mAlign = val.GetIntValue();
// Reflect the attribute into the syle system
nsHTMLTagContent::SetAttribute(aAttribute, val);
} else {
mAlign = ALIGN_UNSET;
}
return;
}
if (aAttribute == nsHTMLAtoms::src) {
nsAutoString src(aString);
src.StripWhitespace();
if (nsnull == mSrc) {
mSrc = new nsString(src);
} else {
*mSrc = src;
}
return;
}
if (aAttribute == nsHTMLAtoms::lowsrc) {
nsAutoString src(aString);
src.StripWhitespace();
if (nsnull == mLowSrc) {
mLowSrc = new nsString(src);
} else {
*mLowSrc = src;
}
return;
}
if (aAttribute == nsHTMLAtoms::alt) {
if (nsnull == mAltText) {
mAltText = new nsString(aString);
} else {
*mAltText = aString;
}
return;
}
if (aAttribute == nsHTMLAtoms::suppress) {
if (aString.EqualsIgnoreCase("true")) {
mSuppress = SUPPRESS;
} else if (aString.EqualsIgnoreCase("false")) {
mSuppress = DONT_SUPPRESS;
} else {
mSuppress = DEFAULT_SUPPRESS;
}
return;
}
// Try other attributes
nsHTMLValue val;
if (ParseImageProperty(aAttribute, aString, val)) {
nsHTMLTagContent::SetAttribute(aAttribute, val);
return;
}
// Use default attribute catching code
nsHTMLTagContent::SetAttribute(aAttribute, aString);
}
nsContentAttr ImagePart::GetAttribute(nsIAtom* aAttribute,
nsHTMLValue& aResult) const
{
nsContentAttr ca = eContentAttr_NotThere;
aResult.Reset();
if (aAttribute == nsHTMLAtoms::ismap) {
if (mIsMap) {
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::usemap) {
if (nsnull != mUseMap) {
aResult.SetStringValue(*mUseMap);
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::align) {
if (ALIGN_UNSET != mAlign) {
aResult.SetIntValue(mAlign, eHTMLUnit_Enumerated);
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::src) {
if (nsnull != mSrc) {
aResult.SetStringValue(*mSrc);
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::lowsrc) {
if (nsnull != mLowSrc) {
aResult.SetStringValue(*mLowSrc);
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::alt) {
if (nsnull != mAltText) {
aResult.SetStringValue(*mAltText);
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::suppress) {
if (SUPPRESS_UNSET != mSuppress) {
switch (mSuppress) {
case SUPPRESS: aResult.SetIntValue(1, eHTMLUnit_Integer); break;
case DONT_SUPPRESS: aResult.SetIntValue(0, eHTMLUnit_Integer); break;
case DEFAULT_SUPPRESS: aResult.SetEmptyValue(); break;
}
ca = eContentAttr_HasValue;
}
}
else {
ca = nsHTMLTagContent::GetAttribute(aAttribute, aResult);
}
return ca;
}
void ImagePart::UnsetAttribute(nsIAtom* aAttribute)
{
if (aAttribute == nsHTMLAtoms::ismap) {
mIsMap = PR_FALSE;
}
else if (aAttribute == nsHTMLAtoms::usemap) {
if (nsnull != mUseMap) {
delete mUseMap;
mUseMap = nsnull;
}
}
else if (aAttribute == nsHTMLAtoms::align) {
mAlign = ALIGN_UNSET;
}
else if (aAttribute == nsHTMLAtoms::src) {
if (nsnull != mSrc) {
delete mSrc;
mSrc = nsnull;
}
}
else if (aAttribute == nsHTMLAtoms::lowsrc) {
if (nsnull != mLowSrc) {
delete mLowSrc;
mSrc = nsnull;
}
}
else if (aAttribute == nsHTMLAtoms::alt) {
if (nsnull != mAltText) {
delete mAltText;
mAltText = nsnull;
}
}
else if (aAttribute == nsHTMLAtoms::suppress) {
mSuppress = SUPPRESS_UNSET;
}
else {
nsHTMLTagContent::UnsetAttribute(aAttribute);
}
}
nsContentAttr ImagePart::AttributeToString(nsIAtom* aAttribute,
nsHTMLValue& aValue,
nsString& aResult) const
{
nsContentAttr ca = eContentAttr_NotThere;
if (aAttribute == nsHTMLAtoms::align) {
if ((eHTMLUnit_Enumerated == aValue.GetUnit()) &&
(ALIGN_UNSET != aValue.GetIntValue())) {
AlignParamToString(aValue, aResult);
ca = eContentAttr_HasValue;
}
}
else if (aAttribute == nsHTMLAtoms::suppress) {
if (SUPPRESS_UNSET != mSuppress) {
aResult.Truncate();
switch (mSuppress) {
case SUPPRESS: aResult.Append("true"); break;
case DONT_SUPPRESS: aResult.Append("false"); break;
case DEFAULT_SUPPRESS: break;
}
ca = eContentAttr_HasValue;
}
}
else if (ImagePropertyToString(aAttribute, aValue, aResult)) {
ca = eContentAttr_HasValue;
}
return ca;
}
void ImagePart::MapAttributesInto(nsIStyleContext* aContext,
nsIPresContext* aPresContext)
{
if (ALIGN_UNSET != mAlign) {
nsStyleDisplay* display = (nsStyleDisplay*)
aContext->GetData(eStyleStruct_Display);
nsStyleText* text = (nsStyleText*)
aContext->GetData(eStyleStruct_Text);
switch (mAlign) {
case NS_STYLE_TEXT_ALIGN_LEFT:
display->mFloats = NS_STYLE_FLOAT_LEFT;
break;
case NS_STYLE_TEXT_ALIGN_RIGHT:
display->mFloats = NS_STYLE_FLOAT_RIGHT;
break;
default:
text->mVerticalAlign.SetIntValue(mAlign, eStyleUnit_Enumerated);
break;
}
}
MapImagePropertiesInto(aContext, aPresContext);
MapImageBorderInto(aContext, aPresContext, nsnull);
}
nsresult
ImagePart::CreateFrame(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsIFrame*& aResult)
{
ImageFrame* frame = new ImageFrame(this, aParentFrame);
if (nsnull == frame) {
return NS_ERROR_OUT_OF_MEMORY;
}
aResult = frame;
frame->SetStyleContext(aPresContext, aStyleContext);
return NS_OK;
}
nsresult
NS_NewHTMLImage(nsIHTMLContent** aInstancePtrResult,
nsIAtom* aTag)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
nsIHTMLContent* img = new ImagePart(aTag);
if (nsnull == img) {
return NS_ERROR_OUT_OF_MEMORY;
}
return img->QueryInterface(kIHTMLContentIID, (void **) aInstancePtrResult);
}