Chromium Code Reviews| 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); |
| } |