📄 cssmutablestyledeclaration.cpp
字号:
ASSERT(!m_iteratorCount); if (removeShorthandProperty(propertyID, notifyChanged)) { // FIXME: Return an equivalent shorthand when possible. return String(); } CSSProperty* foundProperty = findPropertyWithId(propertyID); if (!foundProperty) return String(); String value = returnText ? foundProperty->value()->cssText() : String(); if (foundProperty->value()->isVariableDependentValue()) m_variableDependentValueCount--; // A more efficient removal strategy would involve marking entries as empty // and sweeping them when the vector grows too big. m_properties.remove(foundProperty - m_properties.data()); if (notifyChanged) setChanged(); return value;}void CSSMutableStyleDeclaration::setChanged(){ if (m_node) { // FIXME: Ideally, this should be factored better and there // should be a subclass of CSSMutableStyleDeclaration just // for inline style declarations that handles this bool isInlineStyleDeclaration = m_node->isStyledElement() && this == static_cast<StyledElement*>(m_node)->inlineStyleDecl(); if (isInlineStyleDeclaration) { m_node->setChanged(InlineStyleChange); static_cast<StyledElement*>(m_node)->invalidateStyleAttribute(); } else m_node->setChanged(FullStyleChange); return; } // FIXME: quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk) StyleBase* root = this; while (StyleBase* parent = root->parent()) root = parent; if (root->isCSSStyleSheet()) static_cast<CSSStyleSheet*>(root)->doc()->updateStyleSelector();}bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const{ const CSSProperty* property = findPropertyWithId(propertyID); return property ? property->isImportant() : false;}int CSSMutableStyleDeclaration::getPropertyShorthand(int propertyID) const{ const CSSProperty* property = findPropertyWithId(propertyID); return property ? property->shorthandID() : 0;}bool CSSMutableStyleDeclaration::isPropertyImplicit(int propertyID) const{ const CSSProperty* property = findPropertyWithId(propertyID); return property ? property->isImplicit() : false;}void CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, ExceptionCode& ec){ ec = 0; setProperty(propertyID, value, important, true);}String CSSMutableStyleDeclaration::removeProperty(int propertyID, ExceptionCode& ec){ ec = 0; return removeProperty(propertyID, true, true);}bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, bool notifyChanged){ ASSERT(!m_iteratorCount); // Setting the value to an empty string just removes the property in both IE and Gecko. // Setting it to null seems to produce less consistent results, but we treat it just the same. if (value.isEmpty()) { removeProperty(propertyID, notifyChanged, false); return true; } // When replacing an existing property value, this moves the property to the end of the list. // Firefox preserves the position, and MSIE moves the property to the beginning. CSSParser parser(useStrictParsing()); bool success = parser.parseValue(this, propertyID, value, important); if (!success) { // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility, // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. } else if (notifyChanged) setChanged(); return success;} void CSSMutableStyleDeclaration::setPropertyInternal(const CSSProperty& property, CSSProperty* slot){ ASSERT(!m_iteratorCount); if (!removeShorthandProperty(property.id(), false)) { CSSProperty* toReplace = slot ? slot : findPropertyWithId(property.id()); if (toReplace) { *toReplace = property; return; } } m_properties.append(property);}bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged){ CSSProperty property(propertyID, CSSPrimitiveValue::createIdentifier(value), important); setPropertyInternal(property); if (notifyChanged) setChanged(); return true;}void CSSMutableStyleDeclaration::setStringProperty(int propertyId, const String &value, CSSPrimitiveValue::UnitTypes type, bool important){ ASSERT(!m_iteratorCount); setPropertyInternal(CSSProperty(propertyId, CSSPrimitiveValue::create(value, type), important)); setChanged();}void CSSMutableStyleDeclaration::setImageProperty(int propertyId, const String& url, bool important){ ASSERT(!m_iteratorCount); setPropertyInternal(CSSProperty(propertyId, CSSImageValue::create(url), important)); setChanged();}void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration){ ASSERT(!m_iteratorCount); m_properties.clear(); CSSParser parser(useStrictParsing()); parser.parseDeclaration(this, styleDeclaration); setChanged();}void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty* const* properties, int numProperties){ ASSERT(!m_iteratorCount); m_properties.reserveCapacity(numProperties); for (int i = 0; i < numProperties; ++i) { // Only add properties that have no !important counterpart present if (!getPropertyPriority(properties[i]->id()) || properties[i]->isImportant()) { removeProperty(properties[i]->id(), false); ASSERT(properties[i]); m_properties.append(*properties[i]); if (properties[i]->value()->isVariableDependentValue()) m_variableDependentValueCount++; } } // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add // a notifyChanged argument to this function to follow the model of other functions in this class.}void CSSMutableStyleDeclaration::addParsedProperty(const CSSProperty& property){ ASSERT(!m_iteratorCount); setPropertyInternal(property);}void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& value, bool important, bool /*multiLength*/){ ASSERT(!m_iteratorCount); bool parseMode = useStrictParsing(); setStrictParsing(false); setProperty(propertyId, value, important); setStrictParsing(parseMode);}unsigned CSSMutableStyleDeclaration::length() const{ return m_properties.size();}String CSSMutableStyleDeclaration::item(unsigned i) const{ if (i >= m_properties.size()) return String(); return getPropertyName(static_cast<CSSPropertyID>(m_properties[i].id()));}String CSSMutableStyleDeclaration::cssText() const{ String result = ""; const CSSProperty* positionXProp = 0; const CSSProperty* positionYProp = 0; unsigned size = m_properties.size(); for (unsigned n = 0; n < size; ++n) { const CSSProperty& prop = m_properties[n]; if (prop.id() == CSSPropertyBackgroundPositionX) positionXProp = ∝ else if (prop.id() == CSSPropertyBackgroundPositionY) positionYProp = ∝ else result += prop.cssText(); } // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. // It is required because background-position-x/y are non-standard properties and WebKit generated output // would not work in Firefox (<rdar://problem/5143183>) // It would be a better solution if background-position was CSS_PAIR. if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) { String positionValue; const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY }; if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList()) positionValue = getLayeredShorthandValue(properties, 2); else positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText(); result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; "; } else { if (positionXProp) result += positionXProp->cssText(); if (positionYProp) result += positionYProp->cssText(); } return result;}void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& ec){ ASSERT(!m_iteratorCount); ec = 0; m_properties.clear(); CSSParser parser(useStrictParsing()); parser.parseDeclaration(this, text); // FIXME: Detect syntax errors and set ec. setChanged();}void CSSMutableStyleDeclaration::merge(CSSMutableStyleDeclaration* other, bool argOverridesOnConflict){ ASSERT(!m_iteratorCount); unsigned size = other->m_properties.size(); for (unsigned n = 0; n < size; ++n) { CSSProperty& toMerge = other->m_properties[n]; CSSProperty* old = findPropertyWithId(toMerge.id()); if (old) { if (!argOverridesOnConflict && old->value()) continue; setPropertyInternal(toMerge, old); } else m_properties.append(toMerge); } // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add // a notifyChanged argument to this function to follow the model of other functions in this class.}void CSSMutableStyleDeclaration::addSubresourceStyleURLs(ListHashSet<KURL>& urls){ CSSStyleSheet* sheet = static_cast<CSSStyleSheet*>(stylesheet()); size_t size = m_properties.size(); for (size_t i = 0; i < size; ++i) m_properties[i].value()->addSubresourceStyleURLs(urls, sheet);}// This is the list of properties we want to copy in the copyBlockProperties() function.// It is the list of CSS properties that apply specially to block-level elements.static const int blockProperties[] = { CSSPropertyOrphans, CSSPropertyOverflow, // This can be also be applied to replaced elements CSSPropertyWebkitColumnCount, CSSPropertyWebkitColumnGap, CSSPropertyWebkitColumnRuleColor, CSSPropertyWebkitColumnRuleStyle, CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnBreakBefore, CSSPropertyWebkitColumnBreakAfter, CSSPropertyWebkitColumnBreakInside, CSSPropertyWebkitColumnWidth, CSSPropertyPageBreakAfter, CSSPropertyPageBreakBefore, CSSPropertyPageBreakInside, CSSPropertyTextAlign, CSSPropertyTextIndent, CSSPropertyWidows};const unsigned numBlockProperties = sizeof(blockProperties) / sizeof(blockProperties[0]);PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyBlockProperties() const{ return copyPropertiesInSet(blockProperties, numBlockProperties);}void CSSMutableStyleDeclaration::removeBlockProperties(){ removePropertiesInSet(blockProperties, numBlockProperties);}void CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged){ ASSERT(!m_iteratorCount); if (m_properties.isEmpty()) return; // FIXME: This is always used with static sets and in that case constructing the hash repeatedly is pretty pointless. HashSet<int> toRemove; for (unsigned i = 0; i < length; ++i) toRemove.add(set[i]); Vector<CSSProperty, 4> newProperties; newProperties.reserveInitialCapacity(m_properties.size()); unsigned size = m_properties.size(); for (unsigned n = 0; n < size; ++n) { const CSSProperty& property = m_properties[n]; // Not quite sure if the isImportant test is needed but it matches the existing behavior. if (!property.isImportant()) { if (toRemove.contains(property.id())) continue; } newProperties.append(property); } bool changed = newProperties.size() != m_properties.size(); m_properties = newProperties; if (changed && notifyChanged) setChanged();}PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable(){ return this;}PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copy() const{ return adoptRef(new CSSMutableStyleDeclaration(0, m_properties, m_variableDependentValueCount));}const CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID) const{ for (int n = m_properties.size() - 1 ; n >= 0; --n) { if (propertyID == m_properties[n].m_id) return &m_properties[n]; } return 0;}CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID){ for (int n = m_properties.size() - 1 ; n >= 0; --n) { if (propertyID == m_properties[n].m_id) return &m_properties[n]; } return 0;}} // namespace WebCore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -