Пример #1
0
void RenderStyle::setContent(PassRefPtr<StringImpl> s, bool add)
{
    if (!s)
        return; // The string is null. Nothing to do. Just bail.

    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
    ContentData* lastContent = content.get();
    while (lastContent && lastContent->next())
        lastContent = lastContent->next();

    bool reuseContent = !add;
    if (add && lastContent) {
        if (lastContent->isText()) {
            // We can augment the existing string and share this ContentData node.
            String newStr = lastContent->text();
            newStr.append(s.get());
            lastContent->setText(newStr.impl());
            return;
        }
    }

    ContentData* newContentData = 0;
    if (reuseContent && content) {
        content->clear();
        newContentData = content.release();
    } else
        newContentData = new ContentData;

    if (lastContent && !reuseContent)
        lastContent->setNext(newContentData);
    else
        content.set(newContentData);

    newContentData->setText(s);
}
bool StyleRareNonInheritedData::contentDataEquivalent(const StyleRareNonInheritedData& o) const
{
    ContentData* a = m_content.get();
    ContentData* b = o.m_content.get();

    while (a && b && *a == *b) {
        a = a->next();
        b = b->next();
    }

    return !a && !b;
}
Пример #3
0
PassOwnPtr<ContentData> ContentData::clone() const
{
    OwnPtr<ContentData> result = cloneInternal();

    ContentData* lastNewData = result.get();
    for (const ContentData* contentData = next(); contentData; contentData = contentData->next()) {
        OwnPtr<ContentData> newData = contentData->cloneInternal();
        lastNewData->setNext(newData.release());
        lastNewData = lastNewData->next();
    }

    return result.release();
}
Пример #4
0
std::unique_ptr<ContentData> ContentData::clone() const
{
    auto result = cloneInternal();
    
    ContentData* lastNewData = result.get();
    for (const ContentData* contentData = next(); contentData; contentData = contentData->next()) {
        auto newData = contentData->cloneInternal();
        lastNewData->setNext(std::move(newData));
        lastNewData = lastNewData->next();
    }
        
    return result;
}
Пример #5
0
ContentData* ContentData::clone() const {
  ContentData* result = cloneInternal();

  ContentData* lastNewData = result;
  for (const ContentData* contentData = next(); contentData;
       contentData = contentData->next()) {
    ContentData* newData = contentData->cloneInternal();
    lastNewData->setNext(newData);
    lastNewData = lastNewData->next();
  }

  return result;
}
Пример #6
0
ContentData* RenderStyle::prepareToSetContent(StringImpl* string, bool add)
{
    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
    ContentData* lastContent = content.get();
    while (lastContent && lastContent->next())
        lastContent = lastContent->next();

    if (string && add && lastContent && lastContent->isText()) {
        // Augment the existing string and share the existing ContentData node.
        String newText = lastContent->text();
        newText.append(string);
        lastContent->setText(newText.impl());
        return 0;
    }

    bool reuseContent = !add;
    OwnPtr<ContentData> newContentData;
    if (reuseContent && content) {
        content->clear();
        newContentData = content.release();
    } else
        newContentData = adoptPtr(new ContentData);

    ContentData* result = newContentData.get();

    if (lastContent && !reuseContent)
        lastContent->setNext(newContentData.release());
    else
        content = newContentData.release();

    return result;
}
Пример #7
0
void RenderStyle::setContent(CounterContent* c, bool add)
{
    if (!c)
        return;

    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
    ContentData* lastContent = content.get();
    while (lastContent && lastContent->next())
        lastContent = lastContent->next();

    bool reuseContent = !add;
    ContentData* newContentData = 0;
    if (reuseContent && content) {
        content->clear();
        newContentData = content.release();
    } else
        newContentData = new ContentData;

    if (lastContent && !reuseContent)
        lastContent->setNext(newContentData);
    else
        content.set(newContentData);

    newContentData->setCounter(c);
}
Пример #8
0
void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
{
    if (!image)
        return; // The object is null. Nothing to do. Just bail.

    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
    ContentData* lastContent = content.get();
    while (lastContent && lastContent->next())
        lastContent = lastContent->next();

    bool reuseContent = !add;
    ContentData* newContentData;
    if (reuseContent && content) {
        content->clear();
        newContentData = content.release();
    } else
        newContentData = new ContentData;

    if (lastContent && !reuseContent)
        lastContent->setNext(newContentData);
    else
        content.set(newContentData);

    newContentData->setImage(image);
}
Пример #9
0
bool ContentData::dataEquivalent(const ContentData& other) const
{
    if (type() != other.type())
        return false;

    switch (type()) {
        case CONTENT_NONE:
            return true;
            break;
        case CONTENT_TEXT:
            return equal(text(), other.text());
            break;
        case CONTENT_OBJECT:
            return StyleImage::imagesEquivalent(image(), other.image());
            break;
        case CONTENT_COUNTER:
            return *counter() == *other.counter();
            break;
    }

    ASSERT_NOT_REACHED();
    return false;
}
Пример #10
0
void StyleResourceLoader::loadPendingImages(RenderStyle* style, const ElementStyleResources& elementStyleResources)
{
    if (elementStyleResources.pendingImageProperties().isEmpty())
        return;

    PendingImagePropertyMap::const_iterator::Keys end = elementStyleResources.pendingImageProperties().end().keys();
    for (PendingImagePropertyMap::const_iterator::Keys it = elementStyleResources.pendingImageProperties().begin().keys(); it != end; ++it) {
        CSSPropertyID currentProperty = *it;

        switch (currentProperty) {
        case CSSPropertyBackgroundImage: {
            for (FillLayer* backgroundLayer = style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
                if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
                    backgroundLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(backgroundLayer->image()), elementStyleResources.deviceScaleFactor()));
            }
            break;
        }
        case CSSPropertyContent: {
            for (ContentData* contentData = const_cast<ContentData*>(style->contentData()); contentData; contentData = contentData->next()) {
                if (contentData->isImage()) {
                    StyleImage* image = static_cast<ImageContentData*>(contentData)->image();
                    if (image->isPendingImage()) {
                        RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(image), elementStyleResources.deviceScaleFactor());
                        if (loadedImage)
                            static_cast<ImageContentData*>(contentData)->setImage(loadedImage.release());
                    }
                }
            }
            break;
        }
        case CSSPropertyCursor: {
            if (CursorList* cursorList = style->cursors()) {
                for (size_t i = 0; i < cursorList->size(); ++i) {
                    CursorData& currentCursor = cursorList->at(i);
                    if (StyleImage* image = currentCursor.image()) {
                        if (image->isPendingImage())
                            currentCursor.setImage(loadPendingImage(static_cast<StylePendingImage*>(image), elementStyleResources.deviceScaleFactor()));
                    }
                }
            }
            break;
        }
        case CSSPropertyListStyleImage: {
            if (style->listStyleImage() && style->listStyleImage()->isPendingImage())
                style->setListStyleImage(loadPendingImage(static_cast<StylePendingImage*>(style->listStyleImage()), elementStyleResources.deviceScaleFactor()));
            break;
        }
        case CSSPropertyBorderImageSource: {
            if (style->borderImageSource() && style->borderImageSource()->isPendingImage())
                style->setBorderImageSource(loadPendingImage(static_cast<StylePendingImage*>(style->borderImageSource()), elementStyleResources.deviceScaleFactor()));
            break;
        }
        case CSSPropertyWebkitBoxReflect: {
            if (StyleReflection* reflection = style->boxReflect()) {
                const NinePieceImage& maskImage = reflection->mask();
                if (maskImage.image() && maskImage.image()->isPendingImage()) {
                    RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(maskImage.image()), elementStyleResources.deviceScaleFactor());
                    reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
                }
            }
            break;
        }
        case CSSPropertyWebkitMaskBoxImageSource: {
            if (style->maskBoxImageSource() && style->maskBoxImageSource()->isPendingImage())
                style->setMaskBoxImageSource(loadPendingImage(static_cast<StylePendingImage*>(style->maskBoxImageSource()), elementStyleResources.deviceScaleFactor()));
            break;
        }
        case CSSPropertyWebkitMaskImage: {
            for (FillLayer* maskLayer = style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
                if (maskLayer->image() && maskLayer->image()->isPendingImage())
                    maskLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(maskLayer->image()), elementStyleResources.deviceScaleFactor()));
            }
            break;
        }
        case CSSPropertyWebkitShapeInside:
            loadPendingShapeImage(style, style->shapeInside());
            break;
        case CSSPropertyWebkitShapeOutside:
            loadPendingShapeImage(style, style->shapeOutside());
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    }
}
void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type, RenderObject* child)
{
    // In CSS2, before/after pseudo-content cannot nest.  Check this first.
    if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
        return;
    
    RenderStyle* pseudo = getPseudoStyle(type);

    // Whether or not we currently have generated content attached.
    bool oldContentPresent = child && (child->style()->styleType() == type);

    // Whether or not we now want generated content.  
    bool newContentWanted = pseudo && pseudo->display() != NONE;

    // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
    // :after content and not :before content.
    if (type == RenderStyle::BEFORE && isInlineContinuation())
        newContentWanted = false;

    // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
    // then we don't generate the :after content.
    if (type == RenderStyle::AFTER && isRenderInline() && continuation())
        newContentWanted = false;
    
    // If we don't want generated content any longer, or if we have generated content, but it's no longer
    // identical to the new content data we want to build render objects for, then we nuke all
    // of the old generated content.
    if (!newContentWanted ||
        (oldContentPresent && !child->style()->contentDataEquivalent(pseudo))) {
        // Nuke the child. 
        if (child && child->style()->styleType() == type) {
            oldContentPresent = false;
            removeChild(child);
            child = (type == RenderStyle::BEFORE) ? firstChild() : lastChild();
        }
    }

    // If we have no pseudo-style or if the pseudo's display type is NONE, then we
    // have no generated content and can now return.
    if (!newContentWanted)
        return;

    if (isInlineFlow() && pseudo->display() != INLINE)
        // According to the CSS2 spec (the end of section 12.1), the only allowed
        // display values for the pseudo style are NONE and INLINE.  Since we already
        // determined that the pseudo is not display NONE, any display other than
        // inline should be mutated to INLINE.
        pseudo->setDisplay(INLINE);
    
    if (oldContentPresent) {
        if (child && child->style()->styleType() == type) {
            // We have generated content present still.  We want to walk this content and update our
            // style information with the new pseudo style.
            child->setStyle(pseudo);

            // Note that if we ever support additional types of generated content (which should be way off
            // in the future), this code will need to be patched.
            for (RenderObject* genChild = child->firstChild(); genChild; genChild = genChild->nextSibling()) {
                if (genChild->isText())
                    // Generated text content is a child whose style also needs to be set to the pseudo
                    // style.
                    genChild->setStyle(pseudo);
                else {
                    // Images get an empty style that inherits from the pseudo.
                    RenderStyle* style = new (renderArena()) RenderStyle();
                    style->inheritFrom(pseudo);
                    genChild->setStyle(style);
                }
            }
        }
        return; // We've updated the generated content. That's all we needed to do.
    }
    
    RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? child : 0;

    // Generated content consists of a single container that houses multiple children (specified
    // by the content property).  This pseudo container gets the pseudo style set on it.
    RenderObject* pseudoContainer = 0;
    
    // Now walk our list of generated content and create render objects for every type
    // we encounter.
    for (ContentData* contentData = pseudo->contentData();
         contentData; contentData = contentData->_nextContent) {
        if (!pseudoContainer)
            pseudoContainer = RenderFlow::createAnonymousFlow(document(), pseudo); /* anonymous box */
        
        if (contentData->contentType() == CONTENT_TEXT)
        {
            RenderText* t = new (renderArena()) RenderTextFragment(document() /*anonymous object */, contentData->contentText());
            t->setStyle(pseudo);
            pseudoContainer->addChild(t);
        }
        else if (contentData->contentType() == CONTENT_OBJECT)
        {
            RenderImage* img = new (renderArena()) RenderImage(document()); /* Anonymous object */
            RenderStyle* style = new (renderArena()) RenderStyle();
            style->inheritFrom(pseudo);
            img->setStyle(style);
            img->setContentObject(contentData->contentObject());
            pseudoContainer->addChild(img);
        }
    }

    if (pseudoContainer) {
        // Add the pseudo after we've installed all our content, so that addChild will be able to find the text
        // inside the inline for e.g., first-letter styling.
        addChild(pseudoContainer, insertBefore);
    }
}
Пример #12
0
static void loadPendingImages(const PendingResources& pendingResources, Document& document, RenderStyle& style, const Element* element)
{
    for (auto currentProperty : pendingResources.pendingImages.keys()) {
        switch (currentProperty) {
        case CSSPropertyBackgroundImage: {
            for (FillLayer* backgroundLayer = &style.ensureBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
                auto* styleImage = backgroundLayer->image();
                if (is<StylePendingImage>(styleImage))
                    backgroundLayer->setImage(loadPendingImage(document, *styleImage, element));
            }
            break;
        }
        case CSSPropertyContent: {
            for (ContentData* contentData = const_cast<ContentData*>(style.contentData()); contentData; contentData = contentData->next()) {
                if (is<ImageContentData>(*contentData)) {
                    auto& styleImage = downcast<ImageContentData>(*contentData).image();
                    if (is<StylePendingImage>(styleImage)) {
                        if (auto loadedImage = loadPendingImage(document, styleImage, element))
                            downcast<ImageContentData>(*contentData).setImage(WTFMove(loadedImage));
                    }
                }
            }
            break;
        }
        case CSSPropertyCursor: {
            if (CursorList* cursorList = style.cursors()) {
                for (size_t i = 0; i < cursorList->size(); ++i) {
                    CursorData& currentCursor = cursorList->at(i);
                    auto* styleImage = currentCursor.image();
                    if (is<StylePendingImage>(styleImage))
                        currentCursor.setImage(loadPendingImage(document, *styleImage, element));
                }
            }
            break;
        }
        case CSSPropertyListStyleImage: {
            auto* styleImage = style.listStyleImage();
            if (is<StylePendingImage>(styleImage))
                style.setListStyleImage(loadPendingImage(document, *styleImage, element));
            break;
        }
        case CSSPropertyBorderImageSource: {
            auto* styleImage = style.borderImageSource();
            if (is<StylePendingImage>(styleImage))
                style.setBorderImageSource(loadPendingImage(document, *styleImage, element));
            break;
        }
        case CSSPropertyWebkitBoxReflect: {
            if (StyleReflection* reflection = style.boxReflect()) {
                const NinePieceImage& maskImage = reflection->mask();
                auto* styleImage = maskImage.image();
                if (is<StylePendingImage>(styleImage)) {
                    auto loadedImage = loadPendingImage(document, *styleImage, element);
                    reflection->setMask(NinePieceImage(WTFMove(loadedImage), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
                }
            }
            break;
        }
        case CSSPropertyWebkitMaskBoxImageSource: {
            auto* styleImage = style.maskBoxImageSource();
            if (is<StylePendingImage>(styleImage))
                style.setMaskBoxImageSource(loadPendingImage(document, *styleImage, element));
            break;
        }
        case CSSPropertyWebkitMaskImage: {
            for (FillLayer* maskLayer = &style.ensureMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
                auto* styleImage = maskLayer->image();
                if (is<StylePendingImage>(styleImage))
                    maskLayer->setImage(loadPendingImage(document, *styleImage, element));
            }
            break;
        }
#if ENABLE(CSS_SHAPES)
        case CSSPropertyWebkitShapeOutside: {
            if (!style.shapeOutside())
                return;

            StyleImage* image = style.shapeOutside()->image();
            if (is<StylePendingImage>(image))
                style.shapeOutside()->setImage(loadPendingImage(document, *image, element, LoadPolicy::ShapeOutside));

            break;
        }
#endif
        default:
            ASSERT_NOT_REACHED();
        }
    }
}
void ElementStyleResources::loadPendingImages(ComputedStyle* style)
{
    // We must loop over the properties and then look at the style to see if
    // a pending image exists, and only load that image. For example:
    //
    // <style>
    //    div { background-image: url(a.png); }
    //    div { background-image: url(b.png); }
    //    div { background-image: none; }
    // </style>
    // <div></div>
    //
    // We call styleImage() for both a.png and b.png adding the
    // CSSPropertyBackgroundImage property to the m_pendingImageProperties set,
    // then we null out the background image because of the "none".
    //
    // If we eagerly loaded the images we'd fetch a.png, even though it's not
    // used. If we didn't null check below we'd crash since the none actually
    // removed all background images.

    for (CSSPropertyID property : m_pendingImageProperties) {
        switch (property) {
        case CSSPropertyBackgroundImage: {
            for (FillLayer* backgroundLayer = &style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
                if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
                    backgroundLayer->setImage(loadPendingImage(toStylePendingImage(backgroundLayer->image())));
            }
            break;
        }
        case CSSPropertyContent: {
            for (ContentData* contentData = const_cast<ContentData*>(style->contentData()); contentData; contentData = contentData->next()) {
                if (contentData->isImage()) {
                    StyleImage* image = toImageContentData(contentData)->image();
                    if (image->isPendingImage())
                        toImageContentData(contentData)->setImage(loadPendingImage(toStylePendingImage(image)));
                }
            }
            break;
        }
        case CSSPropertyCursor: {
            if (CursorList* cursorList = style->cursors()) {
                for (size_t i = 0; i < cursorList->size(); ++i) {
                    CursorData& currentCursor = cursorList->at(i);
                    if (StyleImage* image = currentCursor.image()) {
                        if (image->isPendingImage())
                            currentCursor.setImage(loadPendingImage(toStylePendingImage(image)));
                    }
                }
            }
            break;
        }
        case CSSPropertyListStyleImage: {
            if (style->listStyleImage() && style->listStyleImage()->isPendingImage())
                style->setListStyleImage(loadPendingImage(toStylePendingImage(style->listStyleImage())));
            break;
        }
        case CSSPropertyBorderImageSource: {
            if (style->borderImageSource() && style->borderImageSource()->isPendingImage())
                style->setBorderImageSource(loadPendingImage(toStylePendingImage(style->borderImageSource())));
            break;
        }
        case CSSPropertyWebkitBoxReflect: {
            if (StyleReflection* reflection = style->boxReflect()) {
                const NinePieceImage& maskImage = reflection->mask();
                if (maskImage.image() && maskImage.image()->isPendingImage()) {
                    RefPtrWillBeRawPtr<StyleImage> loadedImage = loadPendingImage(toStylePendingImage(maskImage.image()));
                    reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
                }
            }
            break;
        }
        case CSSPropertyWebkitMaskBoxImageSource: {
            if (style->maskBoxImageSource() && style->maskBoxImageSource()->isPendingImage())
                style->setMaskBoxImageSource(loadPendingImage(toStylePendingImage(style->maskBoxImageSource())));
            break;
        }
        case CSSPropertyWebkitMaskImage: {
            for (FillLayer* maskLayer = &style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
                if (maskLayer->image() && maskLayer->image()->isPendingImage())
                    maskLayer->setImage(loadPendingImage(toStylePendingImage(maskLayer->image())));
            }
            break;
        }
        case CSSPropertyShapeOutside:
            if (style->shapeOutside() && style->shapeOutside()->image() && style->shapeOutside()->image()->isPendingImage())
                style->shapeOutside()->setImage(loadPendingImage(toStylePendingImage(style->shapeOutside()->image()), CrossOriginAttributeAnonymous));
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    }
}