Index: Source/core/html/parser/HTMLParserIdioms.cpp |
diff --git a/Source/core/html/parser/HTMLParserIdioms.cpp b/Source/core/html/parser/HTMLParserIdioms.cpp |
index 6f136305f07ee01108d46d0b8da093bcfc11b83c..8902789e4e188aea1c271a253ee3b392e6c2a323 100644 |
--- a/Source/core/html/parser/HTMLParserIdioms.cpp |
+++ b/Source/core/html/parser/HTMLParserIdioms.cpp |
@@ -29,6 +29,7 @@ |
#include "core/dom/QualifiedName.h" |
#include "core/html/parser/HTMLIdentifier.h" |
#include "core/platform/Decimal.h" |
+#include "core/platform/text/DecodeEscapeSequences.h" |
#include "wtf/MathExtras.h" |
#include "wtf/text/AtomicString.h" |
#include "wtf/text/StringBuilder.h" |
@@ -296,4 +297,74 @@ bool threadSafeMatch(const HTMLIdentifier& localName, const QualifiedName& qName |
return threadSafeEqual(localName.asStringImpl(), qName.localName().impl()); |
} |
+struct ImageWithScale { |
+ String imageURL; |
+ float scaleFactor; |
+ bool operator==(const ImageWithScale& image) const |
+ { |
+ return scaleFactor == image.scaleFactor && imageURL == image.imageURL; |
+ } |
+}; |
+typedef Vector<ImageWithScale> ImageCandidates; |
+ |
+static inline bool compareByScaleFactor(const ImageWithScale& first, const ImageWithScale& second) |
+{ |
+ return first.scaleFactor < second.scaleFactor; |
+} |
+ |
+String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcSetAttribute) |
+{ |
+ ImageCandidates imageCandidates; |
+ |
+ const String srcSetAttributeValue = srcSetAttribute.simplifyWhiteSpace(isHTMLSpace); |
+ Vector<String> srcSetTokens; |
+ |
+ srcSetAttributeValue.split(',', srcSetTokens); |
+ for (size_t i = 0; i < srcSetTokens.size(); ++i) { |
+ Vector<String> data; |
+ float imgScaleFactor = 1.0; |
+ bool validScaleFactor = false; |
+ |
+ srcSetTokens[i].stripWhiteSpace().split(' ', data); |
+ // There must be at least one candidate descriptor, and the last one must |
+ // be a scale factor. Since we don't support descriptors other than scale, |
+ // it's better to discard any rule with such descriptors rather than accept |
+ // only the scale data. |
+ if (data.size() != 2) |
+ continue; |
+ if (!data.last().endsWith('x')) |
+ continue; |
+ |
+ imgScaleFactor = data.last().substring(0, data.last().length() - 1).toFloat(&validScaleFactor); |
+ if (!validScaleFactor) |
+ continue; |
+ |
+ ImageWithScale image; |
+ image.imageURL = decodeEscapeSequences<URLEscapeSequence>(data[0], UTF8Encoding()); |
+ image.scaleFactor = imgScaleFactor; |
+ |
+ imageCandidates.append(image); |
+ } |
+ |
+ const String src = srcAttribute.simplifyWhiteSpace(isHTMLSpace); |
+ if (!src.isEmpty()) { |
+ ImageWithScale image; |
+ image.imageURL = decodeEscapeSequences<URLEscapeSequence>(src, UTF8Encoding()); |
+ image.scaleFactor = 1.0; |
+ |
+ imageCandidates.append(image); |
+ } |
+ |
+ if (imageCandidates.isEmpty()) |
+ return String(); |
+ |
+ std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByScaleFactor); |
+ |
+ for (size_t i = 0; i < imageCandidates.size() - 1; ++i) { |
+ if (imageCandidates[i].scaleFactor >= deviceScaleFactor) |
+ return imageCandidates[i].imageURL; |
+ } |
+ return imageCandidates.last().imageURL; |
+} |
+ |
} |