| 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;
|
| +}
|
| +
|
| }
|
|
|