Browse Source

added REM unit support

Julian 12 years ago
parent
commit
94a2515387

+ 8 - 7
Include/Rocket/Core/Property.h

@@ -59,15 +59,16 @@ public:
 
 		// Relative values.
 		EM = 1 << 6,				// number suffixed by 'em'; fetch as < float >
-		PERCENT = 1 << 7,			// number suffixed by '%'; fetch as < float >
-		RELATIVE_UNIT = EM | PERCENT,
+		REM = 1 << 7,				// number suffixed by 'rem'; fetch as < float >
+		PERCENT = 1 << 8,			// number suffixed by '%'; fetch as < float >
+		RELATIVE_UNIT = EM | REM | PERCENT,
 
 		// Values based on pixels-per-inch.
-		INCH = 1 << 8,				// number suffixed by 'in'; fetch as < float >
-		CM = 1 << 9,				// number suffixed by 'cm'; fetch as < float >
-		MM = 1 << 10,				// number suffixed by 'mm'; fetch as < float >
-		PT = 1 << 11,				// number suffixed by 'pt'; fetch as < float >
-		PC = 1 << 12,				// number suffixed by 'pc'; fetch as < float >
+		INCH = 1 << 9,				// number suffixed by 'in'; fetch as < float >
+		CM = 1 << 10,				// number suffixed by 'cm'; fetch as < float >
+		MM = 1 << 11,				// number suffixed by 'mm'; fetch as < float >
+		PT = 1 << 12,				// number suffixed by 'pt'; fetch as < float >
+		PC = 1 << 13,				// number suffixed by 'pc'; fetch as < float >
 		PPI_UNIT = INCH | CM | MM | PT | PC
 	};
 

+ 4 - 0
Source/Core/ElementDocument.cpp

@@ -370,6 +370,10 @@ void ElementDocument::OnPropertyChange(const PropertyNameList& changed_propertie
 {
 	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())
+		GetStyle()->DirtyRemProperties();
+
 	if (changed_properties.find(TOP) != changed_properties.end() ||
 		changed_properties.find(RIGHT) != changed_properties.end() ||
 		changed_properties.find(BOTTOM) != changed_properties.end() ||

+ 53 - 7
Source/Core/ElementStyle.cpp

@@ -356,6 +356,8 @@ float ElementStyle::ResolveProperty(const Property* property, float base_value)
 			return base_value * property->value.Get< float >() * 0.01f;
 		else if (property->unit & Property::EM)
 			return property->value.Get< float >() * ElementUtilities::GetFontSize(element);
+		else if (property->unit & Property::REM)
+			return property->value.Get< float >() * ElementUtilities::GetFontSize(element->GetOwnerDocument());
 	}
 
 	if (property->unit & Property::NUMBER || property->unit & Property::PX)
@@ -383,15 +385,28 @@ float ElementStyle::ResolveProperty(const String& name, float base_value)
 		// is an inherited property. If so, then we return our parent's font size instead.
 		if (name == FONT_SIZE)
 		{
-			Rocket::Core::Element* parent = element->GetParentNode();
-			if (parent == NULL)
-				return 0;
+			// If the rem unit is used, the font-size is inherited directly from the document,
+			// otherwise we use the parent's font size.
+			if (property->unit & Property::REM)
+			{
+				Rocket::Core::ElementDocument* owner_document = element->GetOwnerDocument();
+				if (owner_document == NULL)
+					return 0;
+
+				base_value = element->GetOwnerDocument()->ResolveProperty(FONT_SIZE, 0);
+			}
+			else
+			{
+				Rocket::Core::Element* parent = element->GetParentNode();
+				if (parent == NULL)
+					return 0;
 
-			if (GetLocalProperty(FONT_SIZE) == NULL)
-				return parent->ResolveProperty(FONT_SIZE, 0);
+				if (GetLocalProperty(FONT_SIZE) == NULL)
+					return parent->ResolveProperty(FONT_SIZE, 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);
+				// The base value for font size is always the height of *this* element's parent's font.
+				base_value = parent->ResolveProperty(FONT_SIZE, 0);
+			}
 		}
 
 		if (property->unit & Property::PERCENT)
@@ -405,6 +420,15 @@ float ElementStyle::ResolveProperty(const String& name, float base_value)
 			else
 				return property->value.Get< float >() * ElementUtilities::GetFontSize(element);
 		}
+		else if (property->unit & Property::REM)
+		{
+			// If an rem-relative font size is specified, it is expressed relative to the document's
+			// font height.
+			if (name == FONT_SIZE)
+				return property->value.Get< float >() * base_value;
+			else
+				return property->value.Get< float >() * ElementUtilities::GetFontSize(element->GetOwnerDocument());
+		}
 	}
 
 	if (property->unit & Property::NUMBER || property->unit & Property::PX)
@@ -548,6 +572,28 @@ void ElementStyle::DirtyInheritedEmProperties()
 	}
 }
 
+// Dirties rem properties.
+void ElementStyle::DirtyRemProperties()
+{
+	const PropertyNameList &properties = StyleSheetSpecification::GetRegisteredProperties();
+	PropertyNameList rem_properties;
+
+	// Dirty all the properties of this element that use the rem unit.
+	for (PropertyNameList::const_iterator list_iterator = properties.begin(); list_iterator != properties.end(); ++list_iterator)
+	{
+		if (element->GetProperty(*list_iterator)->unit == Property::REM)
+			rem_properties.insert(*list_iterator);
+	}
+
+	if (!rem_properties.empty())
+		DirtyProperties(rem_properties, false);
+
+	// Now dirty all of our descendant's properties that use the rem unit.
+	int num_children = element->GetNumChildren(true);
+	for (int i = 0; i < num_children; ++i)
+		element->GetChild(i)->GetStyle()->DirtyRemProperties();
+}
+
 // Sets a single property as dirty.
 void ElementStyle::DirtyProperty(const String& property)
 {

+ 2 - 0
Source/Core/ElementStyle.h

@@ -140,6 +140,8 @@ public:
 	void DirtyEmProperties();
 	// Dirties font-size on child elements if appropriate.
 	void DirtyInheritedEmProperties();
+	// Dirties rem properties.
+	void DirtyRemProperties();
 
 	/// Returns 'border-width' properties from element's style or local cache.
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);

+ 1 - 0
Source/Core/PropertyDefinition.cpp

@@ -133,6 +133,7 @@ bool PropertyDefinition::GetValue(String& value, const Property& property) const
 
 		case Property::PX:		value.Append("px"); break;
 		case Property::EM:		value.Append("em"); break;
+		case Property::REM:		value.Append("rem"); break;
 		case Property::PERCENT:	value.Append("%"); break;
 		case Property::INCH:	value.Append("in"); break;
 		case Property::CM:		value.Append("cm"); break;

+ 1 - 0
Source/Core/PropertyParserNumber.cpp

@@ -34,6 +34,7 @@ namespace Core {
 PropertyParserNumber::PropertyParserNumber()
 {
 	unit_suffixes.push_back(UnitSuffix(Property::PX, "px"));
+	unit_suffixes.push_back(UnitSuffix(Property::REM, "rem"));
 	unit_suffixes.push_back(UnitSuffix(Property::EM, "em"));
 	unit_suffixes.push_back(UnitSuffix(Property::INCH, "in"));
 	unit_suffixes.push_back(UnitSuffix(Property::CM, "cm"));