Index: Source/core/html/parser/HTMLSrcsetParser.cpp |
diff --git a/Source/core/html/parser/HTMLSrcsetParser.cpp b/Source/core/html/parser/HTMLSrcsetParser.cpp |
index 1002d8aeee668b208353f524f47ac4ce377ae194..f2528664969c9cce06b7d775015038d06fafa1c5 100644 |
--- a/Source/core/html/parser/HTMLSrcsetParser.cpp |
+++ b/Source/core/html/parser/HTMLSrcsetParser.cpp |
@@ -31,6 +31,7 @@ |
#include "config.h" |
#include "core/html/parser/HTMLSrcsetParser.h" |
+#include "RuntimeEnabledFeatures.h" |
#include "core/html/parser/HTMLParserIdioms.h" |
#include "platform/ParsingUtilities.h" |
@@ -48,11 +49,10 @@ inline bool isComma(CharType character) |
} |
template<typename CharType> |
-static bool parseDescriptors(const CharType* descriptorsStart, const CharType* descriptorsEnd, float& imgScaleFactor) |
+static bool parseDescriptors(const CharType* descriptorsStart, const CharType* descriptorsEnd, DescriptorParsingResult& result) |
{ |
const CharType* position = descriptorsStart; |
bool isValid = false; |
- bool isFoundScaleFactor = false; |
bool isEmptyDescriptor = !(descriptorsEnd > descriptorsStart); |
while (position < descriptorsEnd) { |
// 13.1. Let descriptor list be the result of splitting unparsed descriptors on spaces. |
@@ -66,15 +66,22 @@ static bool parseDescriptors(const CharType* descriptorsStart, const CharType* d |
--currentDescriptorEnd; |
unsigned descriptorLength = currentDescriptorEnd - currentDescriptorStart; |
if (*currentDescriptorEnd == 'x') { |
- if (isFoundScaleFactor) |
+ if (result.foundDescriptor()) |
+ return false; |
+ result.scaleFactor = charactersToFloat(currentDescriptorStart, descriptorLength, &isValid); |
+ if (!isValid || result.scaleFactor < 0) |
+ return false; |
+ } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && *currentDescriptorEnd == 'w') { |
+ if (result.foundDescriptor()) |
+ return false; |
+ result.resourceWidth = charactersToInt(currentDescriptorStart, descriptorLength, &isValid); |
+ if (!isValid || result.resourceWidth < 0) |
return false; |
- imgScaleFactor = charactersToFloat(currentDescriptorStart, descriptorLength, &isValid); |
- isFoundScaleFactor = true; |
- } else { |
- continue; |
} |
} |
- return isEmptyDescriptor || isValid; |
+ if (isEmptyDescriptor) |
+ result.scaleFactor = 1.0; |
+ return result.foundDescriptor(); |
} |
// http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#processing-the-image-candidates |
@@ -85,8 +92,7 @@ static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con |
const CharType* attributeEnd = position + length; |
while (position < attributeEnd) { |
- float imgScaleFactor = 1.0; |
- |
+ DescriptorParsingResult result; |
// 4. Splitting loop: Skip whitespace. |
skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); |
if (position == attributeEnd) |
@@ -105,17 +111,18 @@ static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con |
if (position != attributeEnd && *(position - 1) == ',') { |
--imageURLEnd; |
+ result.scaleFactor = 1.0; |
} else { |
// 7. Collect a sequence of characters that are not "," (U+002C) characters, and let that be descriptors. |
skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); |
const CharType* descriptorsStart = position; |
skipUntil<CharType, isComma<CharType> >(position, attributeEnd); |
const CharType* descriptorsEnd = position; |
- if (!parseDescriptors(descriptorsStart, descriptorsEnd, imgScaleFactor)) |
+ if (!parseDescriptors(descriptorsStart, descriptorsEnd, result)) |
continue; |
} |
- imageCandidates.append(ImageCandidate(attribute, imageURLStart - attributeStart, imageURLEnd - imageURLStart, imgScaleFactor)); |
+ imageCandidates.append(ImageCandidate(attribute, imageURLStart - attributeStart, imageURLEnd - imageURLStart, result)); |
// 11. Return to the step labeled splitting loop. |
} |
} |
@@ -131,17 +138,24 @@ static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec |
parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.characters16(), attribute.length(), imageCandidates); |
} |
-static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector<ImageCandidate>& imageCandidates) |
+static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, int effectiveSize, Vector<ImageCandidate>& imageCandidates) |
{ |
if (imageCandidates.isEmpty()) |
return ImageCandidate(); |
+ // http://picture.responsiveimages.org/#normalize-source-densities |
+ for (Vector<ImageCandidate>::iterator it = imageCandidates.begin(); it != imageCandidates.end(); ++it) { |
+ if (it->scaleFactor() < 0) |
+ it->setScaleFactor((float)it->resourceWidth() / (float)effectiveSize); |
+ } |
+ |
std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByScaleFactor); |
unsigned i; |
- for (i = 0; i < imageCandidates.size() - 1; ++i) |
+ for (i = 0; i < imageCandidates.size() - 1; ++i) { |
if (imageCandidates[i].scaleFactor() >= deviceScaleFactor) |
break; |
+ } |
float winningScaleFactor = imageCandidates[i].scaleFactor(); |
unsigned winner = i; |
@@ -153,21 +167,24 @@ static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector<Ima |
return imageCandidates[winner]; |
} |
-ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, const String& srcsetAttribute) |
+ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, int effectiveSize, const String& srcsetAttribute) |
{ |
Vector<ImageCandidate> imageCandidates; |
parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); |
- return pickBestImageCandidate(deviceScaleFactor, imageCandidates); |
+ return pickBestImageCandidate(deviceScaleFactor, effectiveSize, imageCandidates); |
} |
-ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcsetAttribute) |
+ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, int effectiveSize, const String& srcAttribute, const String& srcsetAttribute) |
{ |
+ DescriptorParsingResult defaultResult; |
+ defaultResult.scaleFactor = 1.0; |
+ |
if (srcsetAttribute.isNull()) { |
if (srcAttribute.isNull()) |
return ImageCandidate(); |
- return ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1); |
+ return ImageCandidate(srcAttribute, 0, srcAttribute.length(), defaultResult); |
} |
Vector<ImageCandidate> imageCandidates; |
@@ -175,13 +192,16 @@ ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const St |
parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); |
if (!srcAttribute.isEmpty()) |
- imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1.0)); |
+ imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), defaultResult)); |
- return pickBestImageCandidate(deviceScaleFactor, imageCandidates); |
+ return pickBestImageCandidate(deviceScaleFactor, effectiveSize, imageCandidates); |
} |
-String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, ImageCandidate& srcsetImageCandidate) |
+String bestFitSourceForImageAttributes(float deviceScaleFactor, int effectiveSize, const String& srcAttribute, ImageCandidate& srcsetImageCandidate) |
{ |
+ DescriptorParsingResult defaultResult; |
+ defaultResult.scaleFactor = 1.0; |
+ |
if (srcsetImageCandidate.isEmpty()) |
return srcAttribute; |
@@ -189,9 +209,9 @@ String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& sr |
imageCandidates.append(srcsetImageCandidate); |
if (!srcAttribute.isEmpty()) |
- imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1.0)); |
+ imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), defaultResult)); |
- return pickBestImageCandidate(deviceScaleFactor, imageCandidates).toString(); |
+ return pickBestImageCandidate(deviceScaleFactor, effectiveSize, imageCandidates).toString(); |
} |
} |