This source file includes following definitions.
- compareByScaleFactor
- isComma
- parseDescriptors
- parseImageCandidatesFromSrcsetAttribute
- parseImageCandidatesFromSrcsetAttribute
- pickBestImageCandidate
- bestFitSourceForSrcsetAttribute
- bestFitSourceForImageAttributes
- bestFitSourceForImageAttributes
#include "config.h"
#include "core/html/parser/HTMLSrcsetParser.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "platform/ParsingUtilities.h"
namespace WebCore {
static bool compareByScaleFactor(const ImageCandidate& first, const ImageCandidate& second)
{
return first.scaleFactor() < second.scaleFactor();
}
template<typename CharType>
inline bool isComma(CharType character)
{
return character == ',';
}
template<typename CharType>
static bool parseDescriptors(const CharType* descriptorsStart, const CharType* descriptorsEnd, float& imgScaleFactor)
{
const CharType* position = descriptorsStart;
bool isValid = false;
bool isFoundScaleFactor = false;
bool isEmptyDescriptor = !(descriptorsEnd > descriptorsStart);
while (position < descriptorsEnd) {
skipWhile<CharType, isHTMLSpace<CharType> >(position, descriptorsEnd);
const CharType* currentDescriptorStart = position;
skipWhile<CharType, isNotHTMLSpace<CharType> >(position, descriptorsEnd);
const CharType* currentDescriptorEnd = position;
++position;
ASSERT(currentDescriptorEnd > currentDescriptorStart);
--currentDescriptorEnd;
unsigned descriptorLength = currentDescriptorEnd - currentDescriptorStart;
if (*currentDescriptorEnd == 'x') {
if (isFoundScaleFactor)
return false;
imgScaleFactor = charactersToFloat(currentDescriptorStart, descriptorLength, &isValid);
isFoundScaleFactor = true;
} else {
continue;
}
}
return isEmptyDescriptor || isValid;
}
template<typename CharType>
static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, const CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandidates)
{
const CharType* position = attributeStart;
const CharType* attributeEnd = position + length;
while (position < attributeEnd) {
float imgScaleFactor = 1.0;
skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
if (position == attributeEnd)
break;
const CharType* imageURLStart = position;
if (*position == ',') {
++position;
continue;
}
skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
const CharType* imageURLEnd = position;
if (position != attributeEnd && *(position - 1) == ',') {
--imageURLEnd;
} else {
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))
continue;
}
imageCandidates.append(ImageCandidate(attribute, imageURLStart - attributeStart, imageURLEnd - imageURLStart, imgScaleFactor));
}
}
static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vector<ImageCandidate>& imageCandidates)
{
if (attribute.isNull())
return;
if (attribute.is8Bit())
parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.characters8(), attribute.length(), imageCandidates);
else
parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.characters16(), attribute.length(), imageCandidates);
}
static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector<ImageCandidate>& imageCandidates)
{
if (imageCandidates.isEmpty())
return ImageCandidate();
std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByScaleFactor);
unsigned i;
for (i = 0; i < imageCandidates.size() - 1; ++i)
if (imageCandidates[i].scaleFactor() >= deviceScaleFactor)
break;
float winningScaleFactor = imageCandidates[i].scaleFactor();
unsigned winner = i;
while ((i > 0) && (imageCandidates[--i].scaleFactor() == winningScaleFactor))
winner = i;
return imageCandidates[winner];
}
ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, const String& srcsetAttribute)
{
Vector<ImageCandidate> imageCandidates;
parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates);
return pickBestImageCandidate(deviceScaleFactor, imageCandidates);
}
ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcsetAttribute)
{
if (srcsetAttribute.isNull()) {
if (srcAttribute.isNull())
return ImageCandidate();
return ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1);
}
Vector<ImageCandidate> imageCandidates;
parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates);
if (!srcAttribute.isEmpty())
imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1.0));
return pickBestImageCandidate(deviceScaleFactor, imageCandidates);
}
String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, ImageCandidate& srcsetImageCandidate)
{
if (srcsetImageCandidate.isEmpty())
return srcAttribute;
Vector<ImageCandidate> imageCandidates;
imageCandidates.append(srcsetImageCandidate);
if (!srcAttribute.isEmpty())
imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1.0));
return pickBestImageCandidate(deviceScaleFactor, imageCandidates).toString();
}
}