Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1056)

Unified Diff: Source/core/html/HTMLImageElement.cpp

Issue 369423002: Have srcset respond to viewport changes (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: more oilpan Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/html/HTMLImageElement.h ('k') | Source/core/html/parser/HTMLPreloadScanner.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/html/HTMLImageElement.cpp
diff --git a/Source/core/html/HTMLImageElement.cpp b/Source/core/html/HTMLImageElement.cpp
index ceeb1ede0923b0b2912ddc8e3cd7f60df49ccb64..96c18ae7921a80ebb1cb716318768c4a626d8550 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,18 +107,41 @@ PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::create(Document& docu
HTMLImageElement::~HTMLImageElement()
{
#if !ENABLE(OILPAN)
+ if (m_listener)
+ m_listener->clearElement();
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);
visitor->trace(m_form);
+ visitor->trace(m_listener);
+ visitor->trace(m_mediaQueryList);
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 +230,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 +297,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 +621,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);
}
« no previous file with comments | « Source/core/html/HTMLImageElement.h ('k') | Source/core/html/parser/HTMLPreloadScanner.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698