Browse Source

WIP more strings to IDs (not compiling)

Michael Ragazzon 6 years ago
parent
commit
44adb03aee

+ 2 - 1
Include/Rocket/Core/Animation.h

@@ -33,6 +33,7 @@
 
 #include "String.h"
 #include "Tween.h"
+#include "../Source/Core/StringCache.h"
 
 namespace Rocket {
 namespace Core {
@@ -52,7 +53,7 @@ typedef std::vector<Animation> AnimationList;
 
 /* Data parsed from the 'transition' property. */
 struct Transition {
-	PropertyId property_id = InvalidPropertyId;
+	PropertyId property_id = PropertyId::Invalid;
 	Tween tween;
 	float duration = 0.0f;
 	float delay = 0.0f;

+ 1 - 1
Include/Rocket/Core/ElementDocument.h

@@ -136,7 +136,7 @@ public:
 	
 protected:
 	/// Repositions the document if necessary.
-	virtual void OnPropertyChange(const PropertyNameList& changed_properties);
+	virtual void OnPropertyChange(const PropertyIdList& changed_properties);
 
 	/// Sets the dirty flag on the layout so the document will format its children before the next render.
 	virtual void DirtyLayout();

+ 11 - 0
Include/Rocket/Core/PropertyDictionary.h

@@ -44,6 +44,17 @@ namespace Core {
 
 using PropertyDictionary = PropertyMap;
 
+/// Merges the contents of another fully-specified property dictionary with this one.
+/// Properties defined in the new dictionary will overwrite those with the same name as
+/// appropriate.
+void Merge(PropertyDictionary& destination, const PropertyDictionary& from, int specificity_offset = 0);
+
+/// Imports into the dictionary, and optionally defines the specificity of, potentially
+/// un-specified properties. In the case of name conflicts, the incoming properties will
+/// overwrite the existing properties if their specificity (or their forced specificity)
+/// are at least equal.
+void Import(PropertyDictionary& destination, const PropertyDictionary& from, int specificity = -1);
+
 //class ROCKETCORE_API PropertyDictionary
 //{
 //public:

+ 3 - 4
Include/Rocket/Core/Types.h

@@ -102,10 +102,9 @@ typedef uintptr_t TextureHandle;
 typedef uintptr_t CompiledGeometryHandle;
 typedef uintptr_t DecoratorDataHandle;
 
-enum class PropertyId : uint16_t {};
-enum class EventId : uint16_t {};
-static constexpr PropertyId InvalidPropertyId = static_cast<PropertyId>(0);
-static constexpr EventId InvalidEventId = static_cast<EventId>(0);
+enum class PropertyId : uint16_t;
+enum class EventId : uint16_t;
+//enum class PseudoId : uint16_t;
 
 // List of elements.
 typedef std::vector< Element* > ElementList;

+ 25 - 25
Source/Core/DecoratorTiledInstancer.cpp

@@ -39,42 +39,42 @@ DecoratorTiledInstancer::~DecoratorTiledInstancer()
 // Adds the property declarations for a tile.
 void DecoratorTiledInstancer::RegisterTileProperty(const String& name, bool register_repeat_modes)
 {
-	RegisterProperty(AddPropertyName( CreateString(32, "%s-src", name.c_str())), "").AddParser("string");
-	RegisterProperty(AddPropertyName( CreateString(32, "%s-s-begin", name.c_str())), "0").AddParser("length");
-	RegisterProperty(AddPropertyName( CreateString(32, "%s-s-end", name.c_str())), "1").AddParser("length");
-	RegisterProperty(AddPropertyName( CreateString(32, "%s-t-begin", name.c_str())), "0").AddParser("length");
-	RegisterProperty(AddPropertyName( CreateString(32, "%s-t-end", name.c_str())), "1").AddParser("length");
-	RegisterShorthand(AddPropertyName(CreateString(32, "%s-s", name.c_str())),
-		{ AddPropertyName(CreateString(32, "%s-s-begin", name.c_str())), AddPropertyName(CreateString(32, "%s-s-end", name.c_str())) }
+	RegisterProperty(CreateOrGetPropertyId( CreateString(32, "%s-src", name.c_str())), "").AddParser("string");
+	RegisterProperty(CreateOrGetPropertyId( CreateString(32, "%s-s-begin", name.c_str())), "0").AddParser("length");
+	RegisterProperty(CreateOrGetPropertyId( CreateString(32, "%s-s-end", name.c_str())), "1").AddParser("length");
+	RegisterProperty(CreateOrGetPropertyId( CreateString(32, "%s-t-begin", name.c_str())), "0").AddParser("length");
+	RegisterProperty(CreateOrGetPropertyId( CreateString(32, "%s-t-end", name.c_str())), "1").AddParser("length");
+	RegisterShorthand(CreateOrGetPropertyId(CreateString(32, "%s-s", name.c_str())),
+		{ CreateOrGetPropertyId(CreateString(32, "%s-s-begin", name.c_str())), CreateOrGetPropertyId(CreateString(32, "%s-s-end", name.c_str())) }
 	);
-	RegisterShorthand(AddPropertyName(CreateString(32, "%s-t", name.c_str())),
-		{ AddPropertyName(CreateString(32, "%s-t-begin", name.c_str())), AddPropertyName(CreateString(32, "%s-t-end", name.c_str())) }
+	RegisterShorthand(CreateOrGetPropertyId(CreateString(32, "%s-t", name.c_str())),
+		{ CreateOrGetPropertyId(CreateString(32, "%s-t-begin", name.c_str())), CreateOrGetPropertyId(CreateString(32, "%s-t-end", name.c_str())) }
 	);
 
 	if (register_repeat_modes)
 	{
-		RegisterProperty(AddPropertyName( CreateString(32, "%s-repeat", name.c_str())), "stretch")
+		RegisterProperty(CreateOrGetPropertyId( CreateString(32, "%s-repeat", name.c_str())), "stretch")
 			.AddParser("keyword", "stretch, clamp-stretch, clamp-truncate, repeat-stretch, repeat-truncate");
 		
-		RegisterShorthand(AddPropertyName(name),
+		RegisterShorthand(CreateOrGetPropertyId(name),
 			{ 
-				AddPropertyName(CreateString(32, "%s-src", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-repeat", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-s-begin", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-t-begin", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-s-end", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-t-end", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-src", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-repeat", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-s-begin", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-t-begin", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-s-end", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-t-end", name.c_str())),
 			}
 		);
 	}
 	else
-		RegisterShorthand(AddPropertyName(name),
+		RegisterShorthand(CreateOrGetPropertyId(name),
 			{
-				AddPropertyName(CreateString(32, "%s-src", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-s-begin", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-t-begin", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-s-end", name.c_str())),
-				AddPropertyName(CreateString(32, "%s-t-end", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-src", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-s-begin", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-t-begin", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-s-end", name.c_str())),
+				CreateOrGetPropertyId(CreateString(32, "%s-t-end", name.c_str())),
 			}
 		);
 }
@@ -87,11 +87,11 @@ void DecoratorTiledInstancer::GetTileProperties(DecoratorTiled::Tile& tile, Stri
 	LoadTexCoord(properties, GetPropertyId( CreateString(32, "%s-s-end", name.c_str())), tile.texcoords[1].x, tile.texcoords_absolute[1][0]);
 	LoadTexCoord(properties, GetPropertyId( CreateString(32, "%s-t-end", name.c_str())), tile.texcoords[1].y, tile.texcoords_absolute[1][1]);
 
-	const Property* repeat_property = GetIf(properties, AddPropertyName( CreateString(32, "%s-repeat", name.c_str())));
+	const Property* repeat_property = GetIf(properties, CreateOrGetPropertyId( CreateString(32, "%s-repeat", name.c_str())));
 	if (repeat_property != NULL)
 		tile.repeat_mode = (DecoratorTiled::TileRepeatMode) repeat_property->value.Get< int >();
 
-	const Property* texture_property = GetIf(properties, AddPropertyName( CreateString(32, "%s-src", name.c_str())));
+	const Property* texture_property = GetIf(properties, CreateOrGetPropertyId( CreateString(32, "%s-src", name.c_str())));
 	texture_name = texture_property->Get< String >();
 	rcss_path = texture_property->source;
 }

+ 78 - 78
Source/Core/Element.cpp

@@ -439,7 +439,7 @@ void Element::SetBox(const Box& box)
 		border->DirtyBorder();
 		decoration->ReloadDecorators();
 
-		DispatchEvent(RESIZE, Dictionary());
+		DispatchEvent(EventId::Resize, Dictionary());
 	}
 }
 
@@ -447,7 +447,7 @@ void Element::SetBox(const Box& box)
 void Element::AddBox(const Box& box)
 {
 	boxes.push_back(box);
-	DispatchEvent(RESIZE, Dictionary());
+	DispatchEvent(EventId::Resize, Dictionary());
 
 	background->DirtyBackground();
 	border->DirtyBorder();
@@ -1120,7 +1120,7 @@ void Element::SetScrollLeft(float scroll_left)
 	scroll->UpdateScrollbar(ElementScroll::HORIZONTAL);
 	DirtyOffset();
 
-	DispatchEvent(SCROLL, Dictionary());
+	DispatchEvent(EventId::Scroll, Dictionary());
 }
 
 // Gets the top scroll offset of the element.
@@ -1136,7 +1136,7 @@ void Element::SetScrollTop(float scroll_top)
 	scroll->UpdateScrollbar(ElementScroll::VERTICAL);
 	DirtyOffset();
 
-	DispatchEvent(SCROLL, Dictionary());
+	DispatchEvent(EventId::Scroll, Dictionary());
 }
 
 // Gets the width of the scrollable content of the element; it includes the element padding but not its margin.
@@ -1268,7 +1268,7 @@ void Element::SetInnerRML(const String& rml)
 bool Element::Focus()
 {
 	// Are we allowed focus?
-	int focus_property = GetProperty< int >(FOCUS_PROPERTY);
+	int focus_property = GetProperty< int >(PropertyId::Focus);
 	if (focus_property == FOCUS_NONE)
 		return false;
 
@@ -1356,8 +1356,8 @@ void Element::ScrollIntoView(bool align_with_top)
 	Element* scroll_parent = parent;
 	while (scroll_parent != NULL)
 	{
-		int overflow_x_property = scroll_parent->GetProperty< int >(OVERFLOW_X);
-		int overflow_y_property = scroll_parent->GetProperty< int >(OVERFLOW_Y);
+		int overflow_x_property = scroll_parent->GetProperty< int >(PropertyId::OverflowX);
+		int overflow_y_property = scroll_parent->GetProperty< int >(PropertyId::OverflowY);
 
 		if ((overflow_x_property != OVERFLOW_VISIBLE &&
 			 scroll_parent->GetScrollWidth() > scroll_parent->GetClientWidth()) ||
@@ -1642,12 +1642,12 @@ bool Element::IsClippingEnabled()
 	if (clipping_state_dirty)
 	{
 		// Is clipping enabled for this element, yes unless both overlow properties are set to visible
-		clipping_enabled = style->GetProperty(OVERFLOW_X)->Get< int >() != OVERFLOW_VISIBLE 
-							|| style->GetProperty(OVERFLOW_Y)->Get< int >() != OVERFLOW_VISIBLE;
+		clipping_enabled = style->GetProperty(PropertyId::OverflowX)->Get< int >() != OVERFLOW_VISIBLE
+							|| style->GetProperty(PropertyId::OverflowY)->Get< int >() != OVERFLOW_VISIBLE;
 		
 		// Get the clipping ignore depth from the clip property
 		clipping_ignore_depth = 0;
-		const Property* clip_property = GetProperty(CLIP);
+		const Property* clip_property = GetProperty(PropertyId::Clip);
 		if (clip_property->unit == Property::NUMBER)
 			clipping_ignore_depth = clip_property->Get< int >();
 		else if (clip_property->Get< int >() == CLIP_NONE)
@@ -1765,11 +1765,11 @@ void Element::OnPropertyChange(const PropertyIdList& changed_properties)
 	}
 
 	// Update the visibility.
-	if (all_dirty || changed_properties.find(VISIBILITY) != changed_properties.end() ||
-		changed_properties.find(DISPLAY) != changed_properties.end())
+	if (all_dirty || changed_properties.find(PropertyId::Visibility) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Display) != changed_properties.end())
 	{
 		bool new_visibility = GetDisplay() != DISPLAY_NONE &&
-							  GetProperty< int >(VISIBILITY) == VISIBILITY_VISIBLE;
+							  GetProperty< int >(PropertyId::Visibility) == VISIBILITY_VISIBLE;
 
 		if (visible != new_visibility)
 		{
@@ -1780,7 +1780,7 @@ void Element::OnPropertyChange(const PropertyIdList& changed_properties)
 		}
 
 		if (all_dirty || 
-			changed_properties.find(DISPLAY) != changed_properties.end())
+			changed_properties.find(PropertyId::Display) != changed_properties.end())
 		{
 			if (parent != NULL)
 				parent->DirtyStructure();
@@ -1789,11 +1789,11 @@ void Element::OnPropertyChange(const PropertyIdList& changed_properties)
 
 	// Fetch a new font face if it has been changed.
 	if (all_dirty ||
-		changed_properties.find(FONT_FAMILY) != changed_properties.end() ||
-		changed_properties.find(FONT_CHARSET) != changed_properties.end() ||
-		changed_properties.find(FONT_WEIGHT) != changed_properties.end() ||
-		changed_properties.find(FONT_STYLE) != changed_properties.end() ||
-		changed_properties.find(FONT_SIZE) != changed_properties.end())
+		changed_properties.find(PropertyId::FontFamily) != changed_properties.end() ||
+		changed_properties.find(PropertyId::FontCharset) != changed_properties.end() ||
+		changed_properties.find(PropertyId::FontWeight) != changed_properties.end() ||
+		changed_properties.find(PropertyId::FontStyle) != changed_properties.end() ||
+		changed_properties.find(PropertyId::FontSize) != changed_properties.end())
 	{
 		// Store the old em; if it changes, then we need to dirty all em-relative properties.
 		int old_em = -1;
@@ -1832,10 +1832,10 @@ void Element::OnPropertyChange(const PropertyIdList& changed_properties)
 
 	// Update the position.
 	if (all_dirty ||
-		changed_properties.find(LEFT) != changed_properties.end() ||
-		changed_properties.find(RIGHT) != changed_properties.end() ||
-		changed_properties.find(TOP) != changed_properties.end() ||
-		changed_properties.find(BOTTOM) != changed_properties.end())
+		changed_properties.find(PropertyId::Left) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Right) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Top) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Bottom) != changed_properties.end())
 	{
 		UpdateOffset();
 		DirtyOffset();
@@ -1843,9 +1843,9 @@ void Element::OnPropertyChange(const PropertyIdList& changed_properties)
 
 	// Update the z-index.
 	if (all_dirty || 
-		changed_properties.find(Z_INDEX) != changed_properties.end())
+		changed_properties.find(PropertyId::ZIndex) != changed_properties.end())
 	{
-		const Property* z_index_property = GetProperty(Z_INDEX);
+		const Property* z_index_property = GetProperty(PropertyId::ZIndex);
 
 		if (z_index_property->unit == Property::KEYWORD &&
 			z_index_property->value.Get< int >() == Z_INDEX_AUTO)
@@ -1898,57 +1898,57 @@ void Element::OnPropertyChange(const PropertyIdList& changed_properties)
 
 	// Dirty the background if it's changed.
     if (all_dirty ||
-        changed_properties.find(BACKGROUND_COLOR) != changed_properties.end() ||
-		changed_properties.find(OPACITY) != changed_properties.end() ||
-		changed_properties.find(IMAGE_COLOR) != changed_properties.end()) {
-        background->DirtyBackground();
-        decoration->ReloadDecorators();
-    }
+        changed_properties.find(PropertyId::BackgroundColor) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Opacity) != changed_properties.end() ||
+		changed_properties.find(PropertyId::ImageColor) != changed_properties.end()) {
+		background->DirtyBackground();
+		decoration->ReloadDecorators();
+	}
 
 	// Dirty the border if it's changed.
-	if (all_dirty || 
-		changed_properties.find(BORDER_TOP_WIDTH) != changed_properties.end() ||
-		changed_properties.find(BORDER_RIGHT_WIDTH) != changed_properties.end() ||
-		changed_properties.find(BORDER_BOTTOM_WIDTH) != changed_properties.end() ||
-		changed_properties.find(BORDER_LEFT_WIDTH) != changed_properties.end() ||
-		changed_properties.find(BORDER_TOP_COLOR) != changed_properties.end() ||
-		changed_properties.find(BORDER_RIGHT_COLOR) != changed_properties.end() ||
-		changed_properties.find(BORDER_BOTTOM_COLOR) != changed_properties.end() ||
-		changed_properties.find(BORDER_LEFT_COLOR) != changed_properties.end() ||
-		changed_properties.find(OPACITY) != changed_properties.end())
+	if (all_dirty ||
+		changed_properties.find(PropertyId::BorderTopWidth) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderRightWidth) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderBottomWidth) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderLeftWidth) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderTopColor) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderRightColor) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderBottomColor) != changed_properties.end() ||
+		changed_properties.find(PropertyId::BorderLeftColor) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Opacity) != changed_properties.end())
 		border->DirtyBorder();
 
 	
 	// Check for clipping state changes
 	if (all_dirty ||
-		changed_properties.find(CLIP) != changed_properties.end() ||
-		changed_properties.find(OVERFLOW_X) != changed_properties.end() ||
-		changed_properties.find(OVERFLOW_Y) != changed_properties.end())
+		changed_properties.find(PropertyId::Clip) != changed_properties.end() ||
+		changed_properties.find(PropertyId::OverflowX) != changed_properties.end() ||
+		changed_properties.find(PropertyId::OverflowY) != changed_properties.end())
 	{
 		clipping_state_dirty = true;
 	}
 
 	// Check for `perspective' and `perspective-origin' changes
 	if (all_dirty ||
-		changed_properties.find(PERSPECTIVE) != changed_properties.end() ||
-		changed_properties.find(PERSPECTIVE_ORIGIN_X) != changed_properties.end() ||
-		changed_properties.find(PERSPECTIVE_ORIGIN_Y) != changed_properties.end())
+		changed_properties.find(PropertyId::Perspective) != changed_properties.end() ||
+		changed_properties.find(PropertyId::PerspectiveOriginX) != changed_properties.end() ||
+		changed_properties.find(PropertyId::PerspectiveOriginY) != changed_properties.end())
 	{
 		DirtyTransformState(true, false, false);
 	}
 
 	// Check for `transform' and `transform-origin' changes
 	if (all_dirty ||
-		changed_properties.find(TRANSFORM) != changed_properties.end() ||
-		changed_properties.find(TRANSFORM_ORIGIN_X) != changed_properties.end() ||
-		changed_properties.find(TRANSFORM_ORIGIN_Y) != changed_properties.end() ||
-		changed_properties.find(TRANSFORM_ORIGIN_Z) != changed_properties.end())
+		changed_properties.find(PropertyId::Transform) != changed_properties.end() ||
+		changed_properties.find(PropertyId::TransformOriginX) != changed_properties.end() ||
+		changed_properties.find(PropertyId::TransformOriginY) != changed_properties.end() ||
+		changed_properties.find(PropertyId::TransformOriginZ) != changed_properties.end())
 	{
 		DirtyTransformState(false, true, false);
 	}
 
 	// Check for `animation' changes
-	if (all_dirty || changed_properties.find(ANIMATION) != changed_properties.end())
+	if (all_dirty || changed_properties.find(PropertyId::Animation) != changed_properties.end())
 	{
 		DirtyAnimation();
 	}
@@ -2037,15 +2037,15 @@ void Element::OnReferenceDeactivate()
 
 void Element::ProcessEvent(Event& event)
 {
-	if (event == MOUSEDOWN && IsPointWithinElement(Vector2f(event.GetParameter< float >("mouse_x", 0), event.GetParameter< float >("mouse_y", 0))) &&
+	if (event == EventId::Mousedown && IsPointWithinElement(Vector2f(event.GetParameter< float >("mouse_x", 0), event.GetParameter< float >("mouse_y", 0))) &&
 		event.GetParameter< int >("button", 0) == 0)
 		SetPseudoClass("active", true);
 
-	if (event == MOUSESCROLL)
+	if (event == EventId::Mousescroll)
 	{
 		if (GetScrollHeight() > GetClientHeight())
 		{
-			int overflow_property = GetProperty< int >(OVERFLOW_Y);
+			int overflow_property = GetProperty< int >(PropertyId::OverflowY);
 			if (overflow_property == OVERFLOW_AUTO ||
 				overflow_property == OVERFLOW_SCROLL)
 			{
@@ -2058,7 +2058,7 @@ void Element::ProcessEvent(Event& event)
 				if ((wheel_delta < 0 && GetScrollTop() > 0) ||
 					(wheel_delta > 0 && GetScrollHeight() > GetScrollTop() + GetClientHeight()))
 				{
-					SetScrollTop(GetScrollTop() + wheel_delta * (GetFontFaceHandle() ? ElementUtilities::GetLineHeight(this) : (GetProperty(SCROLL_DEFAULT_STEP_SIZE) ? GetProperty< int >(SCROLL_DEFAULT_STEP_SIZE) : 0)));
+					SetScrollTop(GetScrollTop() + wheel_delta * (GetFontFaceHandle() ? ElementUtilities::GetLineHeight(this) : (GetProperty(PropertyId::ScrollDefaultStepSize) ? GetProperty< int >(PropertyId::ScrollDefaultStepSize) : 0)));
 				}
 			}
 		}
@@ -2068,13 +2068,13 @@ void Element::ProcessEvent(Event& event)
 
 	if (event.GetTargetElement() == this)
 	{
-		if (event == MOUSEOVER)
+		if (event == EventId::Mouseover)
 			SetPseudoClass("hover", true);
-		else if (event == MOUSEOUT)
+		else if (event == EventId::Mouseout)
 			SetPseudoClass("hover", false);
-		else if (event == FOCUS)
+		else if (event == EventId::Focus)
 			SetPseudoClass("focus", true);
-		else if (event == BLUR)
+		else if (event == EventId::Blur)
 			SetPseudoClass("focus", false);
 	}
 }
@@ -2178,27 +2178,27 @@ void Element::UpdateOffset()
 			const Box& parent_box = offset_parent->GetBox();
 			Vector2f containing_block = parent_box.GetSize(Box::PADDING);
 
-			const Property *left = GetLocalProperty(LEFT);
-			const Property *right = GetLocalProperty(RIGHT);
+			const Property *left = GetLocalProperty(PropertyId::Left);
+			const Property *right = GetLocalProperty(PropertyId::Right);
 			// If the element is anchored left, then the position is offset by that resolved value.
 			if (left != NULL && left->unit != Property::KEYWORD)
-				relative_offset_base.x = parent_box.GetEdge(Box::BORDER, Box::LEFT) + (ResolveProperty(LEFT, containing_block.x) + GetBox().GetEdge(Box::MARGIN, Box::LEFT));
+				relative_offset_base.x = parent_box.GetEdge(Box::BORDER, Box::LEFT) + (ResolveProperty(PropertyId::Left, containing_block.x) + GetBox().GetEdge(Box::MARGIN, Box::LEFT));
 			// If the element is anchored right, then the position is set first so the element's right-most edge
 			// (including margins) will render up against the containing box's right-most content edge, and then
 			// offset by the resolved value.
 			else if (right != NULL && right->unit != Property::KEYWORD)
-				relative_offset_base.x = containing_block.x + parent_box.GetEdge(Box::BORDER, Box::LEFT) - (ResolveProperty(RIGHT, containing_block.x) + GetBox().GetSize(Box::BORDER).x + GetBox().GetEdge(Box::MARGIN, Box::RIGHT));
+				relative_offset_base.x = containing_block.x + parent_box.GetEdge(Box::BORDER, Box::LEFT) - (ResolveProperty(PropertyId::Right, containing_block.x) + GetBox().GetSize(Box::BORDER).x + GetBox().GetEdge(Box::MARGIN, Box::RIGHT));
 
-			const Property *top = GetLocalProperty(TOP);
-			const Property *bottom = GetLocalProperty(BOTTOM);
+			const Property *top = GetLocalProperty(PropertyId::Top);
+			const Property *bottom = GetLocalProperty(PropertyId::Bottom);
 			// If the element is anchored top, then the position is offset by that resolved value.
 			if (top != NULL && top->unit != Property::KEYWORD)
-				relative_offset_base.y = parent_box.GetEdge(Box::BORDER, Box::TOP) + (ResolveProperty(TOP, containing_block.y) + GetBox().GetEdge(Box::MARGIN, Box::TOP));
+				relative_offset_base.y = parent_box.GetEdge(Box::BORDER, Box::TOP) + (ResolveProperty(PropertyId::Top, containing_block.y) + GetBox().GetEdge(Box::MARGIN, Box::TOP));
 			// If the element is anchored bottom, then the position is set first so the element's right-most edge
 			// (including margins) will render up against the containing box's right-most content edge, and then
 			// offset by the resolved value.
 			else if (bottom != NULL && bottom->unit != Property::KEYWORD)
-				relative_offset_base.y = containing_block.y + parent_box.GetEdge(Box::BORDER, Box::TOP) - (ResolveProperty(BOTTOM, containing_block.y) + GetBox().GetSize(Box::BORDER).y + GetBox().GetEdge(Box::MARGIN, Box::BOTTOM));
+				relative_offset_base.y = containing_block.y + parent_box.GetEdge(Box::BORDER, Box::TOP) - (ResolveProperty(PropertyId::Bottom, containing_block.y) + GetBox().GetSize(Box::BORDER).y + GetBox().GetEdge(Box::MARGIN, Box::BOTTOM));
 		}
 	}
 	else if (position_property == POSITION_RELATIVE)
@@ -2208,21 +2208,21 @@ void Element::UpdateOffset()
 			const Box& parent_box = offset_parent->GetBox();
 			Vector2f containing_block = parent_box.GetSize();
 
-			const Property *left = GetLocalProperty(LEFT);
-			const Property *right = GetLocalProperty(RIGHT);
+			const Property *left = GetLocalProperty(PropertyId::Left);
+			const Property *right = GetLocalProperty(PropertyId::Right);
 			if (left != NULL && left->unit != Property::KEYWORD)
-				relative_offset_position.x = ResolveProperty(LEFT, containing_block.x);
+				relative_offset_position.x = ResolveProperty(PropertyId::Left, containing_block.x);
 			else if (right != NULL && right->unit != Property::KEYWORD)
-				relative_offset_position.x = -1 * ResolveProperty(RIGHT, containing_block.x);
+				relative_offset_position.x = -1 * ResolveProperty(PropertyId::Right, containing_block.x);
 			else
 				relative_offset_position.x = 0;
 
-			const Property *top = GetLocalProperty(TOP);
-			const Property *bottom = GetLocalProperty(BOTTOM);
+			const Property *top = GetLocalProperty(PropertyId::Top);
+			const Property *bottom = GetLocalProperty(PropertyId::Bottom);
 			if (top != NULL && top->unit != Property::KEYWORD)
-				relative_offset_position.y = ResolveProperty(TOP, containing_block.y);
+				relative_offset_position.y = ResolveProperty(PropertyId::Top, containing_block.y);
 			else if (bottom != NULL && bottom->unit != Property::KEYWORD)
-				relative_offset_position.y = -1 * ResolveProperty(BOTTOM, containing_block.y);
+				relative_offset_position.y = -1 * ResolveProperty(PropertyId::Bottom, containing_block.y);
 			else
 				relative_offset_position.y = 0;
 		}
@@ -2476,7 +2476,7 @@ void Element::UpdateAnimation()
 {
 	if (dirty_animation)
 	{
-		const Property* property = style->GetLocalProperty(ANIMATION);
+		const Property* property = style->GetLocalProperty(PropertyId::Animation);
 		StyleSheet* stylesheet = nullptr;
 
 		if (property && (stylesheet = GetStyleSheet()))
@@ -2549,7 +2549,7 @@ void Element::AdvanceAnimations()
 		animations.erase(it_completed, animations.end());
 
 		for (size_t i = 0; i < dictionary_list.size(); i++)
-			DispatchEvent(is_transition[i] ? TRANSITIONEND : ANIMATIONEND, dictionary_list[i]);
+			DispatchEvent(is_transition[i] ? EventId::Transitionend : EventId::Animationend, dictionary_list[i]);
 	}
 }
 

+ 8 - 8
Source/Core/ElementDefinition.cpp

@@ -110,10 +110,9 @@ void ElementDefinition::Initialise(const std::vector< const StyleSheetNode* >& s
 					continue;
 
 				// TODO: Pseudo-class should also probably be a PropertyId, for now we do a conversion to String here
-				const String& property_name = GetName(property_id);
-				PseudoClassPropertyDictionary::iterator l = pseudo_class_properties.find(property_name);
+				PseudoClassPropertyDictionary::iterator l = pseudo_class_properties.find(property_id);
 				if (l == pseudo_class_properties.end())
-					pseudo_class_properties[property_name] = PseudoClassPropertyList(1, PseudoClassProperty((*j).first, property));
+					pseudo_class_properties[property_id] = PseudoClassPropertyList(1, PseudoClassProperty((*j).first, property));
 				else
 				{
 					// Find the location to insert this entry in the map, based on property priorities.
@@ -163,7 +162,7 @@ void ElementDefinition::GetDefinedProperties(PropertyIdList& property_ids, const
 
 	for (PseudoClassPropertyDictionary::const_iterator i = pseudo_class_properties.begin(); i != pseudo_class_properties.end(); ++i)
 	{
-		PropertyId id = GetPropertyId((*i).first);
+		PropertyId id = i->first;
 
 		// If this property is already in the default dictionary, don't bother checking for it here.
 		if (property_ids.find(id) != property_ids.end())
@@ -194,7 +193,7 @@ void ElementDefinition::GetDefinedProperties(PropertyIdList& property_ids, const
 {
 	for (PseudoClassPropertyDictionary::const_iterator i = pseudo_class_properties.begin(); i != pseudo_class_properties.end(); ++i)
 	{
-		PropertyId id = GetPropertyId((*i).first);
+		PropertyId id = i->first;
 
 		// If this property has already been found, don't bother checking for it again.
 		if (property_ids.find(id) != property_ids.end())
@@ -358,7 +357,7 @@ void ElementDefinition::BuildPropertyGroup(PropertyGroupMap& groups, const Strin
 
 	for (PropertyMap::const_iterator property_iterator = element_properties.begin(); property_iterator != element_properties.end(); ++property_iterator)
 	{
-		const String& property_name = (*property_iterator).first;
+		const String& property_name = GetName((*property_iterator).first);
 		if (property_name.size() > property_suffix.size() &&
 			strcasecmp(property_name.c_str() + (property_name.size() - property_suffix.size()), property_suffix.c_str()) == 0)
 		{
@@ -427,7 +426,8 @@ int ElementDefinition::BuildPropertyGroupDictionary(PropertyDictionary& group_pr
 
 	for (PropertyMap::const_iterator property_iterator = element_properties.begin(); property_iterator != element_properties.end(); ++property_iterator)
 	{
-		const String& full_property_name = (*property_iterator).first;
+		PropertyId id = (*property_iterator).first;
+		const String& full_property_name = GetName(id);
 		if (full_property_name.size() > group_name.size() + 1 &&
 			strncasecmp(full_property_name.c_str(), group_name.c_str(), group_name.size()) == 0 &&
 			full_property_name[group_name.size()] == '-')
@@ -436,7 +436,7 @@ int ElementDefinition::BuildPropertyGroupDictionary(PropertyDictionary& group_pr
 //			if (property_name == group_type)
 //				continue;
 
-			group_properties[property_name] = (*property_iterator).second;
+			group_properties[id] = (*property_iterator).second;
 			num_properties++;
 		}
 	}

+ 1 - 1
Source/Core/ElementDefinition.h

@@ -48,7 +48,7 @@ class FontEffect;
 //TODO Replace with property IDs
 typedef std::pair< StringList, Property > PseudoClassProperty;
 typedef std::vector< PseudoClassProperty > PseudoClassPropertyList;
-typedef UnorderedMap< String, PseudoClassPropertyList > PseudoClassPropertyDictionary;
+typedef UnorderedMap< PropertyId, PseudoClassPropertyList > PseudoClassPropertyDictionary;
 
 typedef UnorderedMap< String, Decorator* > DecoratorMap;
 typedef std::map< StringList, DecoratorMap > PseudoClassDecoratorMap;

+ 24 - 24
Source/Core/ElementDocument.cpp

@@ -53,7 +53,7 @@ ElementDocument::ElementDocument(const String& tag) : Element(tag)
 
 	ForceLocalStackingContext();
 
-	SetProperty(POSITION, "absolute");
+	SetProperty(PropertyId::Position, "absolute");
 }
 
 ElementDocument::~ElementDocument()
@@ -148,7 +148,7 @@ void ElementDocument::ProcessHeader(const DocumentHeader* document_header)
 	}
 
 	// Hide this document.
-	SetProperty(VISIBILITY, "hidden");
+	SetProperty(PropertyId::Visibility, "hidden");
 }
 
 ElementDocument* ElementDocument::GetOwnerDocument()
@@ -223,7 +223,7 @@ void ElementDocument::Show(int focus_flags)
 	modal = (focus_flags & MODAL) > 0;
 
 	// Set to visible and switch focus if necessary
-	SetProperty(VISIBILITY, "visible");
+	SetProperty(PropertyId::Visibility, "visible");
 	if (focus_flags & FOCUS || focus_flags & MODAL)
 	{
 		// If no element could be focused, focus the window
@@ -233,13 +233,13 @@ void ElementDocument::Show(int focus_flags)
 		}
 	}
 
-	DispatchEvent("show", Dictionary(), false);
+	DispatchEvent(EventId::Show, Dictionary(), false);
 }
 
 void ElementDocument::Hide()
 {
-	SetProperty(VISIBILITY, "hidden");
-	DispatchEvent("hide", Dictionary(), false);
+	SetProperty(PropertyId::Visibility, "hidden");
+	DispatchEvent(EventId::Hide, Dictionary(), false);
 	
 	if (context)
 	{
@@ -338,21 +338,21 @@ void ElementDocument::UpdatePosition()
 	// Work out our containing block; relative offsets are calculated against it.
 	Vector2f containing_block = GetParentNode()->GetBox().GetSize(Box::CONTENT);
 
-	const Property *left = GetLocalProperty(LEFT);
-	const Property *right = GetLocalProperty(RIGHT);
+	const Property *left = GetLocalProperty(PropertyId::Left);
+	const Property *right = GetLocalProperty(PropertyId::Right);
 	if (left != NULL && left->unit != Property::KEYWORD)
-		position.x = ResolveProperty(LEFT, containing_block.x);
+		position.x = ResolveProperty(PropertyId::Left, containing_block.x);
 	else if (right != NULL && right->unit != Property::KEYWORD)
-		position.x = (containing_block.x - GetBox().GetSize(Box::MARGIN).x) - ResolveProperty(RIGHT, containing_block.x);
+		position.x = (containing_block.x - GetBox().GetSize(Box::MARGIN).x) - ResolveProperty(PropertyId::Right, containing_block.x);
 	else
 		position.x = GetBox().GetEdge(Box::MARGIN, Box::LEFT);
 
-	const Property *top = GetLocalProperty(TOP);
-	const Property *bottom = GetLocalProperty(BOTTOM);
+	const Property *top = GetLocalProperty(PropertyId::Top);
+	const Property *bottom = GetLocalProperty(PropertyId::Bottom);
 	if (top != NULL && top->unit != Property::KEYWORD)
-		position.y = ResolveProperty(TOP, containing_block.y);
+		position.y = ResolveProperty(PropertyId::Top, containing_block.y);
 	else if (bottom != NULL && bottom->unit != Property::KEYWORD)
-		position.y = (containing_block.y - GetBox().GetSize(Box::MARGIN).y) - ResolveProperty(BOTTOM, containing_block.y);
+		position.y = (containing_block.y - GetBox().GetSize(Box::MARGIN).y) - ResolveProperty(PropertyId::Bottom, containing_block.y);
 	else
 		position.y = GetBox().GetEdge(Box::MARGIN, Box::TOP);
 
@@ -385,18 +385,18 @@ void ElementDocument::DirtyDpProperties()
 }
 
 // Repositions the document if necessary.
-void ElementDocument::OnPropertyChange(const PropertyNameList& changed_properties)
+void ElementDocument::OnPropertyChange(const PropertyIdList& changed_properties)
 {
 	Element::OnPropertyChange(changed_properties);
 
 	// If the document's font-size has been changed, we need to dirty all rem properties.
-	if (changed_properties.find(FONT_SIZE) != changed_properties.end())
+	if (changed_properties.find(PropertyId::FontSize) != changed_properties.end())
 		GetStyle()->DirtyRemProperties();
 
-	if (changed_properties.find(TOP) != changed_properties.end() ||
-		changed_properties.find(RIGHT) != changed_properties.end() ||
-		changed_properties.find(BOTTOM) != changed_properties.end() ||
-		changed_properties.find(LEFT) != changed_properties.end())
+	if (changed_properties.find(PropertyId::Top) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Right) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Bottom) != changed_properties.end() ||
+		changed_properties.find(PropertyId::Left) != changed_properties.end())
 		UpdatePosition();
 }
 
@@ -406,7 +406,7 @@ void ElementDocument::ProcessEvent(Event& event)
 	Element::ProcessEvent(event);
 
 	// Process generic keyboard events for this window in capture phase
-	if (event.GetPhase() == Event::PHASE_BUBBLE && event == KEYDOWN)
+	if (event.GetPhase() == Event::PHASE_BUBBLE && event == EventId::Keydown)
 	{
 		int key_identifier = event.GetParameter<int>("key_identifier", Input::KI_UNKNOWN);
 
@@ -421,7 +421,7 @@ void ElementDocument::ProcessEvent(Event& event)
 		{
 			Element* focus_node = GetFocusLeafNode();
 
-			if (focus_node && focus_node->GetProperty<int>(TAB_INDEX) == TAB_INDEX_AUTO)
+			if (focus_node && focus_node->GetProperty<int>(PropertyId::TabIndex) == TAB_INDEX_AUTO)
 			{
 				focus_node->Click();
 			}
@@ -429,7 +429,7 @@ void ElementDocument::ProcessEvent(Event& event)
 	}
 	else if (event.GetTargetElement() == this)
 	{
-		if (event == RESIZE)
+		if (event == EventId::Resize)
 			UpdatePosition();
 	}
 }
@@ -506,7 +506,7 @@ bool ElementDocument::SearchFocusSubtree(Element* element, bool forward)
 	}
 
 	// Check if this is the node we're looking for
-	if (element->GetProperty<int>(TAB_INDEX) == TAB_INDEX_AUTO)
+	if (element->GetProperty<int>(PropertyId::TabIndex) == TAB_INDEX_AUTO)
 	{
 		element->Focus();
 		element->ScrollIntoView(false);

+ 12 - 12
Source/Core/ElementHandle.cpp

@@ -38,7 +38,7 @@ namespace Core {
 ElementHandle::ElementHandle(const String& tag) : Element(tag), drag_start(0, 0)
 {
 	// Make sure we can be dragged!
-	SetProperty(DRAG, DRAG);
+	SetProperty(PropertyId::Drag, "drag");
 
 	move_target = NULL;
 	size_target = NULL;
@@ -83,7 +83,7 @@ void ElementHandle::ProcessEvent(Event& event)
 			initialised = true;
 		}
 
-		if (event == DRAGSTART)
+		if (event == EventId::Dragstart)
 		{
 			// Store the drag starting position
 			drag_start.x = event.GetParameter< int >("mouse_x", 0);
@@ -98,7 +98,7 @@ void ElementHandle::ProcessEvent(Event& event)
 			if (size_target)
 				size_original_size = size_target->GetBox().GetSize(Box::CONTENT);
 		}
-		else if (event == DRAG)
+		else if (event == EventId::Drag)
 		{
 			// Work out the delta
 			int x = event.GetParameter< int >("mouse_x", 0) - drag_start.x;
@@ -107,8 +107,8 @@ void ElementHandle::ProcessEvent(Event& event)
 			// Update the move and size objects
 			if (move_target)
 			{
-				move_target->SetProperty(LEFT, Property(Math::RealToInteger(move_original_position.x + x), Property::PX));
-				move_target->SetProperty(TOP, Property(Math::RealToInteger(move_original_position.y + y), Property::PX));
+				move_target->SetProperty(PropertyId::Left, Property(Math::RealToInteger(move_original_position.x + x), Property::PX));
+				move_target->SetProperty(PropertyId::Top, Property(Math::RealToInteger(move_original_position.y + y), Property::PX));
 			}
 
 			if (size_target)
@@ -118,25 +118,25 @@ void ElementHandle::ProcessEvent(Event& event)
 
 				// Check if we have auto-margins; if so, they have to be set to the current margins.
 				if (margin_top->unit == Property::KEYWORD)
-					size_target->SetProperty(MARGIN_TOP, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::TOP)), Property::PX));
+					size_target->SetProperty(PropertyId::MarginTop, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::TOP)), Property::PX));
 				if (margin_right->unit == Property::KEYWORD)
-					size_target->SetProperty(MARGIN_RIGHT, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::RIGHT)), Property::PX));
+					size_target->SetProperty(PropertyId::MarginRight, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::RIGHT)), Property::PX));
 				if (margin_bottom->unit == Property::KEYWORD)
-					size_target->SetProperty(MARGIN_BOTTOM, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::BOTTOM)), Property::PX));
+					size_target->SetProperty(PropertyId::MarginBottom, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::BOTTOM)), Property::PX));
 				if (margin_left->unit == Property::KEYWORD)
-					size_target->SetProperty(MARGIN_LEFT, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::LEFT)), Property::PX));
+					size_target->SetProperty(PropertyId::MarginLeft, Property((float) Math::RealToInteger(size_target->GetBox().GetEdge(Box::MARGIN, Box::LEFT)), Property::PX));
 
 				int new_x = Math::RealToInteger(size_original_size.x + x);
 				int new_y = Math::RealToInteger(size_original_size.y + y);
 
-				size_target->SetProperty(WIDTH, Property(Math::Max< float >((float) new_x, 0), Property::PX));
-				size_target->SetProperty(HEIGHT, Property(Math::Max< float >((float) new_y, 0), Property::PX));
+				size_target->SetProperty(PropertyId::Width, Property(Math::Max< float >((float) new_x, 0), Property::PX));
+				size_target->SetProperty(PropertyId::Height, Property(Math::Max< float >((float) new_y, 0), Property::PX));
 			}
 
 			Dictionary parameters;
 			parameters["handle_x"] = x;
 			parameters["handle_y"] = y;
-			DispatchEvent("handledrag", parameters);
+			DispatchEvent(EventId::Handledrag, parameters);
 		}
 	}
 }

+ 17 - 17
Source/Core/ElementStyle.cpp

@@ -136,7 +136,7 @@ void ElementStyle::TransitionPropertyChanges(Element* element, PropertyIdList& p
 	if (!old_definition || !new_definition || properties.empty())
 		return;
 
-	if (const Property* transition_property = GetLocalProperty(TRANSITION, local_properties, new_definition, pseudo_classes_after))
+	if (const Property* transition_property = GetLocalProperty(PropertyId::Transition, local_properties, new_definition, pseudo_classes_after))
 	{
 		auto transition_list = transition_property->Get<TransitionList>();
 
@@ -479,7 +479,7 @@ float ElementStyle::ResolveAngle(const Property * property)
 
 float ElementStyle::ResolveNumericProperty(PropertyId property_id, const Property * property)
 {
-	if ((property->unit & Property::LENGTH) && !(property->unit == Property::EM && property_id == FONT_SIZE))
+	if ((property->unit & Property::LENGTH) && !(property->unit == Property::EM && property_id == PropertyId::FontSize))
 	{
 		return ResolveLength(property);
 	}
@@ -609,7 +609,7 @@ float ElementStyle::ResolveProperty(PropertyId property_id, float base_value)
 
 	// The calculated value of the font-size property is inherited, so we need to check if this
 	// is an inherited property. If so, then we return our parent's font size instead.
-	if (property_id == FONT_SIZE && property->unit & Property::RELATIVE_UNIT)
+	if (property_id == PropertyId::FontSize && property->unit & Property::RELATIVE_UNIT)
 	{
 		// If the rem unit is used, the font-size is inherited directly from the document,
 		// otherwise we use the parent's font size.
@@ -619,7 +619,7 @@ float ElementStyle::ResolveProperty(PropertyId property_id, float base_value)
 			if (owner_document == NULL)
 				return 0;
 
-			base_value = element->GetOwnerDocument()->ResolveProperty(FONT_SIZE, 0);
+			base_value = element->GetOwnerDocument()->ResolveProperty(PropertyId::FontSize, 0);
 		}
 		else
 		{
@@ -627,11 +627,11 @@ float ElementStyle::ResolveProperty(PropertyId property_id, float base_value)
 			if (parent == NULL)
 				return 0;
 
-			if (GetLocalProperty(FONT_SIZE) == NULL)
-				return parent->ResolveProperty(FONT_SIZE, 0);
+			if (GetLocalProperty(PropertyId::FontSize) == NULL)
+				return parent->ResolveProperty(PropertyId::FontSize, 0);
 
 			// The base value for font size is always the height of *this* element's parent's font.
-			base_value = parent->ResolveProperty(FONT_SIZE, 0);
+			base_value = parent->ResolveProperty(PropertyId::FontSize, 0);
 		}
 
 		switch (property->unit)
@@ -738,7 +738,7 @@ void ElementStyle::DirtyEmProperties()
 		for (auto& property : StyleSheetSpecification::GetRegisteredProperties())
 		{
 			// Skip font-size; this is relative to our parent's em, not ours.
-			if (property == FONT_SIZE)
+			if (property == PropertyId::FontSize)
 				continue;
 
 			// Get this property from this element. If this is em-relative, then add it to the list to
@@ -760,7 +760,7 @@ void ElementStyle::DirtyEmProperties()
 // Dirties font-size on child elements if appropriate.
 void ElementStyle::DirtyInheritedEmProperties()
 {
-	const Property* font_size = element->GetLocalProperty(FONT_SIZE);
+	const Property* font_size = element->GetLocalProperty(PropertyId::FontSize);
 	if (font_size == NULL)
 	{
 		int num_children = element->GetNumChildren(true);
@@ -770,7 +770,7 @@ void ElementStyle::DirtyInheritedEmProperties()
 	else
 	{
 		if (font_size->unit & Property::RELATIVE_UNIT)
-			DirtyProperty(FONT_SIZE);
+			DirtyProperty(PropertyId::FontSize);
 	}
 }
 
@@ -999,43 +999,43 @@ const Property *ElementStyle::GetVerticalAlignProperty()
 // Returns 'perspective' property value from element's style or local cache.
 const Property *ElementStyle::GetPerspective()
 {
-	return element->GetProperty(PERSPECTIVE);
+	return element->GetProperty(PropertyId::Perspective);
 }
 
 // Returns 'perspective-origin-x' property value from element's style or local cache.
 const Property *ElementStyle::GetPerspectiveOriginX()
 {
-	return element->GetProperty(PERSPECTIVE_ORIGIN_X);
+	return element->GetProperty(PropertyId::PerspectiveOriginX);
 }
 
 // Returns 'perspective-origin-y' property value from element's style or local cache.
 const Property *ElementStyle::GetPerspectiveOriginY()
 {
-	return element->GetProperty(PERSPECTIVE_ORIGIN_Y);
+	return element->GetProperty(PropertyId::PerspectiveOriginY);
 }
 
 // Returns 'transform' property value from element's style or local cache.
 const Property *ElementStyle::GetTransform()
 {
-	return element->GetProperty(TRANSFORM);
+	return element->GetProperty(PropertyId::Transform);
 }
 
 // Returns 'transform-origin-x' property value from element's style or local cache.
 const Property *ElementStyle::GetTransformOriginX()
 {
-	return element->GetProperty(TRANSFORM_ORIGIN_X);
+	return element->GetProperty(PropertyId::TransformOriginX);
 }
 
 // Returns 'transform-origin-y' property value from element's style or local cache.
 const Property *ElementStyle::GetTransformOriginY()
 {
-	return element->GetProperty(TRANSFORM_ORIGIN_Y);
+	return element->GetProperty(PropertyId::TransformOriginY);
 }
 
 // Returns 'transform-origin-z' property value from element's style or local cache.
 const Property *ElementStyle::GetTransformOriginZ()
 {
-	return element->GetProperty(TRANSFORM_ORIGIN_Z);
+	return element->GetProperty(PropertyId::TransformOriginZ);
 }
 
 }

+ 1 - 1
Source/Core/ElementTextDefault.cpp

@@ -279,7 +279,7 @@ void ElementTextDefault::SuppressAutoLayout()
 	dirty_layout_on_change = false;
 }
 
-void ElementTextDefault::OnPropertyChange(const PropertyNameList& changed_properties)
+void ElementTextDefault::OnPropertyChange(const PropertyIdList& changed_properties)
 {
 	Element::OnPropertyChange(changed_properties);
 

+ 1 - 1
Source/Core/ElementTextDefault.h

@@ -77,7 +77,7 @@ public:
 	virtual void SuppressAutoLayout();
 
 protected:
-	virtual void OnPropertyChange(const PropertyNameList& properties);
+	virtual void OnPropertyChange(const PropertyIdList& properties) override;
 
 	/// Returns the RML of this element
 	/// @param content[out] The raw text.

+ 32 - 2
Source/Core/PropertyDictionary.cpp

@@ -28,10 +28,40 @@
 #include "precompiled.h"
 #include "../../Include/Rocket/Core/PropertyDictionary.h"
 
-#if 0
 namespace Rocket {
 namespace Core {
 
+
+// Sets a property on the dictionary and its specificity if there is no name conflict, or its
+// specificity (given by the parameter, not read from the property itself) is at least equal to
+// the specificity of the conflicting property.
+static inline void SetProperty(PropertyDictionary& properties, PropertyId id, const Property& property, int specificity)
+{
+	PropertyMap::iterator iterator = properties.find(id);
+	if (iterator != properties.end() &&
+		iterator->second.specificity > specificity)
+		return;
+
+	Property & new_property = (properties[id] = property);
+	new_property.specificity = specificity;
+}
+
+void Merge(PropertyDictionary& destination, const PropertyDictionary& from, int specificity_offset)
+{
+	for (const auto& [id, property] : from)
+	{
+		SetProperty(destination, id, property, property.specificity + specificity_offset);
+	}
+}
+void Import(PropertyDictionary& destination, const PropertyDictionary& from, int specificity)
+{
+	for (const auto& [id, property] : from)
+	{
+		SetProperty(destination, id, property, specificity > 0 ? specificity : property.specificity);
+	}
+}
+
+#if 0
 PropertyDictionary::PropertyDictionary()
 {
 }
@@ -105,7 +135,7 @@ void PropertyDictionary::SetProperty(const String& name, const Rocket::Core::Pro
 	Property& new_property = (properties[name] = property);
 	new_property.specificity = specificity;
 }
+#endif
 }
 }
 
-#endif

+ 234 - 164
Source/Core/StringCache.cpp

@@ -31,187 +31,257 @@
 namespace Rocket {
 namespace Core {
 
-static std::vector<String> PropertyNameMap;
-static UnorderedMap<String, PropertyId> PropertyReverseMap;
 
-PropertyId GetPropertyId(const String& property_name)
-{
-	if (auto it = PropertyReverseMap.find(ToLower(property_name)); it != PropertyReverseMap.end())
-		return it->second;
-	return InvalidPropertyId;
-}
 
-const String& GetName(PropertyId property_id)
-{
-	if (static_cast<size_t>(property_id) < PropertyNameMap.size())
-		return PropertyNameMap[static_cast<size_t>(property_id)];
-	return PropertyNameMap[0];
-}
+template <typename ID>
+class IdNameMap {
 
-PropertyId AddPropertyName(const String & name)
-{
-	//ROCKET_ASSERT(ToLower(name) == name);
-	String lower = ToLower(name);
-	if (PropertyNameMap.empty())
+	static std::vector<String> name_map;  // IDs are indices into the NameMap
+	static UnorderedMap<String, ID> reverse_map;
+
+protected:
+	IdNameMap(ID id_num_to_initialize) {
+		name_map.resize((size_t)id_num_to_initialize);
+		reverse_map.reserve((size_t)id_num_to_initialize);
+	}
+
+	void add(ID id, const String& name) {
+		name_map[(size_t)id] = name;
+		reverse_map.emplace(name, id);
+	}
+
+	void assert_all_inserted(ID id_num_to_initialize) const {
+		ROCKET_ASSERT(name_map.size() == (size_t)id_num_to_initialize && reverse_map.size() == (size_t)id_num_to_initialize);
+	}
+
+public:
+	ID GetId(const String& name)
 	{
-		PropertyReverseMap.reserve(200);
-		PropertyNameMap.reserve(200);
-		PropertyNameMap.push_back("invalid_property");
+		if (auto it = reverse_map.find(ToLower(name)); it != reverse_map.end())
+			return it->second;
+		return ID::Invalid;
 	}
-	// Only insert if not already in list
-	PropertyId next_id = static_cast<PropertyId>(PropertyNameMap.size());
-	auto [it, inserted] = PropertyReverseMap.emplace(lower, next_id);
-	if (inserted)
-		PropertyNameMap.push_back(lower);
-
-	// Return the property id that already existed, or the new one if inserted
-	return it->second;
-}
+	const String& GetName(ID id)
+	{
+		if (static_cast<size_t>(id) < name_map.size())
+			return name_map[static_cast<size_t>(id)];
+		return name_map[static_cast<size_t>(ID::Invalid)];
+	}
+	
+	ID CreateIdFromName(const String& name)
+	{
+		String lower = ToLower(name);
+		ID next_id = static_cast<ID>(name_map.size());
 
+		// Only insert if not already in list
+		auto [it, inserted] = reverse_map.emplace(lower, next_id);
+		if (inserted)
+			name_map.push_back(lower);
 
+		// Return the property id that already existed, or the new one if inserted
+		return it->second;
+	}
+};
 
-static std::vector<String> EventNameMap;
-static UnorderedMap<String, EventId> EventReverseMap;
+class PropertyIdNameMap : public IdNameMap<PropertyId>
+{
+public:
+	PropertyIdNameMap();
+};
 
-EventId GetEventId(const String& event_name)
+inline PropertyIdNameMap::PropertyIdNameMap() : IdNameMap(PropertyId::NumDefinedIds)
 {
-	if (auto it = EventReverseMap.find(ToLower(event_name)); it != EventReverseMap.end())
-		return it->second;
-	return InvalidEventId;
+	add(PropertyId::Invalid, "invalid_property");
+	add(PropertyId::MarginTop, "margin-top");
+	add(PropertyId::MarginRight, "margin-right");
+	add(PropertyId::MarginBottom, "margin-bottom");
+	add(PropertyId::MarginLeft, "margin-left");
+	add(PropertyId::Margin, "margin");
+	add(PropertyId::PaddingTop, "padding-top");
+	add(PropertyId::PaddingRight, "padding-right");
+	add(PropertyId::PaddingBottom, "padding-bottom");
+	add(PropertyId::PaddingLeft, "padding-left");
+	add(PropertyId::Padding, "padding");
+	add(PropertyId::BorderTopWidth, "border-top-width");
+	add(PropertyId::BorderRightWidth, "border-right-width");
+	add(PropertyId::BorderBottomWidth, "border-bottom-width");
+	add(PropertyId::BorderLeftWidth, "border-left-width");
+	add(PropertyId::BorderWidth, "border-width");
+	add(PropertyId::BorderTopColor, "border-top-color");
+	add(PropertyId::BorderRightColor, "border-right-color");
+	add(PropertyId::BorderBottomColor, "border-bottom-color");
+	add(PropertyId::BorderLeftColor, "border-left-color");
+	add(PropertyId::BorderColor, "border-color");
+	add(PropertyId::BorderTop, "border-top");
+	add(PropertyId::BorderRight, "border-right");
+	add(PropertyId::BorderBottom, "border-bottom");
+	add(PropertyId::BorderLeft, "border-left");
+	add(PropertyId::Border, "border");
+	add(PropertyId::Display, "display");
+	add(PropertyId::Position, "position");
+	add(PropertyId::Top, "top");
+	add(PropertyId::Right, "right");
+	add(PropertyId::Bottom, "bottom");
+	add(PropertyId::Left, "left");
+	add(PropertyId::Float, "float");
+	add(PropertyId::Clear, "clear");
+	add(PropertyId::ZIndex, "z-index");
+	add(PropertyId::Width, "width");
+	add(PropertyId::MinWidth, "min-width");
+	add(PropertyId::MaxWidth, "max-width");
+	add(PropertyId::Height, "height");
+	add(PropertyId::MinHeight, "min-height");
+	add(PropertyId::MaxHeight, "max-height");
+	add(PropertyId::LineHeight, "line-height");
+	add(PropertyId::VerticalAlign, "vertical-align");
+	add(PropertyId::Overflow, "overflow");
+	add(PropertyId::OverflowX, "overflow-x");
+	add(PropertyId::OverflowY, "overflow-y");
+	add(PropertyId::Clip, "clip");
+	add(PropertyId::Visibility, "visibility");
+	add(PropertyId::BackgroundColor, "background-color");
+	add(PropertyId::Background, "background");
+	add(PropertyId::Color, "color");
+	add(PropertyId::ImageColor, "image-color");
+	add(PropertyId::FontFamily, "font-family");
+	add(PropertyId::FontCharset, "font-charset");
+	add(PropertyId::FontStyle, "font-style");
+	add(PropertyId::FontWeight, "font-weight");
+	add(PropertyId::FontSize, "font-size");
+	add(PropertyId::Font, "font");
+	add(PropertyId::TextAlign, "text-align");
+	add(PropertyId::TextDecoration, "text-decoration");
+	add(PropertyId::TextTransform, "text-transform");
+	add(PropertyId::WhiteSpace, "white-space");
+	add(PropertyId::Cursor, "cursor");
+	add(PropertyId::Drag, "drag");
+	add(PropertyId::TabIndex, "tab-index");
+	add(PropertyId::ScrollbarMargin, "scrollbar-margin");
+	add(PropertyId::Perspective, "perspective");
+	add(PropertyId::PerspectiveOrigin, "perspective-origin");
+	add(PropertyId::PerspectiveOriginX, "perspective-origin-x");
+	add(PropertyId::PerspectiveOriginY, "perspective-origin-y");
+	add(PropertyId::Transform, "transform");
+	add(PropertyId::TransformOrigin, "transform-origin");
+	add(PropertyId::TransformOriginX, "transform-origin-x");
+	add(PropertyId::TransformOriginY, "transform-origin-y");
+	add(PropertyId::TransformOriginZ, "transform-origin-z");
+	add(PropertyId::None, "none");
+	add(PropertyId::All, "all");
+	add(PropertyId::Transition, "transition");
+	add(PropertyId::Animation, "animation");
+	add(PropertyId::Keyframes, "keyframes");
+	add(PropertyId::ScrollDefaultStepSize, "scroll-default-step-size");
+	add(PropertyId::Opacity, "opacity");
+	add(PropertyId::PointerEvents, "pointer-events");
+	add(PropertyId::Focus, "focus");
+
+	assert_all_inserted(PropertyId::NumDefinedIds);
 }
 
-const String& GetName(EventId property_id)
+
+class EventIdNameMap : public IdNameMap<EventId>
 {
-	if (static_cast<size_t>(property_id) < EventNameMap.size())
-		return EventNameMap[static_cast<size_t>(property_id)];
-	return EventNameMap[0];
-}
+public:
+	EventIdNameMap();
+};
 
-EventId AddEventName(const String & name)
+inline EventIdNameMap::EventIdNameMap() : IdNameMap(EventId::NumDefinedIds)
 {
-	ROCKET_ASSERT(ToLower(name) == name);
-	if (EventNameMap.empty())
-	{
-		EventNameMap.reserve(150);
-		EventNameMap.push_back("invalid_property");
-	}
-	EventId result = static_cast<EventId>(EventNameMap.size());
-	EventNameMap.push_back(name);
-	EventReverseMap[name] = result;
-	return result;
+	add(EventId::Invalid, "invalid_event");
+	add(EventId::Mousedown, "mousedown");
+	add(EventId::Mousescroll, "mousescroll");
+	add(EventId::Mouseover, "mouseover");
+	add(EventId::Mouseout, "mouseout");
+	add(EventId::Focus, "focus");
+	add(EventId::Blur, "blur");
+	add(EventId::Keydown, "keydown");
+	add(EventId::Mouseup, "mouseup");
+	add(EventId::Click, "click");
+	add(EventId::Load, "load");
+	add(EventId::Unload, "unload");
+	add(EventId::Show, "show");
+	add(EventId::Hide, "hide");
+	add(EventId::Keyup, "keyup");
+	add(EventId::Textinput, "textinput");
+	add(EventId::Mousemove, "mousemove");
+	add(EventId::Dragmove, "dragmove");
+	add(EventId::Dblclick, "dblclick");
+	add(EventId::Drag, "drag");
+	add(EventId::Dragstart, "dragstart");
+	add(EventId::Dragover, "dragover");
+	add(EventId::Dragdrop, "dragdrop");
+	add(EventId::Dragout, "dragout");
+	add(EventId::Dragend, "dragend");
+	add(EventId::Handledrag, "handledrag");
+	add(EventId::Resize, "resize");
+	add(EventId::Scroll, "scroll");
+	add(EventId::Animationend, "animationend");
+	add(EventId::Transitionend, "transitionend");
+
+	assert_all_inserted(EventId::NumDefinedIds);
+}
+
+static PropertyIdNameMap property_map;
+
+PropertyId GetPropertyId(const String& property_name) {
+	return property_map.GetId(property_name);
 }
+PropertyId CreateOrGetPropertyId(const String& name) {
+	return property_map.CreateIdFromName(name);
+}
+const String& GetName(PropertyId property_id) {
+	return property_map.GetName(property_id);
+}
+
+static EventIdNameMap event_map;
+
+EventId GetEventId(const String& event_name) {
+	return event_map.GetId(event_name);
+}
+EventId CreateOrGetEventId(const String& name) {
+	return event_map.CreateIdFromName(name);
+}
+const String& GetName(EventId event_id) {
+	return event_map.GetName(event_id);
+}
+
+//
+//class PseudoIdNameMap : public IdNameMap<PseudoId>
+//{
+//public:
+//	PseudoIdNameMap();
+//};
+//
+//inline PseudoIdNameMap::PseudoIdNameMap() : IdNameMap(PseudoId::NumDefinedIds)
+//{
+//	add(PseudoId::Invalid, "invalid_pseudo_class");
+//	add(PseudoId::Hover, "hover");
+//	add(PseudoId::Active, "active");
+//	add(PseudoId::Focus, "focus");
+//	add(PseudoId::Dragged, "dragged");
+//
+//	add(PseudoId::Disabled, "disabled");
+//	add(PseudoId::Selected, "selected");
+//	add(PseudoId::Checked, "checked");
+//
+//	assert_all_inserted(PseudoId::NumDefinedIds);
+//}
+//
+//
+//static PseudoIdNameMap pseudo_map;
+//
+//PseudoId GetPseudoId(const String& event_name) {
+//	return pseudo_map.GetId(event_name);
+//}
+//PseudoId GetOrCreatePseudoId(const String& name) {
+//	return pseudo_map.CreateIdFromName(name);
+//}
+//const String& GetName(PseudoId pseudo_id) {
+//	return pseudo_map.GetName(pseudo_id);
+//}
+
 
-const PropertyId MARGIN_TOP = AddPropertyName("margin-top");
-const PropertyId MARGIN_RIGHT = AddPropertyName("margin-right");
-const PropertyId MARGIN_BOTTOM = AddPropertyName("margin-bottom");
-const PropertyId MARGIN_LEFT = AddPropertyName("margin-left");
-const PropertyId MARGIN = AddPropertyName("margin");
-const PropertyId PADDING_TOP = AddPropertyName("padding-top");
-const PropertyId PADDING_RIGHT = AddPropertyName("padding-right");
-const PropertyId PADDING_BOTTOM = AddPropertyName("padding-bottom");
-const PropertyId PADDING_LEFT = AddPropertyName("padding-left");
-const PropertyId PADDING = AddPropertyName("padding");
-const PropertyId BORDER_TOP_WIDTH = AddPropertyName("border-top-width");
-const PropertyId BORDER_RIGHT_WIDTH = AddPropertyName("border-right-width");
-const PropertyId BORDER_BOTTOM_WIDTH = AddPropertyName("border-bottom-width");
-const PropertyId BORDER_LEFT_WIDTH = AddPropertyName("border-left-width");
-const PropertyId BORDER_WIDTH = AddPropertyName("border-width");
-const PropertyId BORDER_TOP_COLOR = AddPropertyName("border-top-color");
-const PropertyId BORDER_RIGHT_COLOR = AddPropertyName("border-right-color");
-const PropertyId BORDER_BOTTOM_COLOR = AddPropertyName("border-bottom-color");
-const PropertyId BORDER_LEFT_COLOR = AddPropertyName("border-left-color");
-const PropertyId BORDER_COLOR = AddPropertyName("border-color");
-const PropertyId BORDER_TOP = AddPropertyName("border-top");
-const PropertyId BORDER_RIGHT = AddPropertyName("border-right");
-const PropertyId BORDER_BOTTOM = AddPropertyName("border-bottom");
-const PropertyId BORDER_LEFT = AddPropertyName("border-left");
-const PropertyId BORDER = AddPropertyName("border");
-const PropertyId DISPLAY = AddPropertyName("display");
-const PropertyId POSITION = AddPropertyName("position");
-const PropertyId TOP = AddPropertyName("top");
-const PropertyId RIGHT = AddPropertyName("right");
-const PropertyId BOTTOM = AddPropertyName("bottom");
-const PropertyId LEFT = AddPropertyName("left");
-const PropertyId FLOAT = AddPropertyName("float");
-const PropertyId CLEAR = AddPropertyName("clear");
-const PropertyId Z_INDEX = AddPropertyName("z-index");
-const PropertyId WIDTH = AddPropertyName("width");
-const PropertyId MIN_WIDTH = AddPropertyName("min-width");
-const PropertyId MAX_WIDTH = AddPropertyName("max-width");
-const PropertyId HEIGHT = AddPropertyName("height");
-const PropertyId MIN_HEIGHT = AddPropertyName("min-height");
-const PropertyId MAX_HEIGHT = AddPropertyName("max-height");
-const PropertyId LINE_HEIGHT = AddPropertyName("line-height");
-const PropertyId VERTICAL_ALIGN = AddPropertyName("vertical-align");
-const PropertyId OVERFLOW_ = AddPropertyName("overflow");
-const PropertyId OVERFLOW_X = AddPropertyName("overflow-x");
-const PropertyId OVERFLOW_Y = AddPropertyName("overflow-y");
-const PropertyId CLIP = AddPropertyName("clip");
-const PropertyId VISIBILITY = AddPropertyName("visibility");
-const PropertyId BACKGROUND_COLOR = AddPropertyName("background-color");
-const PropertyId BACKGROUND = AddPropertyName("background");
-const PropertyId COLOR = AddPropertyName("color");
-const PropertyId IMAGE_COLOR = AddPropertyName("image-color");
-const PropertyId FONT_FAMILY = AddPropertyName("font-family");
-const PropertyId FONT_CHARSET = AddPropertyName("font-charset");
-const PropertyId FONT_STYLE = AddPropertyName("font-style");
-const PropertyId FONT_WEIGHT = AddPropertyName("font-weight");
-const PropertyId FONT_SIZE = AddPropertyName("font-size");
-const PropertyId FONT = AddPropertyName("font");
-const PropertyId TEXT_ALIGN = AddPropertyName("text-align");
-const PropertyId TEXT_DECORATION = AddPropertyName("text-decoration");
-const PropertyId TEXT_TRANSFORM = AddPropertyName("text-transform");
-const PropertyId WHITE_SPACE = AddPropertyName("white-space");
-const PropertyId CURSOR = AddPropertyName("cursor");
-const PropertyId DRAG_PROPERTY = AddPropertyName("drag");
-const PropertyId TAB_INDEX = AddPropertyName("tab-index");
-const PropertyId SCROLLBAR_MARGIN = AddPropertyName("scrollbar-margin");
-const PropertyId PERSPECTIVE = AddPropertyName("perspective");
-const PropertyId PERSPECTIVE_ORIGIN = AddPropertyName("perspective-origin");
-const PropertyId PERSPECTIVE_ORIGIN_X = AddPropertyName("perspective-origin-x");
-const PropertyId PERSPECTIVE_ORIGIN_Y = AddPropertyName("perspective-origin-y");
-const PropertyId TRANSFORM = AddPropertyName("transform");
-const PropertyId TRANSFORM_ORIGIN = AddPropertyName("transform-origin");
-const PropertyId TRANSFORM_ORIGIN_X = AddPropertyName("transform-origin-x");
-const PropertyId TRANSFORM_ORIGIN_Y = AddPropertyName("transform-origin-y");
-const PropertyId TRANSFORM_ORIGIN_Z = AddPropertyName("transform-origin-z");
-const PropertyId NONE = AddPropertyName("none");
-const PropertyId ALL = AddPropertyName("all");
-const PropertyId TRANSITION = AddPropertyName("transition");
-const PropertyId ANIMATION = AddPropertyName("animation");
-const PropertyId KEYFRAMES = AddPropertyName("keyframes");
-const PropertyId SCROLL_DEFAULT_STEP_SIZE = AddPropertyName("scroll-default-step-size");
-const PropertyId OPACITY = AddPropertyName("opacity");
-const PropertyId POINTER_EVENTS = AddPropertyName("pointer-events");
-const PropertyId FOCUS_PROPERTY = AddPropertyName("focus");
-
-
-const EventId MOUSEDOWN = AddEventName("mousedown");
-const EventId MOUSESCROLL = AddEventName("mousescroll");
-const EventId MOUSEOVER = AddEventName("mouseover");
-const EventId MOUSEOUT = AddEventName("mouseout");
-const EventId FOCUS = AddEventName("focus");
-const EventId BLUR = AddEventName("blur");
-const EventId KEYDOWN = AddEventName("keydown");
-const EventId MOUSEUP = AddEventName("mouseup");
-const EventId CLICK = AddEventName("click");
-const EventId DRAG = AddEventName("drag");
-const EventId DRAGSTART = AddEventName("dragstart");
-const EventId DRAGOVER = AddEventName("dragover");
-const EventId LOAD = AddEventName("load");
-const EventId UNLOAD = AddEventName("unload");
-const EventId KEYUP = AddEventName("keyup");
-const EventId TEXTINPUT = AddEventName("textinput");
-const EventId MOUSEMOVE = AddEventName("mousemove");
-const EventId DRAGMOVE = AddEventName("dragmove");
-const EventId DBLCLICK = AddEventName("dblclick");
-const EventId DRAGDROP = AddEventName("dragdrop");
-const EventId DRAGOUT = AddEventName("dragout");
-const EventId DRAGEND = AddEventName("dragend");
-const EventId RESIZE = AddEventName("resize");
-const EventId SCROLL = AddEventName("scroll");
-const EventId ANIMATIONEND = AddEventName("animationend");
-const EventId TRANSITIONEND = AddEventName("transitionend");
 
 }
 }

+ 163 - 120
Source/Core/StringCache.h

@@ -37,127 +37,170 @@ namespace Rocket {
 namespace Core {
 
 PropertyId GetPropertyId(const String& property_name);
+PropertyId CreateOrGetPropertyId(const String& name);
 const String& GetName(PropertyId property_id);
-PropertyId AddPropertyName(const String& name);
-
-extern const PropertyId MARGIN_TOP;
-extern const PropertyId MARGIN_RIGHT;
-extern const PropertyId MARGIN_BOTTOM;
-extern const PropertyId MARGIN_LEFT;
-extern const PropertyId MARGIN;
-extern const PropertyId PADDING_TOP;
-extern const PropertyId PADDING_RIGHT;
-extern const PropertyId PADDING_BOTTOM;
-extern const PropertyId PADDING_LEFT;
-extern const PropertyId PADDING;
-extern const PropertyId BORDER_TOP_WIDTH;
-extern const PropertyId BORDER_RIGHT_WIDTH;
-extern const PropertyId BORDER_BOTTOM_WIDTH;
-extern const PropertyId BORDER_LEFT_WIDTH;
-extern const PropertyId BORDER_WIDTH;
-extern const PropertyId BORDER_TOP_COLOR;
-extern const PropertyId BORDER_RIGHT_COLOR;
-extern const PropertyId BORDER_BOTTOM_COLOR;
-extern const PropertyId BORDER_LEFT_COLOR;
-extern const PropertyId BORDER_COLOR;
-extern const PropertyId BORDER_TOP;
-extern const PropertyId BORDER_RIGHT;
-extern const PropertyId BORDER_BOTTOM;
-extern const PropertyId BORDER_LEFT;
-extern const PropertyId BORDER;
-extern const PropertyId DISPLAY;
-extern const PropertyId POSITION;
-extern const PropertyId TOP;
-extern const PropertyId RIGHT;
-extern const PropertyId BOTTOM;
-extern const PropertyId LEFT;
-extern const PropertyId FLOAT;
-extern const PropertyId CLEAR;
-extern const PropertyId Z_INDEX;
-extern const PropertyId WIDTH;
-extern const PropertyId MIN_WIDTH;
-extern const PropertyId MAX_WIDTH;
-extern const PropertyId HEIGHT;
-extern const PropertyId MIN_HEIGHT;
-extern const PropertyId MAX_HEIGHT;
-extern const PropertyId LINE_HEIGHT;
-extern const PropertyId VERTICAL_ALIGN;
-extern const PropertyId OVERFLOW_;
-extern const PropertyId OVERFLOW_X;
-extern const PropertyId OVERFLOW_Y;
-extern const PropertyId CLIP;
-extern const PropertyId VISIBILITY;
-extern const PropertyId BACKGROUND_COLOR;
-extern const PropertyId BACKGROUND;
-extern const PropertyId COLOR;
-extern const PropertyId IMAGE_COLOR;
-extern const PropertyId FONT_FAMILY;
-extern const PropertyId FONT_CHARSET;
-extern const PropertyId FONT_STYLE;
-extern const PropertyId FONT_WEIGHT;
-extern const PropertyId FONT_SIZE;
-extern const PropertyId FONT;
-extern const PropertyId TEXT_ALIGN;
-extern const PropertyId TEXT_DECORATION;
-extern const PropertyId TEXT_TRANSFORM;
-extern const PropertyId WHITE_SPACE;
-extern const PropertyId CURSOR;
-extern const PropertyId DRAG_PROPERTY;
-extern const PropertyId TAB_INDEX;
-extern const PropertyId SCROLLBAR_MARGIN;
-
-extern const PropertyId PERSPECTIVE;
-extern const PropertyId PERSPECTIVE_ORIGIN;
-extern const PropertyId PERSPECTIVE_ORIGIN_X;
-extern const PropertyId PERSPECTIVE_ORIGIN_Y;
-extern const PropertyId TRANSFORM;
-extern const PropertyId TRANSFORM_ORIGIN;
-extern const PropertyId TRANSFORM_ORIGIN_X;
-extern const PropertyId TRANSFORM_ORIGIN_Y;
-extern const PropertyId TRANSFORM_ORIGIN_Z;
-extern const PropertyId NONE;
-extern const PropertyId ALL;
-
-extern const PropertyId TRANSITION;
-extern const PropertyId ANIMATION;
-extern const PropertyId KEYFRAMES;
-
-extern const PropertyId SCROLL_DEFAULT_STEP_SIZE;
-extern const PropertyId OPACITY;
-extern const PropertyId POINTER_EVENTS;
-extern const PropertyId FOCUS_PROPERTY; // String is "focus", but variable name made distinct from event
-
-
-EventId GetEventId(const String& property_name);
-const String& GetName(EventId event_id);
-EventId AddEventName(const String& name);
-
-extern const EventId MOUSEDOWN;
-extern const EventId MOUSESCROLL;
-extern const EventId MOUSEOVER;
-extern const EventId MOUSEOUT;
-extern const EventId FOCUS;
-extern const EventId BLUR;
-extern const EventId KEYDOWN;
-extern const EventId MOUSEUP;
-extern const EventId CLICK;
-extern const EventId DRAG;
-extern const EventId DRAGSTART;
-extern const EventId LOAD;
-extern const EventId UNLOAD;
-extern const EventId KEYUP;
-extern const EventId TEXTINPUT;
-extern const EventId MOUSEMOVE;
-extern const EventId DRAGMOVE;
-extern const EventId DBLCLICK;
-extern const EventId DRAGDROP;
-extern const EventId DRAGOUT;
-extern const EventId DRAGEND;
-extern const EventId DRAGOVER;
-extern const EventId RESIZE;
-extern const EventId SCROLL;
-extern const EventId ANIMATIONEND;
-extern const EventId TRANSITIONEND;
+
+EventId GetEventId(const String& event_name);
+EventId CreateOrGetEventId(const String& name);
+const String& GetName(EventId event_id); 
+
+
+
+enum class PropertyId : uint16_t 
+{
+	Invalid,
+
+	MarginTop,
+	MarginRight,
+	MarginBottom,
+	MarginLeft,
+	Margin,
+	PaddingTop,
+	PaddingRight,
+	PaddingBottom,
+	PaddingLeft,
+	Padding,
+	BorderTopWidth,
+	BorderRightWidth,
+	BorderBottomWidth,
+	BorderLeftWidth,
+	BorderWidth,
+	BorderTopColor,
+	BorderRightColor,
+	BorderBottomColor,
+	BorderLeftColor,
+	BorderColor,
+	BorderTop,
+	BorderRight,
+	BorderBottom,
+	BorderLeft,
+	Border,
+	Display,
+	Position,
+	Top,
+	Right,
+	Bottom,
+	Left,
+	Float,
+	Clear,
+	ZIndex,
+	Width,
+	MinWidth,
+	MaxWidth,
+	Height,
+	MinHeight,
+	MaxHeight,
+	LineHeight,
+	VerticalAlign,
+	Overflow,
+	OverflowX,
+	OverflowY,
+	Clip,
+	Visibility,
+	BackgroundColor,
+	Background,
+	Color,
+	ImageColor,
+	FontFamily,
+	FontCharset,
+	FontStyle,
+	FontWeight,
+	FontSize,
+	Font,
+	TextAlign,
+	TextDecoration,
+	TextTransform,
+	WhiteSpace,
+	Cursor,
+	Drag,
+	TabIndex,
+	ScrollbarMargin,
+
+	Perspective,
+	PerspectiveOrigin,
+	PerspectiveOriginX,
+	PerspectiveOriginY,
+	Transform,
+	TransformOrigin,
+	TransformOriginX,
+	TransformOriginY,
+	TransformOriginZ,
+	None,
+	All,
+
+	Transition,
+	Animation,
+	Keyframes,
+
+	ScrollDefaultStepSize,
+	Opacity,
+	PointerEvents,
+	Focus,
+
+	NumDefinedIds,
+	FirstCustomId = NumDefinedIds
+};
+
+
+enum class EventId : uint16_t 
+{
+	Invalid,
+
+	Mousedown,
+	Mousescroll,
+	Mouseover,
+	Mouseout,
+	Focus,
+	Blur,
+	Keydown,
+	Mouseup,
+	Click,
+	Load,
+	Unload,
+	Show,
+	Hide,
+	Keyup,
+	Textinput,
+	Mousemove,
+	Dragmove,
+	Dblclick,
+	Drag,
+	Dragstart,
+	Dragover,
+	Dragdrop,
+	Dragout,
+	Dragend,
+	Handledrag,
+	Resize,
+	Scroll,
+	Animationend,
+	Transitionend,
+
+	NumDefinedIds,
+	FirstCustomId = NumDefinedIds
+};
+
+// Edit: Actually, this might be too complicated due to structural pseudo class selectors
+//PseudoId GetPseudoId(const String& event_name);
+//PseudoId GetOrCreatePseudoId(const String& name);
+//const String& GetName(PseudoId pseudo_id);
+//enum class PseudoId : uint16_t
+//{
+//	Invalid,
+//
+//	Hover,
+//	Active,
+//	Focus,
+//	Dragged,
+//
+//	Disabled,
+//	Selected,
+//	Checked,
+//
+//	NumDefinedIds,
+//	FirstCustomId = NumDefinedIds
+//};
+
 
 }
 }

+ 8 - 11
Source/Core/StyleSheetNode.cpp

@@ -72,7 +72,7 @@ StyleSheetNode::~StyleSheetNode()
 // Writes the style sheet node (and all ancestors) into the stream.
 void StyleSheetNode::Write(Stream* stream)
 {
-	if (properties.GetNumProperties() > 0)
+	if (properties.size() > 0)
 	{
 		String rule;
 		StyleSheetNode* hierarchy = this;
@@ -110,12 +110,9 @@ void StyleSheetNode::Write(Stream* stream)
 		stream->Write(CreateString(1024, "%s /* specificity: %d */\n", StringUtilities::StripWhitespace(rule).c_str(), specificity));
 		stream->Write("{\n");
 
-		const Rocket::Core::PropertyMap& property_map = properties.GetProperties();
-		for (Rocket::Core::PropertyMap::const_iterator i = property_map.begin(); i != property_map.end(); ++i)
+		for (const auto& [id, property] : properties)
 		{
-			const String& name = i->first;
-			const Rocket::Core::Property& property = i->second;
-
+			const String& name = Rocket::Core::GetName(id);
 			stream->Write(CreateString(1024, "\t%s: %s; /* specificity: %d */\n", name.c_str(), property.value.Get< String >().c_str(), property.specificity));
 		}
 
@@ -166,7 +163,7 @@ void StyleSheetNode::BuildIndex(StyleSheet::NodeIndex& styled_index, StyleSheet:
 
 	// If we are a styled node (ie, have some style attributes attached), then we insert our closest parent tag node
 	// into the list of styled tag nodes.
-	if (properties.GetNumProperties() > 0)
+	if (properties.size() > 0)
 	{
 		StyleSheetNode* tag_node = this;
 		while (tag_node != NULL &&
@@ -206,14 +203,14 @@ int StyleSheetNode::GetSpecificity() const
 // properties.
 void StyleSheetNode::ImportProperties(const PropertyDictionary& _properties, int rule_specificity)
 {
-	properties.Import(_properties, specificity + rule_specificity);
+	Import(properties, _properties, specificity + rule_specificity);
 }
 
 // Merges properties from another node (ie, with potentially differing specificities) into the
 // node's properties.
 void StyleSheetNode::MergeProperties(const PropertyDictionary& _properties, int rule_specificity_offset)
 {
-	properties.Merge(_properties, rule_specificity_offset);
+	Merge(properties, _properties, specificity + rule_specificity_offset);
 }
 
 // Returns the node's default properties.
@@ -442,7 +439,7 @@ void StyleSheetNode::GetApplicableDescendants(std::vector< const StyleSheetNode*
 		break;
 	}
 
-	if (properties.GetNumProperties() > 0 ||
+	if (properties.size() > 0 ||
 		!children[PSEUDO_CLASS].empty())
 		applicable_nodes.push_back(this);
 
@@ -564,7 +561,7 @@ void StyleSheetNode::GetPseudoClassProperties(PseudoClassPropertyMap& pseudo_cla
 	StringList pseudo_classes(ancestor_pseudo_classes);
 	pseudo_classes.push_back(name);
 
-	if (properties.GetNumProperties() > 0)
+	if (properties.size() > 0)
 		pseudo_class_properties[pseudo_classes] = properties;
 
 	for (NodeMap::const_iterator i = children[PSEUDO_CLASS].begin(); i != children[PSEUDO_CLASS].end(); ++i)

+ 87 - 85
Source/Core/StyleSheetSpecification.cpp

@@ -159,132 +159,134 @@ void StyleSheetSpecification::RegisterDefaultProperties()
 {
 	// Style property specifications (ala RCSS).
 
-	RegisterProperty(MARGIN_TOP, "0px", false, true)
+	using Id = PropertyId;
+
+	RegisterProperty(Id::MarginTop, "0px", false, true)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(MARGIN_RIGHT, "0px", false, true)
+	RegisterProperty(Id::MarginRight, "0px", false, true)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(MARGIN_BOTTOM, "0px", false, true)
+	RegisterProperty(Id::MarginBottom, "0px", false, true)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(MARGIN_LEFT, "0px", false, true)
+	RegisterProperty(Id::MarginLeft, "0px", false, true)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterShorthand(MARGIN, { MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM, MARGIN_LEFT });
-
-	RegisterProperty(PADDING_TOP, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(PADDING_RIGHT, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(PADDING_BOTTOM, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(PADDING_LEFT, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterShorthand(PADDING, { PADDING_TOP, PADDING_RIGHT, PADDING_BOTTOM, PADDING_LEFT });
-
-	RegisterProperty(BORDER_TOP_WIDTH, "0px", false, true).AddParser("length");
-	RegisterProperty(BORDER_RIGHT_WIDTH, "0px", false, true).AddParser("length");
-	RegisterProperty(BORDER_BOTTOM_WIDTH, "0px", false, true).AddParser("length");
-	RegisterProperty(BORDER_LEFT_WIDTH, "0px", false, true).AddParser("length");
-	RegisterShorthand(BORDER_WIDTH, { BORDER_TOP_WIDTH, BORDER_RIGHT_WIDTH, BORDER_BOTTOM_WIDTH, BORDER_LEFT_WIDTH });
-
-	RegisterProperty(BORDER_TOP_COLOR, "black", false, false).AddParser("color");
-	RegisterProperty(BORDER_RIGHT_COLOR, "black", false, false).AddParser("color");
-	RegisterProperty(BORDER_BOTTOM_COLOR, "black", false, false).AddParser("color");
-	RegisterProperty(BORDER_LEFT_COLOR, "black", false, false).AddParser("color");
-	RegisterShorthand(BORDER_COLOR, { BORDER_TOP_COLOR, BORDER_RIGHT_COLOR, BORDER_BOTTOM_COLOR, BORDER_LEFT_COLOR });
-
-	RegisterShorthand(BORDER_TOP, { BORDER_TOP_WIDTH, BORDER_TOP_COLOR });
-	RegisterShorthand(BORDER_RIGHT, { BORDER_RIGHT_WIDTH, BORDER_RIGHT_COLOR });
-	RegisterShorthand(BORDER_BOTTOM, { BORDER_BOTTOM_WIDTH, BORDER_BOTTOM_COLOR });
-	RegisterShorthand(BORDER_LEFT, { BORDER_LEFT_WIDTH, BORDER_LEFT_COLOR });
-	RegisterShorthand(BORDER, { BORDER_TOP, BORDER_RIGHT, BORDER_BOTTOM, BORDER_LEFT }, PropertySpecification::RECURSIVE);
-
-	RegisterProperty(DISPLAY, "inline", false, true).AddParser("keyword", "none, block, inline, inline-block");
-	RegisterProperty(POSITION, "static", false, true).AddParser("keyword", "static, relative, absolute, fixed");
-	RegisterProperty(TOP, "auto", false, false)
+	RegisterShorthand(Id::Margin, { Id::MarginTop, Id::MarginRight, Id::MarginBottom, Id::MarginLeft });
+
+	RegisterProperty(Id::PaddingTop, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
+	RegisterProperty(Id::PaddingRight, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
+	RegisterProperty(Id::PaddingBottom, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
+	RegisterProperty(Id::PaddingLeft, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
+	RegisterShorthand(Id::Padding, { Id::PaddingTop, Id::PaddingRight, Id::PaddingBottom, Id::PaddingLeft });
+
+	RegisterProperty(Id::BorderTopWidth, "0px", false, true).AddParser("length");
+	RegisterProperty(Id::BorderRightWidth, "0px", false, true).AddParser("length");
+	RegisterProperty(Id::BorderBottomWidth, "0px", false, true).AddParser("length");
+	RegisterProperty(Id::BorderLeftWidth, "0px", false, true).AddParser("length");
+	RegisterShorthand(Id::BorderWidth, { Id::BorderTopWidth, Id::BorderRightWidth, Id::BorderBottomWidth, Id::BorderLeftWidth });
+
+	RegisterProperty(Id::BorderTopColor, "black", false, false).AddParser("color");
+	RegisterProperty(Id::BorderRightColor, "black", false, false).AddParser("color");
+	RegisterProperty(Id::BorderBottomColor, "black", false, false).AddParser("color");
+	RegisterProperty(Id::BorderLeftColor, "black", false, false).AddParser("color");
+	RegisterShorthand(Id::BorderColor, { Id::BorderTopColor, Id::BorderRightColor, Id::BorderBottomColor, Id::BorderLeftColor });
+
+	RegisterShorthand(Id::BorderTop, { Id::BorderTopWidth, Id::BorderTopColor });
+	RegisterShorthand(Id::BorderRight, { Id::BorderRightWidth, Id::BorderRightColor });
+	RegisterShorthand(Id::BorderBottom, { Id::BorderBottomWidth, Id::BorderBottomColor });
+	RegisterShorthand(Id::BorderLeft, { Id::BorderLeftWidth, Id::BorderLeftColor });
+	RegisterShorthand(Id::Border, { Id::BorderTop, Id::BorderRight, Id::BorderBottom, Id::BorderLeft }, PropertySpecification::RECURSIVE);
+
+	RegisterProperty(Id::Display, "inline", false, true).AddParser("keyword", "none, block, inline, inline-block");
+	RegisterProperty(Id::Position, "static", false, true).AddParser("keyword", "static, relative, absolute, fixed");
+	RegisterProperty(Id::Top, "auto", false, false)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
-	RegisterProperty(RIGHT, "auto", false, false)
+	RegisterProperty(Id::Right, "auto", false, false)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(BOTTOM, "auto", false, false)
+	RegisterProperty(Id::Bottom, "auto", false, false)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
-	RegisterProperty(LEFT, "auto", false, false)
+	RegisterProperty(Id::Left, "auto", false, false)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
 
-	RegisterProperty(FLOAT, "none", false, true).AddParser("keyword", "none, left, right");
-	RegisterProperty(CLEAR, "none", false, true).AddParser("keyword", "none, left, right, both");
+	RegisterProperty(Id::Float, "none", false, true).AddParser("keyword", "none, left, right");
+	RegisterProperty(Id::Clear, "none", false, true).AddParser("keyword", "none, left, right, both");
 
-	RegisterProperty(Z_INDEX, "auto", false, false)
+	RegisterProperty(Id::ZIndex, "auto", false, false)
 		.AddParser("keyword", "auto, top, bottom")
 		.AddParser("number");
 
-	RegisterProperty(WIDTH, "auto", false, true)
+	RegisterProperty(Id::Width, "auto", false, true)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(MIN_WIDTH, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
-	RegisterProperty(MAX_WIDTH, "-1px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
+	RegisterProperty(Id::MinWidth, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
+	RegisterProperty(Id::MaxWidth, "-1px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
 
-	RegisterProperty(HEIGHT, "auto", false, true)
+	RegisterProperty(Id::Height, "auto", false, true)
 		.AddParser("keyword", "auto")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
-	RegisterProperty(MIN_HEIGHT, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
-	RegisterProperty(MAX_HEIGHT, "-1px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
+	RegisterProperty(Id::MinHeight, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
+	RegisterProperty(Id::MaxHeight, "-1px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
 
-	RegisterProperty(LINE_HEIGHT, "1.2", true, true).AddParser("number_length_percent").SetRelativeTarget(RelativeTarget::FontSize);
-	RegisterProperty(VERTICAL_ALIGN, "baseline", false, true)
+	RegisterProperty(Id::LineHeight, "1.2", true, true).AddParser("number_length_percent").SetRelativeTarget(RelativeTarget::FontSize);
+	RegisterProperty(Id::VerticalAlign, "baseline", false, true)
 		.AddParser("keyword", "baseline, middle, sub, super, text-top, text-bottom, top, bottom")
 		.AddParser("length_percent").SetRelativeTarget(RelativeTarget::LineHeight);
 
-	RegisterProperty(OVERFLOW_X, "visible", false, true).AddParser("keyword", "visible, hidden, auto, scroll");
-	RegisterProperty(OVERFLOW_Y, "visible", false, true).AddParser("keyword", "visible, hidden, auto, scroll");
-	RegisterShorthand(OVERFLOW_, { OVERFLOW_X, OVERFLOW_Y }, PropertySpecification::REPLICATE);
-	RegisterProperty(CLIP, "auto", true, false).AddParser("keyword", "auto, none").AddParser("number");
-	RegisterProperty(VISIBILITY, "visible", false, false).AddParser("keyword", "visible, hidden");
+	RegisterProperty(Id::OverflowX, "visible", false, true).AddParser("keyword", "visible, hidden, auto, scroll");
+	RegisterProperty(Id::OverflowY, "visible", false, true).AddParser("keyword", "visible, hidden, auto, scroll");
+	RegisterShorthand(Id::Overflow, { Id::OverflowX, Id::OverflowY }, PropertySpecification::REPLICATE);
+	RegisterProperty(Id::Clip, "auto", true, false).AddParser("keyword", "auto, none").AddParser("number");
+	RegisterProperty(Id::Visibility, "visible", false, false).AddParser("keyword", "visible, hidden");
 
 	// Need some work on this if we are to include images.
-	RegisterProperty(BACKGROUND_COLOR, "transparent", false, false).AddParser("color");
-	RegisterShorthand(BACKGROUND, { BACKGROUND_COLOR });
+	RegisterProperty(Id::BackgroundColor, "transparent", false, false).AddParser("color");
+	RegisterShorthand(Id::Background, { Id::BackgroundColor });
 
-	RegisterProperty(COLOR, "white", true, false).AddParser("color");
+	RegisterProperty(Id::Color, "white", true, false).AddParser("color");
 
-	RegisterProperty(IMAGE_COLOR, "white", false, false).AddParser("color");
-	RegisterProperty(OPACITY, "1", true, false).AddParser("number");
+	RegisterProperty(Id::ImageColor, "white", false, false).AddParser("color");
+	RegisterProperty(Id::Opacity, "1", true, false).AddParser("number");
 
-	RegisterProperty(FONT_FAMILY, "", true, true).AddParser("string");
-	RegisterProperty(FONT_CHARSET, "U+0020-007E", true, false).AddParser("string");
-	RegisterProperty(FONT_STYLE, "normal", true, true).AddParser("keyword", "normal, italic");
-	RegisterProperty(FONT_WEIGHT, "normal", true, true).AddParser("keyword", "normal, bold");
-	RegisterProperty(FONT_SIZE, "12px", true, true).AddParser("length").AddParser("length_percent").SetRelativeTarget(RelativeTarget::ParentFontSize);
-	RegisterShorthand(FONT, { FONT_STYLE, FONT_WEIGHT, FONT_SIZE, FONT_FAMILY, FONT_CHARSET });
+	RegisterProperty(Id::FontFamily, "", true, true).AddParser("string");
+	RegisterProperty(Id::FontCharset, "U+0020-007E", true, false).AddParser("string");
+	RegisterProperty(Id::FontStyle, "normal", true, true).AddParser("keyword", "normal, italic");
+	RegisterProperty(Id::FontWeight, "normal", true, true).AddParser("keyword", "normal, bold");
+	RegisterProperty(Id::FontSize, "12px", true, true).AddParser("length").AddParser("length_percent").SetRelativeTarget(RelativeTarget::ParentFontSize);
+	RegisterShorthand(Id::Font, { Id::FontStyle, Id::FontWeight, Id::FontSize, Id::FontFamily, Id::FontCharset });
 
-	RegisterProperty(TEXT_ALIGN, "left", true, true).AddParser("keyword", "left, right, center, justify");
-	RegisterProperty(TEXT_DECORATION, "none", true, false).AddParser("keyword", "none, underline"/*"none, underline, overline, line-through"*/);
-	RegisterProperty(TEXT_TRANSFORM, "none", true, true).AddParser("keyword", "none, capitalize, uppercase, lowercase");
-	RegisterProperty(WHITE_SPACE, "normal", true, true).AddParser("keyword", "normal, pre, nowrap, pre-wrap, pre-line");
+	RegisterProperty(Id::TextAlign, "left", true, true).AddParser("keyword", "left, right, center, justify");
+	RegisterProperty(Id::TextDecoration, "none", true, false).AddParser("keyword", "none, underline"/*"none, underline, overline, line-through"*/);
+	RegisterProperty(Id::TextTransform, "none", true, true).AddParser("keyword", "none, capitalize, uppercase, lowercase");
+	RegisterProperty(Id::WhiteSpace, "normal", true, true).AddParser("keyword", "normal, pre, nowrap, pre-wrap, pre-line");
 
-	RegisterProperty(CURSOR, "auto", true, false).AddParser("keyword", "auto").AddParser("string");
+	RegisterProperty(Id::Cursor, "auto", true, false).AddParser("keyword", "auto").AddParser("string");
 
 	// Functional property specifications.
-	RegisterProperty(DRAG_PROPERTY, "none", false, false).AddParser("keyword", "none, drag, drag-drop, block, clone");
-	RegisterProperty(TAB_INDEX, "none", false, false).AddParser("keyword", "none, auto");
-	RegisterProperty(FOCUS_PROPERTY, "auto", true, false).AddParser("keyword", "none, auto");
-	RegisterProperty(SCROLLBAR_MARGIN, "0", false, false).AddParser("length");
-	RegisterProperty(POINTER_EVENTS, "auto", true, false).AddParser("keyword", "auto, none");
+	RegisterProperty(Id::DragProperty, "none", false, false).AddParser("keyword", "none, drag, drag-drop, block, clone");
+	RegisterProperty(Id::TabIndex, "none", false, false).AddParser("keyword", "none, auto");
+	RegisterProperty(Id::Focus, "auto", true, false).AddParser("keyword", "none, auto");
+	RegisterProperty(Id::ScrollbarMargin, "0", false, false).AddParser("length");
+	RegisterProperty(Id::PointerEvents, "auto", true, false).AddParser("keyword", "auto, none");
 
 	// Perspective and Transform specifications
-	RegisterProperty(PERSPECTIVE, "none", false, false).AddParser("keyword", "none").AddParser("length");
-	RegisterProperty(PERSPECTIVE_ORIGIN_X, "50%", false, false).AddParser("keyword", "left, center, right").AddParser("length_percent");
-	RegisterProperty(PERSPECTIVE_ORIGIN_Y, "50%", false, false).AddParser("keyword", "top, center, bottom").AddParser("length_percent");
-	RegisterShorthand(PERSPECTIVE_ORIGIN, { PERSPECTIVE_ORIGIN_X, PERSPECTIVE_ORIGIN_Y });
-	RegisterProperty(TRANSFORM, "none", false, false).AddParser("transform");
-	RegisterProperty(TRANSFORM_ORIGIN_X, "50%", false, false).AddParser("keyword", "left, center, right").AddParser("length_percent");
-	RegisterProperty(TRANSFORM_ORIGIN_Y, "50%", false, false).AddParser("keyword", "top, center, bottom").AddParser("length_percent");
-	RegisterProperty(TRANSFORM_ORIGIN_Z, "0", false, false).AddParser("length");
-	RegisterShorthand(TRANSFORM_ORIGIN, { TRANSFORM_ORIGIN_X, TRANSFORM_ORIGIN_Y, TRANSFORM_ORIGIN_Z });
-
-	RegisterProperty(TRANSITION, "none", false, false).AddParser("transition");
-	RegisterProperty(ANIMATION, "none", false, false).AddParser("animation");
+	RegisterProperty(Id::Perspective, "none", false, false).AddParser("keyword", "none").AddParser("length");
+	RegisterProperty(Id::PerspectiveOriginX, "50%", false, false).AddParser("keyword", "left, center, right").AddParser("length_percent");
+	RegisterProperty(Id::PerspectiveOriginY, "50%", false, false).AddParser("keyword", "top, center, bottom").AddParser("length_percent");
+	RegisterShorthand(Id::PerspectiveOrigin, { Id::PerspectiveOriginX, Id::PerspectiveOriginY});
+	RegisterProperty(Id::Transform, "none", false, false).AddParser("transform");
+	RegisterProperty(Id::TransformOriginX, "50%", false, false).AddParser("keyword", "left, center, right").AddParser("length_percent");
+	RegisterProperty(Id::TransformOriginY, "50%", false, false).AddParser("keyword", "top, center, bottom").AddParser("length_percent");
+	RegisterProperty(Id::TransformOriginZ, "0", false, false).AddParser("length");
+	RegisterShorthand(Id::TransformOrigin, { Id::TransformOriginX, Id::TransformOriginY, Id::TransformOriginZ });
+
+	RegisterProperty(Id::Transition, "none", false, false).AddParser("transition");
+	RegisterProperty(Id::Animation, "none", false, false).AddParser("animation");
 }
 
 }