360 lines
14 KiB
C++
360 lines
14 KiB
C++
/*
|
|
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
|
|
* Copyright (C) 2004, 2005, 2006, 2008, 2012, 2013 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2013 Intel Corporation. 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "CSSParserContext.h"
|
|
#include "CSSParserTokenRange.h"
|
|
#include "CSSProperty.h"
|
|
#include "CSSValueKeywords.h"
|
|
#include <memory>
|
|
#include <wtf/Function.h>
|
|
#include <wtf/TypeCasts.h>
|
|
#include <wtf/Vector.h>
|
|
#include <wtf/text/WTFString.h>
|
|
|
|
namespace WebCore {
|
|
|
|
class CSSDeferredParser;
|
|
class CSSStyleDeclaration;
|
|
class CachedResource;
|
|
class Color;
|
|
class ImmutableStyleProperties;
|
|
class MutableStyleProperties;
|
|
class PropertySetCSSStyleDeclaration;
|
|
class StyledElement;
|
|
class StylePropertyShorthand;
|
|
class StyleSheetContents;
|
|
|
|
enum StylePropertiesType { ImmutablePropertiesType, MutablePropertiesType, DeferredPropertiesType };
|
|
|
|
class StylePropertiesBase : public RefCounted<StylePropertiesBase> {
|
|
public:
|
|
// Override RefCounted's deref() to ensure operator delete is called on
|
|
// the appropriate subclass type.
|
|
void deref() const;
|
|
|
|
StylePropertiesType type() const { return static_cast<StylePropertiesType>(m_type); }
|
|
|
|
CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
|
|
|
|
protected:
|
|
StylePropertiesBase(CSSParserMode cssParserMode, StylePropertiesType type)
|
|
: m_cssParserMode(cssParserMode)
|
|
, m_type(type)
|
|
, m_arraySize(0)
|
|
{ }
|
|
|
|
StylePropertiesBase(CSSParserMode cssParserMode, unsigned immutableArraySize)
|
|
: m_cssParserMode(cssParserMode)
|
|
, m_type(ImmutablePropertiesType)
|
|
, m_arraySize(immutableArraySize)
|
|
{ }
|
|
|
|
unsigned m_cssParserMode : 3;
|
|
mutable unsigned m_type : 2;
|
|
unsigned m_arraySize : 27;
|
|
};
|
|
|
|
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(StyleProperties);
|
|
class StyleProperties : public StylePropertiesBase {
|
|
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(StyleProperties);
|
|
friend class PropertyReference;
|
|
public:
|
|
class PropertyReference {
|
|
public:
|
|
PropertyReference(const StylePropertyMetadata& metadata, const CSSValue* value)
|
|
: m_metadata(metadata)
|
|
, m_value(value)
|
|
{ }
|
|
|
|
CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); }
|
|
CSSPropertyID shorthandID() const { return m_metadata.shorthandID(); }
|
|
|
|
bool isImportant() const { return m_metadata.m_important; }
|
|
bool isInherited() const { return m_metadata.m_inherited; }
|
|
bool isImplicit() const { return m_metadata.m_implicit; }
|
|
|
|
String cssName() const;
|
|
String cssText() const;
|
|
|
|
const CSSValue* value() const { return m_value; }
|
|
// FIXME: We should try to remove this mutable overload.
|
|
CSSValue* value() { return const_cast<CSSValue*>(m_value); }
|
|
|
|
// FIXME: Remove this.
|
|
CSSProperty toCSSProperty() const { return CSSProperty(id(), const_cast<CSSValue*>(m_value), isImportant(), m_metadata.m_isSetFromShorthand, m_metadata.m_indexInShorthandsVector, isImplicit()); }
|
|
|
|
private:
|
|
const StylePropertyMetadata& m_metadata;
|
|
const CSSValue* m_value;
|
|
};
|
|
|
|
unsigned propertyCount() const;
|
|
bool isEmpty() const { return !propertyCount(); }
|
|
PropertyReference propertyAt(unsigned) const;
|
|
|
|
WEBCORE_EXPORT RefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
|
|
WEBCORE_EXPORT String getPropertyValue(CSSPropertyID) const;
|
|
|
|
WEBCORE_EXPORT std::optional<Color> propertyAsColor(CSSPropertyID) const;
|
|
WEBCORE_EXPORT CSSValueID propertyAsValueID(CSSPropertyID) const;
|
|
|
|
bool propertyIsImportant(CSSPropertyID) const;
|
|
String getPropertyShorthand(CSSPropertyID) const;
|
|
bool isPropertyImplicit(CSSPropertyID) const;
|
|
|
|
RefPtr<CSSValue> getCustomPropertyCSSValue(const String& propertyName) const;
|
|
String getCustomPropertyValue(const String& propertyName) const;
|
|
bool customPropertyIsImportant(const String& propertyName) const;
|
|
|
|
Ref<MutableStyleProperties> copyBlockProperties() const;
|
|
|
|
WEBCORE_EXPORT Ref<MutableStyleProperties> mutableCopy() const;
|
|
Ref<ImmutableStyleProperties> immutableCopyIfNeeded() const;
|
|
|
|
Ref<MutableStyleProperties> copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const;
|
|
|
|
String asText() const;
|
|
|
|
bool hasCSSOMWrapper() const;
|
|
bool isMutable() const { return type() == MutablePropertiesType; }
|
|
|
|
bool traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const;
|
|
|
|
static unsigned averageSizeInBytes();
|
|
|
|
#ifndef NDEBUG
|
|
void showStyle();
|
|
#endif
|
|
|
|
bool propertyMatches(CSSPropertyID, const CSSValue*) const;
|
|
|
|
protected:
|
|
StyleProperties(CSSParserMode cssParserMode, StylePropertiesType type)
|
|
: StylePropertiesBase(cssParserMode, type)
|
|
{ }
|
|
|
|
StyleProperties(CSSParserMode cssParserMode, unsigned immutableArraySize)
|
|
: StylePropertiesBase(cssParserMode, immutableArraySize)
|
|
{ }
|
|
|
|
int findPropertyIndex(CSSPropertyID) const;
|
|
int findCustomPropertyIndex(const String& propertyName) const;
|
|
|
|
private:
|
|
String getGridShorthandValue(const StylePropertyShorthand&) const;
|
|
String getShorthandValue(const StylePropertyShorthand&, const char* separator = " ") const;
|
|
String getCommonValue(const StylePropertyShorthand&) const;
|
|
String getAlignmentShorthandValue(const StylePropertyShorthand&) const;
|
|
String borderPropertyValue(const StylePropertyShorthand&, const StylePropertyShorthand&, const StylePropertyShorthand&) const;
|
|
String pageBreakPropertyValue(const StylePropertyShorthand&) const;
|
|
String getLayeredShorthandValue(const StylePropertyShorthand&) const;
|
|
String get2Values(const StylePropertyShorthand&) const;
|
|
String get4Values(const StylePropertyShorthand&) const;
|
|
String borderSpacingValue(const StylePropertyShorthand&) const;
|
|
String fontValue() const;
|
|
String fontVariantValue() const;
|
|
void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const;
|
|
|
|
friend class PropertySetCSSStyleDeclaration;
|
|
};
|
|
|
|
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ImmutableStyleProperties);
|
|
class ImmutableStyleProperties final : public StyleProperties {
|
|
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ImmutableStyleProperties);
|
|
public:
|
|
WEBCORE_EXPORT ~ImmutableStyleProperties();
|
|
static Ref<ImmutableStyleProperties> create(const CSSProperty* properties, unsigned count, CSSParserMode);
|
|
|
|
unsigned propertyCount() const { return m_arraySize; }
|
|
bool isEmpty() const { return !propertyCount(); }
|
|
PropertyReference propertyAt(unsigned index) const;
|
|
|
|
int findPropertyIndex(CSSPropertyID) const;
|
|
int findCustomPropertyIndex(const String& propertyName) const;
|
|
|
|
void* m_storage;
|
|
|
|
private:
|
|
PackedPtr<const CSSValue>* valueArray() const;
|
|
const StylePropertyMetadata* metadataArray() const;
|
|
ImmutableStyleProperties(const CSSProperty*, unsigned count, CSSParserMode);
|
|
};
|
|
|
|
inline PackedPtr<const CSSValue>* ImmutableStyleProperties::valueArray() const
|
|
{
|
|
return bitwise_cast<PackedPtr<const CSSValue>*>(bitwise_cast<const uint8_t*>(metadataArray()) + (m_arraySize * sizeof(StylePropertyMetadata)));
|
|
}
|
|
|
|
inline const StylePropertyMetadata* ImmutableStyleProperties::metadataArray() const
|
|
{
|
|
return reinterpret_cast<const StylePropertyMetadata*>(const_cast<const void**>((&(this->m_storage))));
|
|
}
|
|
|
|
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(MutableStyleProperties);
|
|
class MutableStyleProperties final : public StyleProperties {
|
|
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(MutableStyleProperties);
|
|
public:
|
|
WEBCORE_EXPORT static Ref<MutableStyleProperties> create(CSSParserMode = HTMLQuirksMode);
|
|
static Ref<MutableStyleProperties> create(Vector<CSSProperty>&&);
|
|
|
|
WEBCORE_EXPORT ~MutableStyleProperties();
|
|
|
|
unsigned propertyCount() const { return m_propertyVector.size(); }
|
|
bool isEmpty() const { return !propertyCount(); }
|
|
PropertyReference propertyAt(unsigned index) const;
|
|
|
|
PropertySetCSSStyleDeclaration* cssStyleDeclaration();
|
|
|
|
bool addParsedProperties(const ParsedPropertyVector&);
|
|
bool addParsedProperty(const CSSProperty&);
|
|
|
|
// These expand shorthand properties into multiple properties.
|
|
bool setProperty(CSSPropertyID, const String& value, bool important, CSSParserContext);
|
|
bool setProperty(CSSPropertyID, const String& value, bool important = false);
|
|
void setProperty(CSSPropertyID, RefPtr<CSSValue>&&, bool important = false);
|
|
|
|
// These do not. FIXME: This is too messy, we can do better.
|
|
bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
|
|
bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
|
|
bool setProperty(const CSSProperty&, CSSProperty* slot = nullptr);
|
|
|
|
bool removeProperty(CSSPropertyID, String* returnText = nullptr);
|
|
void removeBlockProperties();
|
|
bool removePropertiesInSet(const CSSPropertyID* set, unsigned length);
|
|
|
|
void mergeAndOverrideOnConflict(const StyleProperties&);
|
|
|
|
void clear();
|
|
bool parseDeclaration(const String& styleDeclaration, CSSParserContext);
|
|
|
|
WEBCORE_EXPORT CSSStyleDeclaration& ensureCSSStyleDeclaration();
|
|
CSSStyleDeclaration& ensureInlineCSSStyleDeclaration(StyledElement& parentElement);
|
|
|
|
int findPropertyIndex(CSSPropertyID) const;
|
|
int findCustomPropertyIndex(const String& propertyName) const;
|
|
|
|
Vector<CSSProperty, 4> m_propertyVector;
|
|
|
|
// Methods for querying and altering CSS custom properties.
|
|
bool setCustomProperty(const Document*, const String& propertyName, const String& value, bool important, CSSParserContext);
|
|
bool removeCustomProperty(const String& propertyName, String* returnText = nullptr);
|
|
|
|
private:
|
|
explicit MutableStyleProperties(CSSParserMode);
|
|
explicit MutableStyleProperties(const StyleProperties&);
|
|
MutableStyleProperties(Vector<CSSProperty>&&);
|
|
|
|
bool removeShorthandProperty(CSSPropertyID);
|
|
CSSProperty* findCSSPropertyWithID(CSSPropertyID);
|
|
CSSProperty* findCustomCSSPropertyWithName(const String&);
|
|
std::unique_ptr<PropertySetCSSStyleDeclaration> m_cssomWrapper;
|
|
bool canUpdateInPlace(const CSSProperty&, CSSProperty* toReplace) const;
|
|
|
|
friend class StyleProperties;
|
|
};
|
|
|
|
class DeferredStyleProperties final : public StylePropertiesBase {
|
|
public:
|
|
WEBCORE_EXPORT ~DeferredStyleProperties();
|
|
static Ref<DeferredStyleProperties> create(const CSSParserTokenRange&, CSSDeferredParser&);
|
|
|
|
Ref<ImmutableStyleProperties> parseDeferredProperties();
|
|
|
|
private:
|
|
DeferredStyleProperties(const CSSParserTokenRange&, CSSDeferredParser&);
|
|
|
|
Vector<CSSParserToken> m_tokens;
|
|
Ref<CSSDeferredParser> m_parser;
|
|
};
|
|
|
|
inline ImmutableStyleProperties::PropertyReference ImmutableStyleProperties::propertyAt(unsigned index) const
|
|
{
|
|
return PropertyReference(metadataArray()[index], valueArray()[index].get());
|
|
}
|
|
|
|
inline MutableStyleProperties::PropertyReference MutableStyleProperties::propertyAt(unsigned index) const
|
|
{
|
|
const CSSProperty& property = m_propertyVector[index];
|
|
return PropertyReference(property.metadata(), property.value());
|
|
}
|
|
|
|
inline StyleProperties::PropertyReference StyleProperties::propertyAt(unsigned index) const
|
|
{
|
|
if (is<MutableStyleProperties>(*this))
|
|
return downcast<MutableStyleProperties>(*this).propertyAt(index);
|
|
return downcast<ImmutableStyleProperties>(*this).propertyAt(index);
|
|
}
|
|
|
|
inline unsigned StyleProperties::propertyCount() const
|
|
{
|
|
if (is<MutableStyleProperties>(*this))
|
|
return downcast<MutableStyleProperties>(*this).propertyCount();
|
|
return downcast<ImmutableStyleProperties>(*this).propertyCount();
|
|
}
|
|
|
|
inline void StylePropertiesBase::deref() const
|
|
{
|
|
if (!derefBase())
|
|
return;
|
|
|
|
if (is<MutableStyleProperties>(*this))
|
|
delete downcast<MutableStyleProperties>(this);
|
|
else if (is<ImmutableStyleProperties>(*this))
|
|
delete downcast<ImmutableStyleProperties>(this);
|
|
else
|
|
delete downcast<DeferredStyleProperties>(this);
|
|
}
|
|
|
|
inline int StyleProperties::findPropertyIndex(CSSPropertyID propertyID) const
|
|
{
|
|
if (is<MutableStyleProperties>(*this))
|
|
return downcast<MutableStyleProperties>(*this).findPropertyIndex(propertyID);
|
|
return downcast<ImmutableStyleProperties>(*this).findPropertyIndex(propertyID);
|
|
}
|
|
|
|
inline int StyleProperties::findCustomPropertyIndex(const String& propertyName) const
|
|
{
|
|
if (is<MutableStyleProperties>(*this))
|
|
return downcast<MutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
|
|
return downcast<ImmutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
|
|
}
|
|
|
|
} // namespace WebCore
|
|
|
|
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleProperties)
|
|
static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() != WebCore::DeferredPropertiesType; }
|
|
SPECIALIZE_TYPE_TRAITS_END()
|
|
|
|
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MutableStyleProperties)
|
|
static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::MutablePropertiesType; }
|
|
SPECIALIZE_TYPE_TRAITS_END()
|
|
|
|
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ImmutableStyleProperties)
|
|
static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::ImmutablePropertiesType; }
|
|
SPECIALIZE_TYPE_TRAITS_END()
|
|
|
|
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::DeferredStyleProperties)
|
|
static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::DeferredPropertiesType; }
|
|
SPECIALIZE_TYPE_TRAITS_END()
|
|
|