Chromium Code Reviews| Index: third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp |
| diff --git a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..deda5f66302016f0e85648b395a7a15259cf4869 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp |
| @@ -0,0 +1,192 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/css/cssom/InlineStylePropertyMap.h" |
| + |
| +#include "core/CSSPropertyNames.h" |
| +#include "core/css/CSSPrimitiveValue.h" |
| +#include "core/css/CSSPropertyMetadata.h" |
| +#include "core/css/CSSValueList.h" |
| +#include "core/css/StylePropertySet.h" |
| +#include "core/css/cssom/CSSOMTypes.h" |
| +#include "core/css/cssom/SimpleLength.h" |
| +#include "core/css/cssom/StyleValueFactory.h" |
| + |
| +namespace blink { |
| + |
| +StyleValue* InlineStylePropertyMap::get(CSSPropertyID propertyID) |
| +{ |
| + ASSERT(propertyID != CSSPropertyInvalid); |
| + |
| + updatePropertyIfNeeded(propertyID); |
| + |
| + if (!m_styles.contains(propertyID)) { |
| + return nullptr; |
| + } |
| + StyleValueVector& styleVector = ensurePropertyList(propertyID); |
| + if (styleVector.isEmpty()) { |
| + return nullptr; |
| + } |
| + return styleVector.at(0); |
| +} |
| + |
| +StyleValueVector InlineStylePropertyMap::getAll(CSSPropertyID propertyID) |
| +{ |
| + ASSERT(propertyID != CSSPropertyInvalid); |
| + |
| + updatePropertyIfNeeded(propertyID); |
| + |
| + if (!m_styles.contains(propertyID)) |
| + return StyleValueVector(); |
| + |
| + return ensurePropertyList(propertyID); |
| +} |
| + |
| +bool InlineStylePropertyMap::has(CSSPropertyID propertyID) |
| +{ |
| + ASSERT(propertyID != CSSPropertyInvalid); |
| + return m_styles.contains(propertyID) && (!ensurePropertyList(propertyID).isEmpty()); |
| +} |
| + |
| +Vector<String> InlineStylePropertyMap::getProperties() |
| +{ |
| + Vector<String> result; |
| + StylePropertySet& inlineStyleSet = m_ownerElement->ensureMutableInlineStyle(); |
| + for (unsigned i = 0; i < inlineStyleSet.propertyCount(); i++) { |
| + CSSPropertyID cssPropertyID = inlineStyleSet.propertyAt(i).id(); |
| + // TODO(meade): Consider whether this is necessary here. |
| + updatePropertyIfNeeded(cssPropertyID); |
| + result.append(getPropertyNameString(cssPropertyID)); |
| + } |
| + return result; |
| +} |
| + |
| +void InlineStylePropertyMap::set(CSSPropertyID propertyID, StyleValueOrStyleValueSequenceOrString& item, ExceptionState& exceptionState) |
| +{ |
| + ASSERT(propertyID != CSSPropertyInvalid); |
| + if (!item.isNull()) { |
|
Timothy Loh
2016/03/23 03:45:09
IMO clearer to not negate here and switch the orde
meade_UTC10
2016/03/29 06:27:36
Done.
|
| + m_styles.remove(propertyID); |
| + append(propertyID, item, exceptionState); |
| + } else { |
| + // Clear it. |
|
Timothy Loh
2016/03/23 03:45:08
I don't think this is a useful comment.
meade_UTC10
2016/03/29 06:27:36
Removed.
|
| + remove(propertyID, exceptionState); |
| + } |
| +} |
| + |
| +void InlineStylePropertyMap::append(CSSPropertyID propertyID, StyleValueOrStyleValueSequenceOrString& item, ExceptionState& exceptionState) |
| +{ |
| + ASSERT(propertyID != CSSPropertyInvalid); |
| + |
| + StyleValueVector& values = ensurePropertyList(propertyID); |
| + bool supportsMultiple = CSSPropertyMetadata::propertySupportsMultiple(propertyID); |
| + |
| + if (item.isStyleValue()) { |
| + // Setting a single value. |
| + StyleValue* value = item.getAsStyleValue(); |
| + if (!CSSOMTypes::propertyCanTake(propertyID, *value)) { |
| + exceptionState.throwTypeError("Invalid type for property"); |
| + return; |
| + } |
| + if (!values.isEmpty() && !supportsMultiple) { |
| + exceptionState.throwTypeError("Property does not support multiple values"); |
| + return; |
| + } |
| + values.append(value); |
| + |
| + } else if (item.isStyleValueSequence()) { |
| + if (!CSSPropertyMetadata::propertySupportsMultiple(propertyID)) { |
|
Timothy Loh
2016/03/23 03:45:09
!supportsMultiple
meade_UTC10
2016/03/29 06:27:36
Done.
|
| + exceptionState.throwTypeError("Property does not support multiple values"); |
|
Timothy Loh
2016/03/23 03:45:09
need a return here?
meade_UTC10
2016/03/29 06:27:36
Done.
|
| + } |
| + // Check all the values in the sequence to make sure they're valid. |
| + const StyleValueVector specifiedValues = item.getAsStyleValueSequence(); |
| + for (const Member<StyleValue> value : specifiedValues) { |
| + if (!CSSOMTypes::propertyCanTake(propertyID, *value)) { |
| + exceptionState.throwTypeError("Invalid type for property"); |
| + return; |
| + } |
| + } |
| + values.appendVector(specifiedValues); |
| + |
| + } else if (item.isNull()) { |
|
Timothy Loh
2016/03/23 03:45:09
IMO put this last (so the if structure matches the
meade_UTC10
2016/03/29 06:27:36
Done.
|
| + // No-op |
| + return; |
| + } else if (item.isString()) { |
| + // Parse it. |
| + // TODO(meade): Implement this. |
| + exceptionState.throwTypeError("Not implemented yet"); |
| + return; |
| + } |
| + |
| + if (supportsMultiple) { |
| + RefPtrWillBeRawPtr<CSSValueList> valueList = CSSValueList::createSpaceSeparated(); |
| + for (const Member<StyleValue> value : values) { |
| + valueList->append(value->toCSSValue()); |
| + } |
| + m_ownerElement->setInlineStyleProperty(propertyID, valueList); |
| + } else { |
| + m_ownerElement->setInlineStyleProperty(propertyID, values[0]->toCSSValue()); |
| + } |
| + m_cleanStyles.set(propertyID, true); |
| +} |
| + |
| +void InlineStylePropertyMap::remove(CSSPropertyID propertyID, ExceptionState& exceptionState) |
| +{ |
| + ASSERT(propertyID != CSSPropertyInvalid); |
| + |
| + const StyleVectorMap::iterator& iterator = m_styles.find(propertyID); |
| + if (iterator == m_styles.end()) |
| + return; |
| + |
| + m_styles.remove(iterator); |
| + m_ownerElement->removeInlineStyleProperty(propertyID); |
| + m_cleanStyles.set(propertyID, true); |
| +} |
| + |
| +void InlineStylePropertyMap::updatePropertyIfNeeded(CSSPropertyID propertyID) |
| +{ |
| + if (m_cleanStyles.contains(propertyID) && m_cleanStyles.get(propertyID)) { |
| + return; |
| + } |
| + |
| + RefPtrWillBeRawPtr<CSSValue> cssValue = m_ownerElement->ensureMutableInlineStyle().getPropertyCSSValue(propertyID); |
| + if (!cssValue) { |
| + m_styles.remove(propertyID); |
| + m_cleanStyles.set(propertyID, true); |
| + return; |
| + } |
| + |
| + StyleValueVector& values = ensurePropertyList(propertyID); |
| + values.clear(); |
| + |
| + if (!cssValue->isValueList()) { |
| + StyleValue* styleValue = StyleValueFactory::create(propertyID, *cssValue); |
| + if (styleValue) { |
| + values.append(*styleValue); |
| + } |
| + } |
| + |
| + if (values.isEmpty()) |
| + m_styles.remove(propertyID); |
| + |
| + // TODO(meade) implement the other cases. |
| + |
| + m_cleanStyles.set(propertyID, true); |
| +} |
| + |
| +void InlineStylePropertyMap::updateCustomProperty(const String& propertyName, PassRefPtrWillBeRawPtr<CSSValue> cssValue) |
| +{ |
| + // TODO(meade): Implement. |
| +} |
| + |
| +StyleValueVector& InlineStylePropertyMap::ensurePropertyList(CSSPropertyID propertyID) |
| +{ |
| + if (!m_styles.contains(propertyID)) { |
|
Timothy Loh
2016/03/23 03:45:09
Can probably make this a little more efficient in
meade_UTC10
2016/03/29 06:27:36
Done.
|
| + m_styles.set(propertyID, StyleValueVector()); |
| + } |
| + // Note: If you write return m_style.get(propertyID) here, you get a copy. |
| + return m_styles.find(propertyID)->value; |
| +} |
| + |
| +} // namespace blink |
| + |