Esempio n. 1
0
ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const AtomicString& srcAttribute, const AtomicString& srcsetAttribute
#if ENABLE(PICTURE_SIZES)
    , unsigned sourceSize
#endif
    )
{
    if (srcsetAttribute.isNull()) {
        if (srcAttribute.isNull())
            return ImageCandidate();
        return ImageCandidate(StringView(srcAttribute), DescriptorParsingResult(), ImageCandidate::SrcOrigin);
    }

    Vector<ImageCandidate> imageCandidates;

    parseImageCandidatesFromSrcsetAttribute(StringView(srcsetAttribute), imageCandidates);

    if (!srcAttribute.isEmpty())
        imageCandidates.append(ImageCandidate(StringView(srcAttribute), DescriptorParsingResult(), ImageCandidate::SrcOrigin));

    return pickBestImageCandidate(deviceScaleFactor, imageCandidates
#if ENABLE(PICTURE_SIZES)
        , sourceSize
#endif
        );
}
Esempio n. 2
0
ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, unsigned sourceSize, const String& srcAttribute, const String& srcsetAttribute)
{
    if (srcsetAttribute.isNull()) {
        if (srcAttribute.isNull())
            return ImageCandidate();
        return ImageCandidate(srcAttribute, 0, srcAttribute.length(), DescriptorParsingResult(), ImageCandidate::SrcOrigin);
    }

    Vector<ImageCandidate> imageCandidates;

    parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates);

    if (!srcAttribute.isEmpty())
        imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), DescriptorParsingResult(), ImageCandidate::SrcOrigin));

    return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates);
}
static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, const CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandidates, Document* document)
{
    const CharType* position = attributeStart;
    const CharType* attributeEnd = position + length;

    while (position < attributeEnd) {
        // 4. Splitting loop: Collect a sequence of characters that are space characters or U+002C COMMA characters.
        skipWhile<CharType, isHTMLSpaceOrComma<CharType>>(position, attributeEnd);
        if (position == attributeEnd) {
            // Contrary to spec language - descriptor parsing happens on each candidate, so when we reach the attributeEnd, we can exit.
            break;
        }
        const CharType* imageURLStart = position;

        // 6. Collect a sequence of characters that are not space characters, and let that be url.
        skipUntil<CharType, isHTMLSpace<CharType>>(position, attributeEnd);
        const CharType* imageURLEnd = position;

        DescriptorParsingResult result;

        // 8. If url ends with a U+002C COMMA character (,)
        if (isComma(*(position - 1))) {
            // Remove all trailing U+002C COMMA characters from url.
            imageURLEnd = position - 1;
            reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart);
            ++imageURLEnd;
            // If url is empty, then jump to the step labeled splitting loop.
            if (imageURLStart == imageURLEnd)
                continue;
        } else {
            skipWhile<CharType, isHTMLSpace<CharType>>(position, attributeEnd);
            Vector<DescriptorToken> descriptorTokens;
            tokenizeDescriptors(attributeStart, position, attributeEnd, descriptorTokens);
            // Contrary to spec language - descriptor parsing happens on each candidate.
            // This is a black-box equivalent, to avoid storing descriptor lists for each candidate.
            if (!parseDescriptors(attribute, descriptorTokens, result, document)) {
                if (document) {
                    UseCounter::count(document, UseCounter::SrcsetDroppedCandidate);
                    if (document->frame())
                        document->frame()->console().addMessage(ConsoleMessage::create(OtherMessageSource, ErrorMessageLevel, String("Dropped srcset candidate ") + String(imageURLStart, imageURLEnd - imageURLStart)));
                }
                continue;
            }
        }

        ASSERT(imageURLEnd > attributeStart);
        unsigned imageURLStartingPosition = imageURLStart - attributeStart;
        ASSERT(imageURLEnd > imageURLStart);
        unsigned imageURLLength = imageURLEnd - imageURLStart;
        imageCandidates.append(ImageCandidate(attribute, imageURLStartingPosition, imageURLLength, result, ImageCandidate::SrcsetOrigin));
        // 11. Return to the step labeled splitting loop.
    }
}
String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize, 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(), DescriptorParsingResult(), ImageCandidate::SrcOrigin));

    return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates).toString();
}
static Vector<ImageCandidate> parseImageCandidatesFromSrcsetAttribute(const CharType* attributeStart, unsigned length)
{
    Vector<ImageCandidate> imageCandidates;

    const CharType* attributeEnd = attributeStart + length;

    for (const CharType* position = attributeStart; position < attributeEnd;) {
        // 4. Splitting loop: Collect a sequence of characters that are space characters or U+002C COMMA characters.
        skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEnd);
        if (position == attributeEnd) {
            // Contrary to spec language - descriptor parsing happens on each candidate, so when we reach the attributeEnd, we can exit.
            break;
        }
        const CharType* imageURLStart = position;
        // 6. Collect a sequence of characters that are not space characters, and let that be url.

        skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
        const CharType* imageURLEnd = position;

        DescriptorParsingResult result;

        // 8. If url ends with a U+002C COMMA character (,)
        if (isComma(*(position - 1))) {
            // Remove all trailing U+002C COMMA characters from url.
            imageURLEnd = position - 1;
            reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart);
            ++imageURLEnd;
            // If url is empty, then jump to the step labeled splitting loop.
            if (imageURLStart == imageURLEnd)
                continue;
        } else {
            // Advancing position here (contrary to spec) to avoid an useless extra state machine step.
            // Filed a spec bug: https://github.com/ResponsiveImagesCG/picture-element/issues/189
            ++position;
            Vector<StringView> descriptorTokens;
            tokenizeDescriptors(position, attributeEnd, descriptorTokens);
            // Contrary to spec language - descriptor parsing happens on each candidate.
            // This is a black-box equivalent, to avoid storing descriptor lists for each candidate.
            if (!parseDescriptors(descriptorTokens, result))
                continue;
        }

        ASSERT(imageURLEnd > imageURLStart);
        unsigned imageURLLength = imageURLEnd - imageURLStart;
        imageCandidates.append(ImageCandidate(StringView(imageURLStart, imageURLLength), result, ImageCandidate::SrcsetOrigin));
        // 11. Return to the step labeled splitting loop.
    }
    return imageCandidates;
}
Esempio n. 6
0
static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector<ImageCandidate>& imageCandidates
#if ENABLE(PICTURE_SIZES)
    , unsigned sourceSize
#endif
    )
{
    bool ignoreSrc = false;
    if (imageCandidates.isEmpty())
        return ImageCandidate();

    // http://picture.responsiveimages.org/#normalize-source-densities
    for (auto& candidate : imageCandidates) {
#if ENABLE(PICTURE_SIZES)
        if (candidate.resourceWidth > 0) {
            candidate.density = static_cast<float>(candidate.resourceWidth) / static_cast<float>(sourceSize);
            ignoreSrc = true;
        } else
#endif
        if (candidate.density < 0)
            candidate.density = DefaultDensityValue;
    }

    std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByDensity);

    unsigned i;
    for (i = 0; i < imageCandidates.size() - 1; ++i) {
        if ((imageCandidates[i].density >= deviceScaleFactor) && (!ignoreSrc || !imageCandidates[i].srcOrigin()))
            break;
    }

    if (imageCandidates[i].srcOrigin() && ignoreSrc) {
        ASSERT(i > 0);
        --i;
    }
    float winningDensity = imageCandidates[i].density;

    unsigned winner = i;
    // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates,
    // then remove entry b
    while ((i > 0) && (imageCandidates[--i].density == winningDensity))
        winner = i;

    return imageCandidates[winner];
}
Esempio n. 7
0
static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, unsigned sourceSize, Vector<ImageCandidate>& imageCandidates)
{
    const float defaultDensityValue = 1.0;
    bool ignoreSrc = false;
    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->resourceWidth() > 0) {
            it->setDensity((float)it->resourceWidth() / (float)sourceSize);
            ignoreSrc = true;
        } else if (it->density() < 0) {
            it->setDensity(defaultDensityValue);
        }
    }

    std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByDensity);

    unsigned i;
    for (i = 0; i < imageCandidates.size() - 1; ++i) {
        if ((imageCandidates[i].density() >= deviceScaleFactor) && (!ignoreSrc || !imageCandidates[i].srcOrigin()))
            break;
    }

    if (imageCandidates[i].srcOrigin() && ignoreSrc) {
        ASSERT(i > 0);
        --i;
    }
    float winningDensity = imageCandidates[i].density();

    unsigned winner = i;
    // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates,
    // then remove entry b
    while ((i > 0) && (imageCandidates[--i].density() == winningDensity))
        winner = i;

    return imageCandidates[winner];
}
static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sourceSize, Vector<ImageCandidate>& imageCandidates, Document* document = nullptr)
{
    const float defaultDensityValue = 1.0;
    bool ignoreSrc = false;
    if (imageCandidates.isEmpty())
        return ImageCandidate();

    // http://picture.responsiveimages.org/#normalize-source-densities
    for (ImageCandidate& image : imageCandidates) {
        if (image.resourceWidth() > 0) {
            image.setDensity((float)image.resourceWidth() / sourceSize);
            ignoreSrc = true;
        } else if (image.density() < 0) {
            image.setDensity(defaultDensityValue);
        }
    }

    std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByDensity);

    Vector<ImageCandidate*> deDupedImageCandidates;
    float prevDensity = -1.0;
    for (ImageCandidate& image : imageCandidates) {
        if (image.density() != prevDensity && (!ignoreSrc || !image.srcOrigin()))
            deDupedImageCandidates.append(&image);
        prevDensity = image.density();
    }
    unsigned winner = selectionLogic(deDupedImageCandidates, deviceScaleFactor);
    ASSERT(winner < deDupedImageCandidates.size());
    winner = avoidDownloadIfHigherDensityResourceIsInCache(deDupedImageCandidates, winner, document);

    float winningDensity = deDupedImageCandidates[winner]->density();
    // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates,
    // then remove entry b
    while ((winner > 0) && (deDupedImageCandidates[winner - 1]->density() == winningDensity))
        --winner;

    return *deDupedImageCandidates[winner];
}