2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
5 * Copyright (C) 2010 Google Inc. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #include "core/html/HTMLImageElement.h"
26 #include "bindings/core/v8/ScriptEventListener.h"
27 #include "core/CSSPropertyNames.h"
28 #include "core/HTMLNames.h"
29 #include "core/MediaTypeNames.h"
30 #include "core/css/MediaQueryMatcher.h"
31 #include "core/css/MediaValuesDynamic.h"
32 #include "core/css/parser/SizesAttributeParser.h"
33 #include "core/dom/Attribute.h"
34 #include "core/dom/NodeTraversal.h"
35 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/fetch/ImageResource.h"
37 #include "core/frame/UseCounter.h"
38 #include "core/html/HTMLAnchorElement.h"
39 #include "core/html/HTMLCanvasElement.h"
40 #include "core/html/HTMLFormElement.h"
41 #include "core/html/HTMLImageFallbackHelper.h"
42 #include "core/html/HTMLSourceElement.h"
43 #include "core/html/parser/HTMLParserIdioms.h"
44 #include "core/html/parser/HTMLSrcsetParser.h"
45 #include "core/inspector/ConsoleMessage.h"
46 #include "core/layout/LayoutBlockFlow.h"
47 #include "core/layout/LayoutImage.h"
48 #include "core/page/Page.h"
49 #include "core/style/ContentData.h"
50 #include "platform/ContentType.h"
51 #include "platform/EventDispatchForbiddenScope.h"
52 #include "platform/MIMETypeRegistry.h"
53 #include "platform/RuntimeEnabledFeatures.h"
54 #include "platform/weborigin/SecurityPolicy.h"
58 using namespace HTMLNames
;
60 class HTMLImageElement::ViewportChangeListener final
: public MediaQueryListListener
{
62 static RefPtrWillBeRawPtr
<ViewportChangeListener
> create(HTMLImageElement
* element
)
64 return adoptRefWillBeNoop(new ViewportChangeListener(element
));
67 void notifyMediaQueryChanged() override
70 m_element
->notifyViewportChanged();
74 void clearElement() { m_element
= nullptr; }
76 DEFINE_INLINE_VIRTUAL_TRACE()
78 visitor
->trace(m_element
);
79 MediaQueryListListener::trace(visitor
);
82 explicit ViewportChangeListener(HTMLImageElement
* element
) : m_element(element
) { }
83 RawPtrWillBeMember
<HTMLImageElement
> m_element
;
86 HTMLImageElement::HTMLImageElement(Document
& document
, HTMLFormElement
* form
, bool createdByParser
)
87 : HTMLElement(imgTag
, document
)
88 , m_imageLoader(HTMLImageLoader::create(this))
89 , m_imageDevicePixelRatio(1.0f
)
90 , m_formWasSetByParser(false)
91 , m_elementCreatedByParser(createdByParser
)
92 , m_intrinsicSizingViewportDependant(false)
93 , m_useFallbackContent(false)
94 , m_isFallbackImage(false)
95 , m_referrerPolicy(ReferrerPolicyDefault
)
97 setHasCustomStyleCallbacks();
98 if (form
&& form
->inDocument()) {
102 m_form
= form
->createWeakPtr();
104 m_formWasSetByParser
= true;
105 m_form
->associate(*this);
106 m_form
->didAssociateByParser();
110 PassRefPtrWillBeRawPtr
<HTMLImageElement
> HTMLImageElement::create(Document
& document
)
112 return adoptRefWillBeNoop(new HTMLImageElement(document
));
115 PassRefPtrWillBeRawPtr
<HTMLImageElement
> HTMLImageElement::create(Document
& document
, HTMLFormElement
* form
, bool createdByParser
)
117 return adoptRefWillBeNoop(new HTMLImageElement(document
, form
, createdByParser
));
120 HTMLImageElement::~HTMLImageElement()
124 document().mediaQueryMatcher().removeViewportListener(m_listener
.get());
125 m_listener
->clearElement();
128 m_form
->disassociate(*this);
132 DEFINE_TRACE(HTMLImageElement
)
134 visitor
->trace(m_imageLoader
);
135 visitor
->trace(m_listener
);
136 visitor
->trace(m_form
);
137 HTMLElement::trace(visitor
);
140 void HTMLImageElement::notifyViewportChanged()
142 // Re-selecting the source URL in order to pick a more fitting resource
143 // And update the image's intrinsic dimensions when the viewport changes.
144 // Picking of a better fitting resource is UA dependant, not spec required.
145 selectSourceURL(ImageLoader::UpdateSizeChanged
);
148 PassRefPtrWillBeRawPtr
<HTMLImageElement
> HTMLImageElement::createForJSConstructor(Document
& document
)
150 RefPtrWillBeRawPtr
<HTMLImageElement
> image
= adoptRefWillBeNoop(new HTMLImageElement(document
));
151 image
->m_elementCreatedByParser
= false;
152 return image
.release();
155 PassRefPtrWillBeRawPtr
<HTMLImageElement
> HTMLImageElement::createForJSConstructor(Document
& document
, int width
)
157 RefPtrWillBeRawPtr
<HTMLImageElement
> image
= adoptRefWillBeNoop(new HTMLImageElement(document
));
158 image
->setWidth(width
);
159 image
->m_elementCreatedByParser
= false;
160 return image
.release();
163 PassRefPtrWillBeRawPtr
<HTMLImageElement
> HTMLImageElement::createForJSConstructor(Document
& document
, int width
, int height
)
165 RefPtrWillBeRawPtr
<HTMLImageElement
> image
= adoptRefWillBeNoop(new HTMLImageElement(document
));
166 image
->setWidth(width
);
167 image
->setHeight(height
);
168 image
->m_elementCreatedByParser
= false;
169 return image
.release();
172 bool HTMLImageElement::isPresentationAttribute(const QualifiedName
& name
) const
174 if (name
== widthAttr
|| name
== heightAttr
|| name
== borderAttr
|| name
== vspaceAttr
|| name
== hspaceAttr
|| name
== alignAttr
|| name
== valignAttr
)
176 return HTMLElement::isPresentationAttribute(name
);
179 void HTMLImageElement::collectStyleForPresentationAttribute(const QualifiedName
& name
, const AtomicString
& value
, MutableStylePropertySet
* style
)
181 if (name
== widthAttr
) {
182 addHTMLLengthToStyle(style
, CSSPropertyWidth
, value
);
183 } else if (name
== heightAttr
) {
184 addHTMLLengthToStyle(style
, CSSPropertyHeight
, value
);
185 } else if (name
== borderAttr
) {
186 applyBorderAttributeToStyle(value
, style
);
187 } else if (name
== vspaceAttr
) {
188 addHTMLLengthToStyle(style
, CSSPropertyMarginTop
, value
);
189 addHTMLLengthToStyle(style
, CSSPropertyMarginBottom
, value
);
190 } else if (name
== hspaceAttr
) {
191 addHTMLLengthToStyle(style
, CSSPropertyMarginLeft
, value
);
192 addHTMLLengthToStyle(style
, CSSPropertyMarginRight
, value
);
193 } else if (name
== alignAttr
) {
194 applyAlignmentAttributeToStyle(value
, style
);
195 } else if (name
== valignAttr
) {
196 addPropertyToPresentationAttributeStyle(style
, CSSPropertyVerticalAlign
, value
);
198 HTMLElement::collectStyleForPresentationAttribute(name
, value
, style
);
202 const AtomicString
HTMLImageElement::imageSourceURL() const
204 return m_bestFitImageURL
.isNull() ? fastGetAttribute(srcAttr
) : m_bestFitImageURL
;
207 HTMLFormElement
* HTMLImageElement::formOwner() const
212 void HTMLImageElement::formRemovedFromTree(const Node
& formRoot
)
215 if (NodeTraversal::highestAncestorOrSelf(*this) != formRoot
)
219 void HTMLImageElement::resetFormOwner()
221 m_formWasSetByParser
= false;
222 HTMLFormElement
* nearestForm
= findFormAncestor();
224 if (nearestForm
== m_form
.get())
226 m_form
->disassociate(*this);
230 m_form
= nearestForm
;
232 m_form
= nearestForm
->createWeakPtr();
234 m_form
->associate(*this);
239 m_form
= WeakPtr
<HTMLFormElement
>();
244 void HTMLImageElement::setBestFitURLAndDPRFromImageCandidate(const ImageCandidate
& candidate
)
246 m_bestFitImageURL
= candidate
.url();
247 float candidateDensity
= candidate
.density();
248 if (candidateDensity
>= 0)
249 m_imageDevicePixelRatio
= 1.0 / candidateDensity
;
250 if (candidate
.resourceWidth() > 0) {
251 m_intrinsicSizingViewportDependant
= true;
252 UseCounter::count(document(), UseCounter::SrcsetWDescriptor
);
253 } else if (!candidate
.srcOrigin()) {
254 UseCounter::count(document(), UseCounter::SrcsetXDescriptor
);
256 if (layoutObject() && layoutObject()->isImage())
257 toLayoutImage(layoutObject())->setImageDevicePixelRatio(m_imageDevicePixelRatio
);
260 void HTMLImageElement::parseAttribute(const QualifiedName
& name
, const AtomicString
& value
)
262 if (name
== altAttr
|| name
== titleAttr
) {
263 if (userAgentShadowRoot()) {
264 Element
* text
= userAgentShadowRoot()->getElementById("alttext");
265 String value
= altText();
266 if (text
&& text
->textContent() != value
)
267 text
->setTextContent(altText());
269 } else if (name
== srcAttr
|| name
== srcsetAttr
|| name
== sizesAttr
) {
270 selectSourceURL(ImageLoader::UpdateIgnorePreviousError
);
271 } else if (name
== usemapAttr
) {
272 setIsLink(!value
.isNull());
273 } else if (RuntimeEnabledFeatures::referrerPolicyAttributeEnabled() && name
== referrerpolicyAttr
) {
274 m_referrerPolicy
= ReferrerPolicyDefault
;
276 SecurityPolicy::referrerPolicyFromString(value
, &m_referrerPolicy
);
278 HTMLElement::parseAttribute(name
, value
);
282 String
HTMLImageElement::altText() const
284 // lets figure out the alt text.. magic stuff
285 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
286 // also heavily discussed by Hixie on bugzilla
287 const AtomicString
& alt
= fastGetAttribute(altAttr
);
290 // fall back to title attribute
291 return fastGetAttribute(titleAttr
);
294 static bool supportedImageType(const String
& type
)
296 String trimmedType
= ContentType(type
).type();
297 // An empty type attribute is implicitly supported.
298 if (trimmedType
.isEmpty())
300 return MIMETypeRegistry::isSupportedImagePrefixedMIMEType(trimmedType
);
303 // http://picture.responsiveimages.org/#update-source-set
304 ImageCandidate
HTMLImageElement::findBestFitImageFromPictureParent()
306 ASSERT(isMainThread());
307 Node
* parent
= parentNode();
308 if (!parent
|| !isHTMLPictureElement(*parent
))
309 return ImageCandidate();
310 for (Node
* child
= parent
->firstChild(); child
; child
= child
->nextSibling()) {
312 return ImageCandidate();
314 if (!isHTMLSourceElement(*child
))
317 HTMLSourceElement
* source
= toHTMLSourceElement(child
);
318 if (!source
->fastGetAttribute(srcAttr
).isNull())
319 UseCounter::countDeprecation(document(), UseCounter::PictureSourceSrc
);
320 String srcset
= source
->fastGetAttribute(srcsetAttr
);
321 if (srcset
.isEmpty())
323 String type
= source
->fastGetAttribute(typeAttr
);
324 if (!type
.isEmpty() && !supportedImageType(type
))
327 if (!source
->mediaQueryMatches())
330 ImageCandidate candidate
= bestFitSourceForSrcsetAttribute(document().devicePixelRatio(), sourceSize(*source
), source
->fastGetAttribute(srcsetAttr
), &document());
331 if (candidate
.isEmpty())
335 return ImageCandidate();
338 LayoutObject
* HTMLImageElement::createLayoutObject(const ComputedStyle
& style
)
340 const ContentData
* contentData
= style
.contentData();
341 if (contentData
&& contentData
->isImage()) {
342 const StyleImage
* contentImage
= toImageContentData(contentData
)->image();
343 bool errorOccurred
= contentImage
&& contentImage
->cachedImage() && contentImage
->cachedImage()->errorOccurred();
345 return LayoutObject::createObject(this, style
);
348 if (m_useFallbackContent
)
349 return new LayoutBlockFlow(this);
351 LayoutImage
* image
= new LayoutImage(this);
352 image
->setImageResource(LayoutImageResource::create());
353 image
->setImageDevicePixelRatio(m_imageDevicePixelRatio
);
357 void HTMLImageElement::attach(const AttachContext
& context
)
359 HTMLElement::attach(context
);
361 if (layoutObject() && layoutObject()->isImage()) {
362 LayoutImage
* layoutImage
= toLayoutImage(layoutObject());
363 LayoutImageResource
* layoutImageResource
= layoutImage
->imageResource();
364 if (m_isFallbackImage
) {
365 float deviceScaleFactor
= blink::deviceScaleFactor(layoutImage
->frame());
366 pair
<Image
*, float> brokenImageAndImageScaleFactor
= ImageResource::brokenImage(deviceScaleFactor
);
367 ImageResource
* newImageResource
= new ImageResource(brokenImageAndImageScaleFactor
.first
);
368 layoutImage
->imageResource()->setImageResource(newImageResource
);
370 if (layoutImageResource
->hasImage())
373 if (!imageLoader().image() && !layoutImageResource
->cachedImage())
375 layoutImageResource
->setImageResource(imageLoader().image());
379 Node::InsertionNotificationRequest
HTMLImageElement::insertedInto(ContainerNode
* insertionPoint
)
381 if (!m_formWasSetByParser
|| NodeTraversal::highestAncestorOrSelf(*insertionPoint
) != NodeTraversal::highestAncestorOrSelf(*m_form
.get()))
384 document().mediaQueryMatcher().addViewportListener(m_listener
);
386 bool imageWasModified
= false;
387 if (document().isActive()) {
388 ImageCandidate candidate
= findBestFitImageFromPictureParent();
389 if (!candidate
.isEmpty()) {
390 setBestFitURLAndDPRFromImageCandidate(candidate
);
391 imageWasModified
= true;
395 // If we have been inserted from a layoutObject-less document,
396 // our loader may have not fetched the image, so do it now.
397 if ((insertionPoint
->inDocument() && !imageLoader().image()) || imageWasModified
)
398 imageLoader().updateFromElement(ImageLoader::UpdateNormal
, m_referrerPolicy
);
400 return HTMLElement::insertedInto(insertionPoint
);
403 void HTMLImageElement::removedFrom(ContainerNode
* insertionPoint
)
405 if (!m_form
|| NodeTraversal::highestAncestorOrSelf(*m_form
.get()) != NodeTraversal::highestAncestorOrSelf(*this))
408 document().mediaQueryMatcher().removeViewportListener(m_listener
);
409 HTMLElement::removedFrom(insertionPoint
);
412 int HTMLImageElement::width()
414 if (inActiveDocument())
415 document().updateLayoutIgnorePendingStylesheets();
417 if (!layoutObject()) {
418 // check the attribute first for an explicit pixel value
420 int width
= getAttribute(widthAttr
).toInt(&ok
);
424 // if the image is available, use its width
425 if (imageLoader().image())
426 return imageLoader().image()->imageSizeForLayoutObject(layoutObject(), 1.0f
).width();
429 LayoutBox
* box
= layoutBox();
430 return box
? adjustForAbsoluteZoom(box
->contentBoxRect().pixelSnappedWidth(), box
) : 0;
433 int HTMLImageElement::height()
435 if (inActiveDocument())
436 document().updateLayoutIgnorePendingStylesheets();
438 if (!layoutObject()) {
439 // check the attribute first for an explicit pixel value
441 int height
= getAttribute(heightAttr
).toInt(&ok
);
445 // if the image is available, use its height
446 if (imageLoader().image())
447 return imageLoader().image()->imageSizeForLayoutObject(layoutObject(), 1.0f
).height();
450 LayoutBox
* box
= layoutBox();
451 return box
? adjustForAbsoluteZoom(box
->contentBoxRect().pixelSnappedHeight(), box
) : 0;
454 int HTMLImageElement::naturalWidth() const
456 if (!imageLoader().image())
459 return imageLoader().image()->imageSizeForLayoutObject(layoutObject(), m_imageDevicePixelRatio
, ImageResource::IntrinsicCorrectedToDPR
).width();
462 int HTMLImageElement::naturalHeight() const
464 if (!imageLoader().image())
467 return imageLoader().image()->imageSizeForLayoutObject(layoutObject(), m_imageDevicePixelRatio
, ImageResource::IntrinsicCorrectedToDPR
).height();
470 const String
& HTMLImageElement::currentSrc() const
472 // http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#dom-img-currentsrc
473 // The currentSrc IDL attribute must return the img element's current request's current URL.
474 // Initially, the pending request turns into current request when it is either available or broken.
475 // We use the image's dimensions as a proxy to it being in any of these states.
476 if (!imageLoader().image() || !imageLoader().image()->image() || !imageLoader().image()->image()->width())
479 return imageLoader().image()->url().string();
482 bool HTMLImageElement::isURLAttribute(const Attribute
& attribute
) const
484 return attribute
.name() == srcAttr
485 || attribute
.name() == lowsrcAttr
486 || attribute
.name() == longdescAttr
487 || (attribute
.name() == usemapAttr
&& attribute
.value()[0] != '#')
488 || HTMLElement::isURLAttribute(attribute
);
491 bool HTMLImageElement::hasLegalLinkAttribute(const QualifiedName
& name
) const
493 return name
== srcAttr
|| HTMLElement::hasLegalLinkAttribute(name
);
496 const QualifiedName
& HTMLImageElement::subResourceAttributeName() const
501 bool HTMLImageElement::draggable() const
503 // Image elements are draggable by default.
504 return !equalIgnoringCase(getAttribute(draggableAttr
), "false");
507 void HTMLImageElement::setHeight(int value
)
509 setIntegralAttribute(heightAttr
, value
);
512 KURL
HTMLImageElement::src() const
514 return document().completeURL(getAttribute(srcAttr
));
517 void HTMLImageElement::setSrc(const String
& value
)
519 setAttribute(srcAttr
, AtomicString(value
));
522 void HTMLImageElement::setWidth(int value
)
524 setIntegralAttribute(widthAttr
, value
);
527 int HTMLImageElement::x() const
529 document().updateLayoutIgnorePendingStylesheets();
530 LayoutObject
* r
= layoutObject();
534 // FIXME: This doesn't work correctly with transforms.
535 FloatPoint absPos
= r
->localToAbsolute();
539 int HTMLImageElement::y() const
541 document().updateLayoutIgnorePendingStylesheets();
542 LayoutObject
* r
= layoutObject();
546 // FIXME: This doesn't work correctly with transforms.
547 FloatPoint absPos
= r
->localToAbsolute();
551 bool HTMLImageElement::complete() const
553 return imageLoader().imageComplete();
556 void HTMLImageElement::didMoveToNewDocument(Document
& oldDocument
)
558 selectSourceURL(ImageLoader::UpdateIgnorePreviousError
);
559 imageLoader().elementDidMoveToNewDocument();
560 HTMLElement::didMoveToNewDocument(oldDocument
);
563 bool HTMLImageElement::isServerMap() const
565 if (!fastHasAttribute(ismapAttr
))
568 const AtomicString
& usemap
= fastGetAttribute(usemapAttr
);
570 // If the usemap attribute starts with '#', it refers to a map element in the document.
571 if (usemap
[0] == '#')
574 return document().completeURL(stripLeadingAndTrailingHTMLSpaces(usemap
)).isEmpty();
577 Image
* HTMLImageElement::imageContents()
579 if (!imageLoader().imageComplete())
582 return imageLoader().image()->image();
585 bool HTMLImageElement::isInteractiveContent() const
587 return fastHasAttribute(usemapAttr
);
590 PassRefPtr
<Image
> HTMLImageElement::getSourceImageForCanvas(SourceImageStatus
* status
) const
592 if (!complete() || !cachedImage()) {
593 *status
= IncompleteSourceImageStatus
;
597 if (cachedImage()->errorOccurred()) {
598 *status
= UndecodableSourceImageStatus
;
602 RefPtr
<Image
> sourceImage
= cachedImage()->imageForLayoutObject(layoutObject());
604 // We need to synthesize a container size if a layoutObject is not available to provide one.
605 if (!layoutObject() && sourceImage
->usesContainerSize())
606 sourceImage
->setContainerSize(sourceImage
->size());
608 *status
= NormalSourceImageStatus
;
609 return sourceImage
->imageForDefaultFrame();
612 bool HTMLImageElement::wouldTaintOrigin(SecurityOrigin
* destinationSecurityOrigin
) const
614 ImageResource
* image
= cachedImage();
617 return !image
->isAccessAllowed(destinationSecurityOrigin
);
620 FloatSize
HTMLImageElement::elementSize() const
622 ImageResource
* image
= cachedImage();
626 return FloatSize(image
->imageSizeForLayoutObject(layoutObject(), 1.0f
));
629 FloatSize
HTMLImageElement::defaultDestinationSize() const
631 ImageResource
* image
= cachedImage();
635 size
= image
->imageSizeForLayoutObject(layoutObject(), 1.0f
);
636 if (layoutObject() && layoutObject()->isLayoutImage() && image
->image() && !image
->image()->hasRelativeWidth())
637 size
.scale(toLayoutImage(layoutObject())->imageDevicePixelRatio());
638 return FloatSize(size
);
641 static bool sourceSizeValue(Element
& element
, Document
& currentDocument
, float& sourceSize
)
643 String sizes
= element
.fastGetAttribute(sizesAttr
);
644 bool exists
= !sizes
.isNull();
646 UseCounter::count(currentDocument
, UseCounter::Sizes
);
647 sourceSize
= SizesAttributeParser(MediaValuesDynamic::create(currentDocument
), sizes
).length();
651 FetchRequest::ResourceWidth
HTMLImageElement::resourceWidth()
653 FetchRequest::ResourceWidth resourceWidth
;
654 resourceWidth
.isSet
= sourceSizeValue(*this, document(), resourceWidth
.width
);
655 return resourceWidth
;
658 float HTMLImageElement::sourceSize(Element
& element
)
661 // We don't care here if the sizes attribute exists, so we ignore the return value.
662 // If it doesn't exist, we just return the default.
663 sourceSizeValue(element
, document(), value
);
667 void HTMLImageElement::forceReload() const
669 imageLoader().updateFromElement(ImageLoader::UpdateForcedReload
, m_referrerPolicy
);
672 void HTMLImageElement::selectSourceURL(ImageLoader::UpdateFromElementBehavior behavior
)
674 if (!document().isActive())
677 bool foundURL
= false;
678 ImageCandidate candidate
= findBestFitImageFromPictureParent();
679 if (!candidate
.isEmpty()) {
680 setBestFitURLAndDPRFromImageCandidate(candidate
);
685 candidate
= bestFitSourceForImageAttributes(document().devicePixelRatio(), sourceSize(*this), fastGetAttribute(srcAttr
), fastGetAttribute(srcsetAttr
), &document());
686 setBestFitURLAndDPRFromImageCandidate(candidate
);
688 if (m_intrinsicSizingViewportDependant
&& !m_listener
) {
689 m_listener
= ViewportChangeListener::create(this);
690 document().mediaQueryMatcher().addViewportListener(m_listener
);
692 imageLoader().updateFromElement(behavior
, m_referrerPolicy
);
694 if (imageLoader().image() || (imageLoader().hasPendingActivity() && !imageSourceURL().isEmpty()))
695 ensurePrimaryContent();
697 ensureFallbackContent();
700 const KURL
& HTMLImageElement::sourceURL() const
702 return cachedImage()->response().url();
705 void HTMLImageElement::didAddUserAgentShadowRoot(ShadowRoot
&)
707 HTMLImageFallbackHelper::createAltTextShadowTree(*this);
710 void HTMLImageElement::ensureFallbackForGeneratedContent()
712 setUseFallbackContent();
713 reattachFallbackContent();
716 void HTMLImageElement::ensureFallbackContent()
718 if (m_useFallbackContent
|| m_isFallbackImage
)
720 setUseFallbackContent();
721 reattachFallbackContent();
724 void HTMLImageElement::ensurePrimaryContent()
726 if (!m_useFallbackContent
)
728 m_useFallbackContent
= false;
729 reattachFallbackContent();
732 void HTMLImageElement::reattachFallbackContent()
734 // This can happen inside of attach() in the middle of a recalcStyle so we need to
735 // reattach synchronously here.
736 if (document().inStyleRecalc())
739 lazyReattachIfAttached();
742 PassRefPtr
<ComputedStyle
> HTMLImageElement::customStyleForLayoutObject()
744 RefPtr
<ComputedStyle
> newStyle
= originalStyleForLayoutObject();
746 if (!m_useFallbackContent
)
749 RefPtr
<ComputedStyle
> style
= ComputedStyle::clone(*newStyle
);
750 return HTMLImageFallbackHelper::customStyleForAltText(*this, style
);
753 void HTMLImageElement::setUseFallbackContent()
755 m_useFallbackContent
= true;
756 if (document().inStyleRecalc())
758 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents
;
759 ensureUserAgentShadowRoot();
762 bool HTMLImageElement::isOpaque() const
764 Image
* image
= const_cast<HTMLImageElement
*>(this)->imageContents();
765 return image
&& image
->currentFrameKnownToBeOpaque();