Ejemplo n.º 1
0
void StyledElement::attributeChanged(Attribute* attr, bool preserveDecls)
{
    if (!attr->isMappedAttribute()) {
        Element::attributeChanged(attr, preserveDecls);
        return;
    }
 
    MappedAttribute* mappedAttr = toMappedAttribute(attr);
    if (mappedAttr->decl() && !preserveDecls) {
        mappedAttr->setDecl(0);
        setNeedsStyleRecalc();
        if (namedAttrMap)
            mappedAttributes()->declRemoved();
    }

    bool checkDecl = true;
    MappedAttributeEntry entry;
    bool needToParse = mapToEntry(attr->name(), entry);
    if (preserveDecls) {
        if (mappedAttr->decl()) {
            setNeedsStyleRecalc();
            if (namedAttrMap)
                mappedAttributes()->declAdded();
            checkDecl = false;
        }
    }
    else if (!attr->isNull() && entry != eNone) {
        CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(entry, attr);
        if (decl) {
            mappedAttr->setDecl(decl);
            setNeedsStyleRecalc();
            if (namedAttrMap)
                mappedAttributes()->declAdded();
            checkDecl = false;
        } else
            needToParse = true;
    }

    // parseMappedAttribute() might create a CSSMappedAttributeDeclaration on the attribute.  
    // Normally we would be concerned about reseting the parent of those declarations in StyledElement::didMoveToNewOwnerDocument().
    // But currently we always clear its parent and node below when adding it to the decl table.  
    // If that changes for some reason moving between documents will be buggy.
    // webarchive/adopt-attribute-styled-node-webarchive.html should catch any resulting crashes.
    if (needToParse)
        parseMappedAttribute(mappedAttr);

    if (entry == eNone)
        recalcStyleIfNeededAfterAttributeChanged(attr);

    if (checkDecl && mappedAttr->decl()) {
        // Add the decl to the table in the appropriate spot.
        setMappedAttributeDecl(entry, attr, mappedAttr->decl());
        mappedAttr->decl()->setMappedState(entry, attr->name(), attr->value());
        mappedAttr->decl()->setParent(0);
        mappedAttr->decl()->setNode(0);
        if (namedAttrMap)
            mappedAttributes()->declAdded();
    }
    updateAfterAttributeChanged(attr);
}
Ejemplo n.º 2
0
void StyledElement::attributeChanged(Attribute* attr, bool preserveDecls)
{
    MappedAttribute* mappedAttr = static_cast<MappedAttribute*>(attr);
    if (mappedAttr->decl() && !preserveDecls) {
        mappedAttr->setDecl(0);
        setChanged();
        if (namedAttrMap)
            mappedAttributes()->declRemoved();
    }

    bool checkDecl = true;
    MappedAttributeEntry entry;
    bool needToParse = mapToEntry(attr->name(), entry);
    if (preserveDecls) {
        if (mappedAttr->decl()) {
            setChanged();
            if (namedAttrMap)
                mappedAttributes()->declAdded();
            checkDecl = false;
        }
    }
    else if (!attr->isNull() && entry != eNone) {
        CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(entry, attr);
        if (decl) {
            mappedAttr->setDecl(decl);
            setChanged();
            if (namedAttrMap)
                mappedAttributes()->declAdded();
            checkDecl = false;
        } else
            needToParse = true;
    }

    if (needToParse)
        parseMappedAttribute(mappedAttr);

    if (entry == eNone && ownerDocument()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
        setChanged();

    if (checkDecl && mappedAttr->decl()) {
        // Add the decl to the table in the appropriate spot.
        setMappedAttributeDecl(entry, attr, mappedAttr->decl());
        mappedAttr->decl()->setMappedState(entry, attr->name(), attr->value());
        mappedAttr->decl()->setParent(0);
        mappedAttr->decl()->setNode(0);
        if (namedAttrMap)
            mappedAttributes()->declAdded();
    }
}
// This function mimics addCSSProperty and StyledElement::attributeChanged.
// In HTML code, you'd always call addCSSProperty from your derived parseMappedAttribute()
// function - though in SVG code we need to move this logic into svgAttributeChanged, in
// order to support SVG DOM changes (which don't use the parseMappedAttribute/attributeChanged).
// If we'd ignore SVG DOM, we could use _exactly_ the same logic as HTML.
static inline void addCSSPropertyAndNotifyAttributeMap(StyledElement* element, const QualifiedName& name, int cssProperty, const String& value)
{
    ASSERT(element);

    if (!element)
        return;

    NamedMappedAttrMap* attrs = element->mappedAttributes();
    ASSERT(attrs);

    if (!attrs)
        return;

    Attribute* attr = attrs->getAttributeItem(name);
    if (!attr || !attr->isMappedAttribute())
        return;

    MappedAttribute* mappedAttr = static_cast<MappedAttribute*>(attr);

    // This logic is only meant to be used for entries that have to be parsed and are mapped to eNone. Assert that.
    MappedAttributeEntry entry;
    bool needToParse = element->mapToEntry(mappedAttr->name(), entry);

    ASSERT(needToParse);
    ASSERT(entry == eNone);

    if (!needToParse || entry != eNone) 
        return;

    if (mappedAttr->decl()) {
        mappedAttr->setDecl(0);
        attrs->declRemoved();
    }

    element->setNeedsStyleRecalc();
    element->addCSSProperty(mappedAttr, cssProperty, value);

    if (CSSMappedAttributeDeclaration* decl = mappedAttr->decl()) {
        // Add the decl to the table in the appropriate spot.
        element->setMappedAttributeDecl(entry, mappedAttr, decl);

        decl->setMappedState(entry, mappedAttr->name(), mappedAttr->value());
        decl->setParent(0);
        decl->setNode(0);

        attrs->declAdded();
    }
}
Ejemplo n.º 4
0
PassRefPtr<CSSValue> SVGStyledElement::getPresentationAttribute(const String& name)
{
    if (!mappedAttributes())
        return 0;

    QualifiedName attributeName(nullAtom, name, nullAtom);
    Attribute* attr = mappedAttributes()->getAttributeItem(attributeName);
    if (!attr || !attr->isMappedAttribute() || !attr->style())
        return 0;

    MappedAttribute* cssSVGAttr = toMappedAttribute(attr);
    // This function returns a pointer to a CSSValue which can be mutated from JavaScript.
    // If the associated MappedAttribute uses the same CSSMappedAttributeDeclaration
    // as StyledElement's mappedAttributeDecls cache, create a new CSSMappedAttributeDeclaration
    // before returning so that any modifications to the CSSValue will not affect other attributes.
    MappedAttributeEntry entry;
    mapToEntry(attributeName, entry);
    if (getMappedAttributeDecl(entry, cssSVGAttr) == cssSVGAttr->decl()) {
        cssSVGAttr->setDecl(0);
        int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(cssSVGAttr->name());
        addCSSProperty(cssSVGAttr, propId, cssSVGAttr->value());
    }
    return cssSVGAttr->style()->getPropertyCSSValue(name);
}