📄 cssmutablestyledeclaration.cpp
字号:
/* * (C) 1999-2003 Lars Knoll (knoll@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "CSSMutableStyleDeclaration.h"#include "CSSImageValue.h"#include "CSSParser.h"#include "CSSProperty.h"#include "CSSPropertyLonghand.h"#include "CSSPropertyNames.h"#include "CSSRule.h"#include "CSSStyleSheet.h"#include "CSSValueList.h"#include "Document.h"#include "ExceptionCode.h"#include "StyledElement.h"using namespace std;namespace WebCore {CSSMutableStyleDeclaration::CSSMutableStyleDeclaration() : m_node(0) , m_variableDependentValueCount(0) , m_strictParsing(false)#ifndef NDEBUG , m_iteratorCount(0)#endif{}CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent) : CSSStyleDeclaration(parent) , m_node(0) , m_variableDependentValueCount(0) , m_strictParsing(!parent || parent->useStrictParsing())#ifndef NDEBUG , m_iteratorCount(0)#endif{}CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const Vector<CSSProperty>& properties, unsigned variableDependentValueCount) : CSSStyleDeclaration(parent) , m_properties(properties) , m_node(0) , m_variableDependentValueCount(variableDependentValueCount) , m_strictParsing(!parent || parent->useStrictParsing())#ifndef NDEBUG , m_iteratorCount(0)#endif{ m_properties.shrinkToFit(); // FIXME: This allows duplicate properties.}CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CSSProperty* const * properties, int numProperties) : CSSStyleDeclaration(parent) , m_node(0) , m_variableDependentValueCount(0) , m_strictParsing(!parent || parent->useStrictParsing())#ifndef NDEBUG , m_iteratorCount(0)#endif{ m_properties.reserveInitialCapacity(numProperties); for (int i = 0; i < numProperties; ++i) { ASSERT(properties[i]); m_properties.append(*properties[i]); if (properties[i]->value()->isVariableDependentValue()) m_variableDependentValueCount++; } // FIXME: This allows duplicate properties.}CSSMutableStyleDeclaration& CSSMutableStyleDeclaration::operator=(const CSSMutableStyleDeclaration& other){ ASSERT(!m_iteratorCount); // don't attach it to the same node, just leave the current m_node value m_properties = other.m_properties; m_strictParsing = other.m_strictParsing; return *this;}String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const{ RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); if (value) return value->cssText(); // Shorthand and 4-values properties switch (propertyID) { case CSSPropertyBackgroundPosition: { // FIXME: Is this correct? The code in cssparser.cpp is confusing const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY }; return getLayeredShorthandValue(properties, 2); } case CSSPropertyBackground: { const int properties[7] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat, CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyWebkitBackgroundClip, CSSPropertyWebkitBackgroundOrigin, CSSPropertyBackgroundColor }; return getLayeredShorthandValue(properties, 7); } case CSSPropertyBorder: { const int properties[3][4] = {{ CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth }, { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle }, { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor }}; String res; const int nrprops = sizeof(properties) / sizeof(properties[0]); for (int i = 0; i < nrprops; ++i) { String value = getCommonValue(properties[i], 4); if (!value.isNull()) { if (!res.isNull()) res += " "; res += value; } } return res; } case CSSPropertyBorderTop: { const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle, CSSPropertyBorderTopColor}; return getShorthandValue(properties, 3); } case CSSPropertyBorderRight: { const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle, CSSPropertyBorderRightColor}; return getShorthandValue(properties, 3); } case CSSPropertyBorderBottom: { const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle, CSSPropertyBorderBottomColor}; return getShorthandValue(properties, 3); } case CSSPropertyBorderLeft: { const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle, CSSPropertyBorderLeftColor}; return getShorthandValue(properties, 3); } case CSSPropertyOutline: { const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle, CSSPropertyOutlineColor }; return getShorthandValue(properties, 3); } case CSSPropertyBorderColor: { const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor }; return get4Values(properties); } case CSSPropertyBorderWidth: { const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth }; return get4Values(properties); } case CSSPropertyBorderStyle: { const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle }; return get4Values(properties); } case CSSPropertyMargin: { const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight, CSSPropertyMarginBottom, CSSPropertyMarginLeft }; return get4Values(properties); } case CSSPropertyOverflow: { const int properties[2] = { CSSPropertyOverflowX, CSSPropertyOverflowY }; return getCommonValue(properties, 2); } case CSSPropertyPadding: { const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight, CSSPropertyPaddingBottom, CSSPropertyPaddingLeft }; return get4Values(properties); } case CSSPropertyListStyle: { const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition, CSSPropertyListStyleImage }; return getShorthandValue(properties, 3); } case CSSPropertyWebkitMaskPosition: { // FIXME: Is this correct? The code in cssparser.cpp is confusing const int properties[2] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY }; return getLayeredShorthandValue(properties, 2); } case CSSPropertyWebkitMask: { const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat, CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskClip, CSSPropertyWebkitMaskOrigin }; return getLayeredShorthandValue(properties, 6); } case CSSPropertyWebkitTransformOrigin: { const int properties[3] = { CSSPropertyWebkitTransformOriginX, CSSPropertyWebkitTransformOriginY, CSSPropertyWebkitTransformOriginZ }; return getShorthandValue(properties, 3); } case CSSPropertyWebkitTransition: { const int properties[4] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration, CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionDelay }; return getLayeredShorthandValue(properties, 4); } case CSSPropertyWebkitAnimation: { const int properties[6] = { CSSPropertyWebkitAnimationName, CSSPropertyWebkitAnimationDuration, CSSPropertyWebkitAnimationTimingFunction, CSSPropertyWebkitAnimationDelay, CSSPropertyWebkitAnimationIterationCount, CSSPropertyWebkitAnimationDirection }; return getLayeredShorthandValue(properties, 6); }#if ENABLE(SVG) case CSSPropertyMarker: { RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyMarkerStart); if (value) return value->cssText(); }#endif } return String();}String CSSMutableStyleDeclaration::get4Values(const int* properties) const{ String res; for (int i = 0; i < 4; ++i) { if (!isPropertyImplicit(properties[i])) { RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); // apparently all 4 properties must be specified. if (!value) return String(); if (!res.isNull()) res += " "; res += value->cssText(); } } return res;}String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, unsigned number) const{ String res; // Begin by collecting the properties into an array. Vector< RefPtr<CSSValue> > values(number); size_t numLayers = 0; for (size_t i = 0; i < number; ++i) { values[i] = getPropertyCSSValue(properties[i]); if (values[i]) { if (values[i]->isValueList()) { CSSValueList* valueList = static_cast<CSSValueList*>(values[i].get()); numLayers = max(valueList->length(), numLayers); } else numLayers = max<size_t>(1U, numLayers); } } // Now stitch the properties together. Implicit initial values are flagged as such and // can safely be omitted. for (size_t i = 0; i < numLayers; i++) { String layerRes; for (size_t j = 0; j < number; j++) { RefPtr<CSSValue> value; if (values[j]) { if (values[j]->isValueList()) value = static_cast<CSSValueList*>(values[j].get())->itemWithoutBoundsCheck(i); else { value = values[j]; // Color only belongs in the last layer. if (properties[j] == CSSPropertyBackgroundColor) { if (i != numLayers - 1) value = 0; } else if (i != 0) // Other singletons only belong in the first layer. value = 0; } } if (value && !value->isImplicitInitialValue()) { if (!layerRes.isNull()) layerRes += " "; layerRes += value->cssText(); } } if (!layerRes.isNull()) { if (!res.isNull()) res += ", "; res += layerRes; } } return res;}String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, int number) const{ String res; for (int i = 0; i < number; ++i) { if (!isPropertyImplicit(properties[i])) { RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); // FIXME: provide default value if !value if (value) { if (!res.isNull()) res += " "; res += value->cssText(); } } } return res;}// only returns a non-null value if all properties have the same, non-null valueString CSSMutableStyleDeclaration::getCommonValue(const int* properties, int number) const{ String res; for (int i = 0; i < number; ++i) { if (!isPropertyImplicit(properties[i])) { RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); if (!value) return String(); String text = value->cssText(); if (text.isNull()) return String(); if (res.isNull()) res = text; else if (res != text) return String(); } } return res;}PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(int propertyID) const{ const CSSProperty* property = findPropertyWithId(propertyID); return property ? property->value() : 0;}bool CSSMutableStyleDeclaration::removeShorthandProperty(int propertyID, bool notifyChanged) { CSSPropertyLonghand longhand = longhandForProperty(propertyID); if (longhand.length()) { removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged); return true; } return false;}String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -