• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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.
6  *
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.
11  *
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.
16  *
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.
21  */
22 
23 #include "config.h"
24 #include "core/html/HTMLImageElement.h"
25 
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/fetch/ImageResource.h"
36 #include "core/frame/UseCounter.h"
37 #include "core/html/HTMLAnchorElement.h"
38 #include "core/html/HTMLCanvasElement.h"
39 #include "core/html/HTMLFormElement.h"
40 #include "core/html/HTMLSourceElement.h"
41 #include "core/html/canvas/CanvasRenderingContext.h"
42 #include "core/html/parser/HTMLParserIdioms.h"
43 #include "core/html/parser/HTMLSrcsetParser.h"
44 #include "core/inspector/ConsoleMessage.h"
45 #include "core/rendering/RenderImage.h"
46 #include "platform/MIMETypeRegistry.h"
47 #include "platform/RuntimeEnabledFeatures.h"
48 
49 namespace blink {
50 
51 using namespace HTMLNames;
52 
53 class HTMLImageElement::ViewportChangeListener FINAL : public MediaQueryListListener {
54 public:
create(HTMLImageElement * element)55     static RefPtrWillBeRawPtr<ViewportChangeListener> create(HTMLImageElement* element)
56     {
57         return adoptRefWillBeNoop(new ViewportChangeListener(element));
58     }
59 
notifyMediaQueryChanged()60     virtual void notifyMediaQueryChanged() OVERRIDE
61     {
62         if (m_element)
63             m_element->notifyViewportChanged();
64     }
65 
66 #if !ENABLE(OILPAN)
clearElement()67     void clearElement() { m_element = nullptr; }
68 #endif
trace(Visitor * visitor)69     virtual void trace(Visitor* visitor) OVERRIDE
70     {
71         visitor->trace(m_element);
72         MediaQueryListListener::trace(visitor);
73     }
74 private:
ViewportChangeListener(HTMLImageElement * element)75     explicit ViewportChangeListener(HTMLImageElement* element) : m_element(element) { }
76     RawPtrWillBeMember<HTMLImageElement> m_element;
77 };
78 
HTMLImageElement(Document & document,HTMLFormElement * form,bool createdByParser)79 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bool createdByParser)
80     : HTMLElement(imgTag, document)
81     , m_imageLoader(HTMLImageLoader::create(this))
82     , m_compositeOperator(CompositeSourceOver)
83     , m_imageDevicePixelRatio(1.0f)
84     , m_formWasSetByParser(false)
85     , m_elementCreatedByParser(createdByParser)
86     , m_intrinsicSizingViewportDependant(false)
87     , m_effectiveSizeViewportDependant(false)
88 {
89     if (form && form->inDocument()) {
90 #if ENABLE(OILPAN)
91         m_form = form;
92 #else
93         m_form = form->createWeakPtr();
94 #endif
95         m_formWasSetByParser = true;
96         m_form->associate(*this);
97         m_form->didAssociateByParser();
98     }
99 }
100 
create(Document & document)101 PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::create(Document& document)
102 {
103     return adoptRefWillBeNoop(new HTMLImageElement(document));
104 }
105 
create(Document & document,HTMLFormElement * form,bool createdByParser)106 PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::create(Document& document, HTMLFormElement* form, bool createdByParser)
107 {
108     return adoptRefWillBeNoop(new HTMLImageElement(document, form, createdByParser));
109 }
110 
~HTMLImageElement()111 HTMLImageElement::~HTMLImageElement()
112 {
113 #if !ENABLE(OILPAN)
114     if (m_listener) {
115         document().mediaQueryMatcher().removeViewportListener(m_listener.get());
116         m_listener->clearElement();
117     }
118     if (m_form)
119         m_form->disassociate(*this);
120 #endif
121 }
122 
trace(Visitor * visitor)123 void HTMLImageElement::trace(Visitor* visitor)
124 {
125     visitor->trace(m_imageLoader);
126     visitor->trace(m_listener);
127     visitor->trace(m_form);
128     HTMLElement::trace(visitor);
129 }
130 
notifyViewportChanged()131 void HTMLImageElement::notifyViewportChanged()
132 {
133     // Re-selecting the source URL in order to pick a more fitting resource
134     // And update the image's intrinsic dimensions when the viewport changes.
135     // Picking of a better fitting resource is UA dependant, not spec required.
136     selectSourceURL(ImageLoader::UpdateSizeChanged);
137 }
138 
createForJSConstructor(Document & document,int width,int height)139 PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document& document, int width, int height)
140 {
141     RefPtrWillBeRawPtr<HTMLImageElement> image = adoptRefWillBeNoop(new HTMLImageElement(document));
142     if (width)
143         image->setWidth(width);
144     if (height)
145         image->setHeight(height);
146     image->m_elementCreatedByParser = false;
147     return image.release();
148 }
149 
isPresentationAttribute(const QualifiedName & name) const150 bool HTMLImageElement::isPresentationAttribute(const QualifiedName& name) const
151 {
152     if (name == widthAttr || name == heightAttr || name == borderAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr || name == valignAttr)
153         return true;
154     return HTMLElement::isPresentationAttribute(name);
155 }
156 
collectStyleForPresentationAttribute(const QualifiedName & name,const AtomicString & value,MutableStylePropertySet * style)157 void HTMLImageElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
158 {
159     if (name == widthAttr)
160         addHTMLLengthToStyle(style, CSSPropertyWidth, value);
161     else if (name == heightAttr)
162         addHTMLLengthToStyle(style, CSSPropertyHeight, value);
163     else if (name == borderAttr)
164         applyBorderAttributeToStyle(value, style);
165     else if (name == vspaceAttr) {
166         addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
167         addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
168     } else if (name == hspaceAttr) {
169         addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
170         addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
171     } else if (name == alignAttr)
172         applyAlignmentAttributeToStyle(value, style);
173     else if (name == valignAttr)
174         addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, value);
175     else
176         HTMLElement::collectStyleForPresentationAttribute(name, value, style);
177 }
178 
imageSourceURL() const179 const AtomicString HTMLImageElement::imageSourceURL() const
180 {
181     return m_bestFitImageURL.isNull() ? fastGetAttribute(srcAttr) : m_bestFitImageURL;
182 }
183 
formOwner() const184 HTMLFormElement* HTMLImageElement::formOwner() const
185 {
186     return m_form.get();
187 }
188 
formRemovedFromTree(const Node & formRoot)189 void HTMLImageElement::formRemovedFromTree(const Node& formRoot)
190 {
191     ASSERT(m_form);
192     if (NodeTraversal::highestAncestorOrSelf(*this) != formRoot)
193         resetFormOwner();
194 }
195 
resetFormOwner()196 void HTMLImageElement::resetFormOwner()
197 {
198     m_formWasSetByParser = false;
199     HTMLFormElement* nearestForm = findFormAncestor();
200     if (m_form) {
201         if (nearestForm == m_form.get())
202             return;
203         m_form->disassociate(*this);
204     }
205     if (nearestForm) {
206 #if ENABLE(OILPAN)
207         m_form = nearestForm;
208 #else
209         m_form = nearestForm->createWeakPtr();
210 #endif
211         m_form->associate(*this);
212     } else {
213 #if ENABLE(OILPAN)
214         m_form = nullptr;
215 #else
216         m_form = WeakPtr<HTMLFormElement>();
217 #endif
218     }
219 }
220 
setBestFitURLAndDPRFromImageCandidate(const ImageCandidate & candidate)221 void HTMLImageElement::setBestFitURLAndDPRFromImageCandidate(const ImageCandidate& candidate)
222 {
223     m_bestFitImageURL = candidate.url();
224     float candidateDensity = candidate.density();
225     if (candidateDensity >= 0)
226         m_imageDevicePixelRatio = 1.0 / candidateDensity;
227     if (candidate.resourceWidth() > 0) {
228         m_intrinsicSizingViewportDependant = true;
229         UseCounter::count(document(), UseCounter::SrcsetWDescriptor);
230     } else if (!candidate.srcOrigin()) {
231         UseCounter::count(document(), UseCounter::SrcsetXDescriptor);
232     }
233     if (renderer() && renderer()->isImage())
234         toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRatio);
235 }
236 
parseAttribute(const QualifiedName & name,const AtomicString & value)237 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
238 {
239     if (name == altAttr) {
240         if (renderer() && renderer()->isImage())
241             toRenderImage(renderer())->updateAltText();
242     } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) {
243         selectSourceURL(ImageLoader::UpdateIgnorePreviousError);
244     } else if (name == usemapAttr) {
245         setIsLink(!value.isNull());
246     } else if (name == compositeAttr) {
247         blink::WebBlendMode blendOp = blink::WebBlendModeNormal;
248         if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp))
249             m_compositeOperator = CompositeSourceOver;
250         else if (m_compositeOperator != CompositeSourceOver)
251             UseCounter::count(document(), UseCounter::HTMLImageElementComposite);
252     } else {
253         HTMLElement::parseAttribute(name, value);
254     }
255 }
256 
altText() const257 const AtomicString& HTMLImageElement::altText() const
258 {
259     // lets figure out the alt text.. magic stuff
260     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
261     // also heavily discussed by Hixie on bugzilla
262     const AtomicString& alt = fastGetAttribute(altAttr);
263     if (!alt.isNull())
264         return alt;
265     // fall back to title attribute
266     return fastGetAttribute(titleAttr);
267 }
268 
supportedImageType(const String & type)269 static bool supportedImageType(const String& type)
270 {
271     return MIMETypeRegistry::isSupportedImagePrefixedMIMEType(type);
272 }
273 
274 // http://picture.responsiveimages.org/#update-source-set
findBestFitImageFromPictureParent()275 ImageCandidate HTMLImageElement::findBestFitImageFromPictureParent()
276 {
277     ASSERT(isMainThread());
278     Node* parent = parentNode();
279     if (!parent || !isHTMLPictureElement(*parent))
280         return ImageCandidate();
281     for (Node* child = parent->firstChild(); child; child = child->nextSibling()) {
282         if (child == this)
283             return ImageCandidate();
284 
285         if (!isHTMLSourceElement(*child))
286             continue;
287 
288         HTMLSourceElement* source = toHTMLSourceElement(child);
289         if (!source->fastGetAttribute(srcAttr).isNull())
290             UseCounter::countDeprecation(document(), UseCounter::PictureSourceSrc);
291         String srcset = source->fastGetAttribute(srcsetAttr);
292         if (srcset.isEmpty())
293             continue;
294         String type = source->fastGetAttribute(typeAttr);
295         if (!type.isEmpty() && !supportedImageType(type))
296             continue;
297 
298         if (!source->mediaQueryMatches())
299             continue;
300 
301         String sizes = source->fastGetAttribute(sizesAttr);
302         if (!sizes.isNull())
303             UseCounter::count(document(), UseCounter::Sizes);
304         SizesAttributeParser parser = SizesAttributeParser(MediaValuesDynamic::create(document()), sizes);
305         unsigned effectiveSize = parser.length();
306         m_effectiveSizeViewportDependant = parser.viewportDependant();
307         ImageCandidate candidate = bestFitSourceForSrcsetAttribute(document().devicePixelRatio(), effectiveSize, source->fastGetAttribute(srcsetAttr));
308         if (candidate.isEmpty())
309             continue;
310         return candidate;
311     }
312     return ImageCandidate();
313 }
314 
createRenderer(RenderStyle * style)315 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style)
316 {
317     if (style->hasContent())
318         return RenderObject::createObject(this, style);
319 
320     RenderImage* image = new RenderImage(this);
321     image->setImageResource(RenderImageResource::create());
322     image->setImageDevicePixelRatio(m_imageDevicePixelRatio);
323     return image;
324 }
325 
canStartSelection() const326 bool HTMLImageElement::canStartSelection() const
327 {
328     if (shadow())
329         return HTMLElement::canStartSelection();
330 
331     return false;
332 }
333 
attach(const AttachContext & context)334 void HTMLImageElement::attach(const AttachContext& context)
335 {
336     HTMLElement::attach(context);
337 
338     if (renderer() && renderer()->isImage()) {
339         RenderImage* renderImage = toRenderImage(renderer());
340         RenderImageResource* renderImageResource = renderImage->imageResource();
341         if (renderImageResource->hasImage())
342             return;
343 
344         // If we have no image at all because we have no src attribute, set
345         // image height and width for the alt text instead.
346         if (!imageLoader().image() && !renderImageResource->cachedImage())
347             renderImage->setImageSizeForAltText();
348         else
349             renderImageResource->setImageResource(imageLoader().image());
350 
351     }
352 }
353 
insertedInto(ContainerNode * insertionPoint)354 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode* insertionPoint)
355 {
356     if (!m_formWasSetByParser || NodeTraversal::highestAncestorOrSelf(*insertionPoint) != NodeTraversal::highestAncestorOrSelf(*m_form.get()))
357         resetFormOwner();
358     if (m_listener)
359         document().mediaQueryMatcher().addViewportListener(m_listener);
360 
361     bool imageWasModified = false;
362     if (RuntimeEnabledFeatures::pictureEnabled()) {
363         ImageCandidate candidate = findBestFitImageFromPictureParent();
364         if (!candidate.isEmpty()) {
365             setBestFitURLAndDPRFromImageCandidate(candidate);
366             imageWasModified = true;
367         }
368     }
369 
370     // If we have been inserted from a renderer-less document,
371     // our loader may have not fetched the image, so do it now.
372     if ((insertionPoint->inDocument() && !imageLoader().image()) || imageWasModified)
373         imageLoader().updateFromElement(ImageLoader::UpdateNormal, m_elementCreatedByParser ? ImageLoader::ForceLoadImmediately : ImageLoader::LoadNormally);
374 
375     return HTMLElement::insertedInto(insertionPoint);
376 }
377 
removedFrom(ContainerNode * insertionPoint)378 void HTMLImageElement::removedFrom(ContainerNode* insertionPoint)
379 {
380     if (!m_form || NodeTraversal::highestAncestorOrSelf(*m_form.get()) != NodeTraversal::highestAncestorOrSelf(*this))
381         resetFormOwner();
382     if (m_listener)
383         document().mediaQueryMatcher().removeViewportListener(m_listener);
384     HTMLElement::removedFrom(insertionPoint);
385 }
386 
width(bool ignorePendingStylesheets)387 int HTMLImageElement::width(bool ignorePendingStylesheets)
388 {
389     if (!renderer()) {
390         // check the attribute first for an explicit pixel value
391         bool ok;
392         int width = getAttribute(widthAttr).toInt(&ok);
393         if (ok)
394             return width;
395 
396         // if the image is available, use its width
397         if (imageLoader().image())
398             return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f).width();
399     }
400 
401     if (ignorePendingStylesheets)
402         document().updateLayoutIgnorePendingStylesheets();
403     else
404         document().updateLayout();
405 
406     RenderBox* box = renderBox();
407     return box ? adjustForAbsoluteZoom(box->contentBoxRect().pixelSnappedWidth(), box) : 0;
408 }
409 
height(bool ignorePendingStylesheets)410 int HTMLImageElement::height(bool ignorePendingStylesheets)
411 {
412     if (!renderer()) {
413         // check the attribute first for an explicit pixel value
414         bool ok;
415         int height = getAttribute(heightAttr).toInt(&ok);
416         if (ok)
417             return height;
418 
419         // if the image is available, use its height
420         if (imageLoader().image())
421             return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f).height();
422     }
423 
424     if (ignorePendingStylesheets)
425         document().updateLayoutIgnorePendingStylesheets();
426     else
427         document().updateLayout();
428 
429     RenderBox* box = renderBox();
430     return box ? adjustForAbsoluteZoom(box->contentBoxRect().pixelSnappedHeight(), box) : 0;
431 }
432 
naturalWidth() const433 int HTMLImageElement::naturalWidth() const
434 {
435     if (!imageLoader().image())
436         return 0;
437 
438     return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f, ImageResource::IntrinsicSize).width();
439 }
440 
naturalHeight() const441 int HTMLImageElement::naturalHeight() const
442 {
443     if (!imageLoader().image())
444         return 0;
445 
446     return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f, ImageResource::IntrinsicSize).height();
447 }
448 
currentSrc() const449 const String& HTMLImageElement::currentSrc() const
450 {
451     // http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#dom-img-currentsrc
452     // The currentSrc IDL attribute must return the img element's current request's current URL.
453     // Initially, the pending request turns into current request when it is either available or broken.
454     // We use the image's dimensions as a proxy to it being in any of these states.
455     if (!imageLoader().image() || !imageLoader().image()->image() || !imageLoader().image()->image()->width())
456         return emptyAtom;
457 
458     return imageLoader().image()->url().string();
459 }
460 
isURLAttribute(const Attribute & attribute) const461 bool HTMLImageElement::isURLAttribute(const Attribute& attribute) const
462 {
463     return attribute.name() == srcAttr
464         || attribute.name() == lowsrcAttr
465         || attribute.name() == longdescAttr
466         || (attribute.name() == usemapAttr && attribute.value()[0] != '#')
467         || HTMLElement::isURLAttribute(attribute);
468 }
469 
hasLegalLinkAttribute(const QualifiedName & name) const470 bool HTMLImageElement::hasLegalLinkAttribute(const QualifiedName& name) const
471 {
472     return name == srcAttr || HTMLElement::hasLegalLinkAttribute(name);
473 }
474 
subResourceAttributeName() const475 const QualifiedName& HTMLImageElement::subResourceAttributeName() const
476 {
477     return srcAttr;
478 }
479 
draggable() const480 bool HTMLImageElement::draggable() const
481 {
482     // Image elements are draggable by default.
483     return !equalIgnoringCase(getAttribute(draggableAttr), "false");
484 }
485 
setHeight(int value)486 void HTMLImageElement::setHeight(int value)
487 {
488     setIntegralAttribute(heightAttr, value);
489 }
490 
src() const491 KURL HTMLImageElement::src() const
492 {
493     return document().completeURL(getAttribute(srcAttr));
494 }
495 
setSrc(const String & value)496 void HTMLImageElement::setSrc(const String& value)
497 {
498     setAttribute(srcAttr, AtomicString(value));
499 }
500 
setWidth(int value)501 void HTMLImageElement::setWidth(int value)
502 {
503     setIntegralAttribute(widthAttr, value);
504 }
505 
x() const506 int HTMLImageElement::x() const
507 {
508     document().updateLayoutIgnorePendingStylesheets();
509     RenderObject* r = renderer();
510     if (!r)
511         return 0;
512 
513     // FIXME: This doesn't work correctly with transforms.
514     FloatPoint absPos = r->localToAbsolute();
515     return absPos.x();
516 }
517 
y() const518 int HTMLImageElement::y() const
519 {
520     document().updateLayoutIgnorePendingStylesheets();
521     RenderObject* r = renderer();
522     if (!r)
523         return 0;
524 
525     // FIXME: This doesn't work correctly with transforms.
526     FloatPoint absPos = r->localToAbsolute();
527     return absPos.y();
528 }
529 
complete() const530 bool HTMLImageElement::complete() const
531 {
532     return imageLoader().imageComplete();
533 }
534 
didMoveToNewDocument(Document & oldDocument)535 void HTMLImageElement::didMoveToNewDocument(Document& oldDocument)
536 {
537     imageLoader().elementDidMoveToNewDocument();
538     HTMLElement::didMoveToNewDocument(oldDocument);
539 }
540 
isServerMap() const541 bool HTMLImageElement::isServerMap() const
542 {
543     if (!fastHasAttribute(ismapAttr))
544         return false;
545 
546     const AtomicString& usemap = fastGetAttribute(usemapAttr);
547 
548     // If the usemap attribute starts with '#', it refers to a map element in the document.
549     if (usemap[0] == '#')
550         return false;
551 
552     return document().completeURL(stripLeadingAndTrailingHTMLSpaces(usemap)).isEmpty();
553 }
554 
imageContents()555 Image* HTMLImageElement::imageContents()
556 {
557     if (!imageLoader().imageComplete())
558         return 0;
559 
560     return imageLoader().image()->image();
561 }
562 
isInteractiveContent() const563 bool HTMLImageElement::isInteractiveContent() const
564 {
565     return fastHasAttribute(usemapAttr);
566 }
567 
getSourceImageForCanvas(SourceImageMode,SourceImageStatus * status) const568 PassRefPtr<Image> HTMLImageElement::getSourceImageForCanvas(SourceImageMode, SourceImageStatus* status) const
569 {
570     if (!complete() || !cachedImage()) {
571         *status = IncompleteSourceImageStatus;
572         return nullptr;
573     }
574 
575     if (cachedImage()->errorOccurred()) {
576         *status = UndecodableSourceImageStatus;
577         return nullptr;
578     }
579 
580     RefPtr<Image> sourceImage = cachedImage()->imageForRenderer(renderer());
581 
582     // We need to synthesize a container size if a renderer is not available to provide one.
583     if (!renderer() && sourceImage->usesContainerSize())
584         sourceImage->setContainerSize(sourceImage->size());
585 
586     *status = NormalSourceImageStatus;
587     return sourceImage->imageForDefaultFrame();
588 }
589 
wouldTaintOrigin(SecurityOrigin * destinationSecurityOrigin) const590 bool HTMLImageElement::wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const
591 {
592     ImageResource* image = cachedImage();
593     if (!image)
594         return false;
595     return !image->isAccessAllowed(destinationSecurityOrigin);
596 }
597 
sourceSize() const598 FloatSize HTMLImageElement::sourceSize() const
599 {
600     ImageResource* image = cachedImage();
601     if (!image)
602         return FloatSize();
603     LayoutSize size;
604     size = image->imageSizeForRenderer(renderer(), 1.0f); // FIXME: Not sure about this.
605 
606     return size;
607 }
608 
defaultDestinationSize() const609 FloatSize HTMLImageElement::defaultDestinationSize() const
610 {
611     ImageResource* image = cachedImage();
612     if (!image)
613         return FloatSize();
614     LayoutSize size;
615     size = image->imageSizeForRenderer(renderer(), 1.0f); // FIXME: Not sure about this.
616     if (renderer() && renderer()->isRenderImage() && image->image() && !image->image()->hasRelativeWidth())
617         size.scale(toRenderImage(renderer())->imageDevicePixelRatio());
618     return size;
619 }
620 
selectSourceURL(ImageLoader::UpdateFromElementBehavior behavior)621 void HTMLImageElement::selectSourceURL(ImageLoader::UpdateFromElementBehavior behavior)
622 {
623     bool foundURL = false;
624     if (RuntimeEnabledFeatures::pictureEnabled()) {
625         ImageCandidate candidate = findBestFitImageFromPictureParent();
626         if (!candidate.isEmpty()) {
627             setBestFitURLAndDPRFromImageCandidate(candidate);
628             foundURL = true;
629         }
630     }
631 
632     if (!foundURL) {
633         unsigned effectiveSize = 0;
634         if (RuntimeEnabledFeatures::pictureSizesEnabled()) {
635             String sizes = fastGetAttribute(sizesAttr);
636             if (!sizes.isNull())
637                 UseCounter::count(document(), UseCounter::Sizes);
638             SizesAttributeParser parser = SizesAttributeParser(MediaValuesDynamic::create(document()), sizes);
639             effectiveSize = parser.length();
640             m_effectiveSizeViewportDependant = parser.viewportDependant();
641         }
642         ImageCandidate candidate = bestFitSourceForImageAttributes(document().devicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr));
643         setBestFitURLAndDPRFromImageCandidate(candidate);
644     }
645     if (m_intrinsicSizingViewportDependant && m_effectiveSizeViewportDependant && !m_listener) {
646         m_listener = ViewportChangeListener::create(this);
647         document().mediaQueryMatcher().addViewportListener(m_listener);
648     }
649     imageLoader().updateFromElement(behavior);
650 }
651 
sourceURL() const652 const KURL& HTMLImageElement::sourceURL() const
653 {
654     return cachedImage()->response().url();
655 }
656 
657 }
658