Index: Source/core/html/HTMLImageElement.cpp |
diff --git a/Source/core/html/HTMLImageElement.cpp b/Source/core/html/HTMLImageElement.cpp |
index ceeb1ede0923b0b2912ddc8e3cd7f60df49ccb64..622398550064b8be6abd76855777cca486263bb1 100644 |
--- a/Source/core/html/HTMLImageElement.cpp |
+++ b/Source/core/html/HTMLImageElement.cpp |
@@ -47,6 +47,30 @@ namespace WebCore { |
using namespace HTMLNames; |
+class HTMLImageElement::Listener FINAL : public MediaQueryListListener { |
+public: |
+ static RefPtrWillBeRawPtr<Listener> create(HTMLImageElement* element) |
+ { |
+ return adoptRefWillBeNoop(new Listener(element)); |
+ } |
+ |
+ virtual void call() OVERRIDE |
+ { |
+ if (m_element) |
+ m_element->notifyMediaQueryChanged(); |
+ } |
+ |
+ void clearElement() { m_element = nullptr; } |
+ virtual void trace(Visitor* visitor) OVERRIDE |
+ { |
+ visitor->trace(m_element); |
+ MediaQueryListListener::trace(visitor); |
+ } |
+private: |
+ Listener(HTMLImageElement* element) : m_element(element) { } |
+ RawPtrWillBeMember<HTMLImageElement> m_element; |
+}; |
+ |
HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bool createdByParser) |
: HTMLElement(imgTag, document) |
, m_imageLoader(HTMLImageLoader::create(this)) |
@@ -54,6 +78,8 @@ HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bo |
, m_imageDevicePixelRatio(1.0f) |
, m_formWasSetByParser(false) |
, m_elementCreatedByParser(createdByParser) |
+ , m_intrinsicSizingViewportDependant(false) |
+ , m_effectiveSizeViewportDependant(false) |
{ |
ScriptWrappable::init(this); |
if (form && form->inDocument()) { |
@@ -81,11 +107,24 @@ PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::create(Document& docu |
HTMLImageElement::~HTMLImageElement() |
{ |
#if !ENABLE(OILPAN) |
+ if (m_listener) |
+ m_listener->clearElement(); |
Yoav Weiss
2014/07/15 09:46:31
Note that clearElement is only called on images th
|
if (m_form) |
m_form->disassociate(*this); |
#endif |
} |
+void HTMLImageElement::createMediaQueryListIfDoesNotExist() |
+{ |
+ if (m_mediaQueryList) |
+ return; |
+ RefPtrWillBeRawPtr<MediaQuerySet> set = MediaQuerySet::create(MediaTypeNames::all); |
+ m_listener = Listener::create(this); |
+ m_mediaQueryList = MediaQueryList::create(&document().mediaQueryMatcher(), set.release()); |
+ m_mediaQueryList->addListener(m_listener); |
+ m_mediaQueryList->alwaysUpdate(); |
+} |
+ |
void HTMLImageElement::trace(Visitor* visitor) |
{ |
visitor->trace(m_imageLoader); |
@@ -93,6 +132,14 @@ void HTMLImageElement::trace(Visitor* visitor) |
HTMLElement::trace(visitor); |
} |
+void HTMLImageElement::notifyMediaQueryChanged() |
+{ |
+ // Re-selecting the source URL in order to pick a more fitting resource |
+ // And update the image's intrinsic dimensions when the viewport changes. |
+ // Picking of a better fitting resource is UA dependant, not spec required. |
+ selectSourceURL(ImageLoader::UpdateForce); |
+} |
+ |
PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document& document, int width, int height) |
{ |
RefPtrWillBeRawPtr<HTMLImageElement> image = adoptRefWillBeNoop(new HTMLImageElement(document)); |
@@ -181,6 +228,8 @@ void HTMLImageElement::setBestFitURLAndDPRFromImageCandidate(const ImageCandidat |
float candidateDensity = candidate.density(); |
if (candidateDensity >= 0) |
m_imageDevicePixelRatio = 1.0 / candidateDensity; |
+ if (candidate.resourceWidth() > 0) |
+ m_intrinsicSizingViewportDependant = true; |
if (renderer() && renderer()->isImage()) |
toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRatio); |
} |
@@ -246,7 +295,9 @@ ImageCandidate HTMLImageElement::findBestFitImageFromPictureParent() |
if (!source->mediaQueryMatches()) |
continue; |
- unsigned effectiveSize = SizesAttributeParser::findEffectiveSize(source->fastGetAttribute(sizesAttr), MediaValuesDynamic::create(document())); |
+ SizesAttributeParser parser = SizesAttributeParser(MediaValuesDynamic::create(document()), source->fastGetAttribute(sizesAttr)); |
+ unsigned effectiveSize = parser.length(); |
+ m_effectiveSizeViewportDependant = parser.viewportDependant(); |
ImageCandidate candidate = bestFitSourceForSrcsetAttribute(document().devicePixelRatio(), effectiveSize, source->fastGetAttribute(srcsetAttr)); |
if (candidate.isEmpty()) |
continue; |
@@ -568,11 +619,18 @@ void HTMLImageElement::selectSourceURL(ImageLoader::UpdateFromElementBehavior be |
if (!foundURL) { |
unsigned effectiveSize = 0; |
- if (RuntimeEnabledFeatures::pictureSizesEnabled()) |
- effectiveSize = SizesAttributeParser::findEffectiveSize(fastGetAttribute(sizesAttr), MediaValuesDynamic::create(document())); |
+ if (RuntimeEnabledFeatures::pictureSizesEnabled()) { |
+ SizesAttributeParser parser = SizesAttributeParser(MediaValuesDynamic::create(document()), fastGetAttribute(sizesAttr)); |
+ effectiveSize = parser.length(); |
+ m_effectiveSizeViewportDependant = parser.viewportDependant(); |
+ } |
ImageCandidate candidate = bestFitSourceForImageAttributes(document().devicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr)); |
setBestFitURLAndDPRFromImageCandidate(candidate); |
} |
+ if (m_intrinsicSizingViewportDependant && m_effectiveSizeViewportDependant) { |
+ createMediaQueryListIfDoesNotExist(); |
+ document().mediaQueryMatcher().addMediaQueryList(m_mediaQueryList.get()); |
+ } |
imageLoader().updateFromElement(behavior); |
} |