Browse Source

Margin, padding, border, ...

Michael Ragazzon 6 years ago
parent
commit
bb70d38d61
4 changed files with 110 additions and 33 deletions
  1. 5 0
      Samples/basic/benchmark/src/main.cpp
  2. 65 6
      Source/Core/ElementStyle.cpp
  3. 15 25
      Source/Core/LayoutEngine.cpp
  4. 25 2
      Source/Core/RCSS.h

+ 5 - 0
Samples/basic/benchmark/src/main.cpp

@@ -42,6 +42,10 @@
 //       Instead, GetComputedValue which gives either absolute length, percentage, keywords (enum), color, etc. Inherited values then only need to check their nearest parent.
 //  - [bug] Input.range appears only after one additional frame.
 
+// Other TODO:
+// - The em-property depends on the current font-size, not font face lineheight! (See Element::OnPropertyChange)
+
+
 class DemoWindow
 {
 public:
@@ -86,6 +90,7 @@ public:
 		  First usage of computed values (font): 74.0  [04dc275]
 		  Computed values, clipping: 77.0
 		  Computed values, background-color, image-color, opacity: 77.0
+		  Computed values, padding, margin border++: 81.0
 		
 		*/
 

+ 65 - 6
Source/Core/ElementStyle.cpp

@@ -1048,15 +1048,13 @@ const Property *ElementStyle::GetTransformOriginZ()
 
 static float ComputeLength(const Property* property, float font_size, float document_font_size, float dp_ratio, float pixels_per_inch)
 {
+	// Note that percentages are not lengths! They have to be resolved elsewhere.
 	if (!property)
 	{
 		ROCKET_ERROR;
 		return 0.0f;
 	}
 
-	// TODO
-	float base_value = 1.0f;
-
 	switch (property->unit)
 	{
 	case Property::NUMBER:
@@ -1064,9 +1062,6 @@ static float ComputeLength(const Property* property, float font_size, float docu
 	case Property::RAD:
 		return property->value.Get< float >();
 
-	case Property::PERCENT:
-		return base_value * property->value.Get< float >()* 0.01f;
-
 	case Property::EM:
 		return property->value.Get< float >() * font_size;
 	case Property::REM:
@@ -1076,6 +1071,8 @@ static float ComputeLength(const Property* property, float font_size, float docu
 
 	case Property::DEG:
 		return Math::DegreesToRadians(property->value.Get< float >());
+	default: 
+		break;
 	}
 
 	// Values based on pixels-per-inch.
@@ -1095,6 +1092,8 @@ static float ComputeLength(const Property* property, float font_size, float docu
 			return inch * (1.0f / 72.0f);
 		case Property::PC: // pica
 			return inch * (1.0f / 6.0f);
+		default:
+			break;
 		}
 	}
 
@@ -1190,18 +1189,45 @@ static inline Style::Clip ComputeClip(const Property* property)
 	return Style::Clip::Auto;
 }
 
+static inline LengthPercentage ComputeLengthPercentage(const Property* property, float font_size, float document_font_size, float dp_ratio, float pixels_per_inch)
+{
+	if (property->unit & Property::PERCENT)
+		return LengthPercentage(LengthPercentage::Percentage, property->Get<float>());
+
+	return LengthPercentage(LengthPercentage::Length, ComputeLength(property, font_size, document_font_size, dp_ratio, pixels_per_inch));
+}
+
+
+static inline LengthPercentageAuto ComputeLengthPercentageAuto(const Property* property, float font_size, float document_font_size, float dp_ratio, float pixels_per_inch)
+{
+	// Assuming here that 'auto' is the only possible keyword
+	if (property->unit & Property::PERCENT)
+		return LengthPercentageAuto(LengthPercentageAuto::Percentage, property->Get<float>());
+	else if (property->unit & Property::KEYWORD)
+		return LengthPercentageAuto(LengthPercentageAuto::Auto);
+
+	return LengthPercentageAuto(LengthPercentageAuto::Length, ComputeLength(property, font_size, document_font_size, dp_ratio, pixels_per_inch));
+}
+
 
 // Must be called in correct order, from document root to children elements.
 void ElementStyle::ComputeValues(Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, float dp_ratio, float pixels_per_inch)
 {
 	// TODO: Iterate through dirty values, and compute corresponding properties.
 	// Important: Always do font-size first if dirty, because of em-relative values.
+	// Whenever the font-size changes, we need to dirty all properties making use of em!
+
 
 	if (auto p = GetLocalProperty(FONT_SIZE))
 		values.font_size = ComputeFontsize(*p, values, parent_values, document_values, dp_ratio, pixels_per_inch);
 	else if (parent_values)
 		values.font_size = parent_values->font_size;
 
+
+	const float font_size = values.font_size;
+	const float document_font_size = (document_values ? document_values->font_size : DefaultComputedValues.font_size);
+
+
 	if (auto p = GetLocalProperty(FONT_FAMILY))
 		values.font_family = p->Get<String>();
 	else if (parent_values)
@@ -1259,6 +1285,39 @@ void ElementStyle::ComputeValues(Style::ComputedValues& values, const Style::Com
 
 
 
+	if(auto p = GetLocalProperty(MARGIN_TOP))
+		values.margin_top = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(MARGIN_RIGHT))
+		values.margin_right = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(MARGIN_BOTTOM))
+		values.margin_bottom = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(MARGIN_LEFT))
+		values.margin_top = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+
+
+	if (auto p = GetLocalProperty(PADDING_TOP))
+		values.padding_top = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(PADDING_RIGHT))
+		values.padding_right = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(PADDING_BOTTOM))
+		values.padding_bottom = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(PADDING_LEFT))
+		values.padding_top = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+
+
+
+	if (auto p = GetLocalProperty(BORDER_TOP_WIDTH))
+		values.border_top_width = ComputeLength(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(BORDER_RIGHT_WIDTH))
+		values.border_right_width = ComputeLength(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(BORDER_BOTTOM_WIDTH))
+		values.border_bottom_width = ComputeLength(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+	if (auto p = GetLocalProperty(BORDER_LEFT_WIDTH))
+		values.border_top_width = ComputeLength(p, font_size, document_font_size, dp_ratio, pixels_per_inch);
+
+
+
+
 }
 
 }

+ 15 - 25
Source/Core/LayoutEngine.cpp

@@ -31,6 +31,7 @@
 #include "Pool.h"
 #include "LayoutBlockBoxSpace.h"
 #include "LayoutInlineBoxText.h"
+#include "RCSS.h"
 #include "../../Include/Rocket/Core/Element.h"
 #include "../../Include/Rocket/Core/ElementScroll.h"
 #include "../../Include/Rocket/Core/ElementText.h"
@@ -123,31 +124,23 @@ void LayoutEngine::BuildBox(Box& box, const Vector2f& containing_block, Element*
 		return;
 	}
 
-	// Calculate the padding area.
-	const Property *padding_top, *padding_bottom, *padding_left, *padding_right;
-	element->GetPaddingProperties (&padding_top, &padding_bottom, &padding_left, &padding_right);
+	const ComputedValues& computed = element->GetComputedValues();
 
-	float padding = element->ResolveProperty(padding_top, containing_block.x);
+	// Calculate the padding area.
+	float padding = ResolveProperty(computed.padding_top, containing_block.x);
 	box.SetEdge(Box::PADDING, Box::TOP, Math::Max(0.0f, padding));
-	padding = element->ResolveProperty(padding_right, containing_block.x);
+	padding = ResolveProperty(computed.padding_right, containing_block.x);
 	box.SetEdge(Box::PADDING, Box::RIGHT, Math::Max(0.0f, padding));
-	padding = element->ResolveProperty(padding_bottom, containing_block.x);
+	padding = ResolveProperty(computed.padding_bottom, containing_block.x);
 	box.SetEdge(Box::PADDING, Box::BOTTOM, Math::Max(0.0f, padding));
-	padding = element->ResolveProperty(padding_left, containing_block.x);
+	padding = ResolveProperty(computed.padding_left, containing_block.x);
 	box.SetEdge(Box::PADDING, Box::LEFT, Math::Max(0.0f, padding));
 
 	// Calculate the border area.
-	const Property *border_top_width, *border_bottom_width, *border_left_width, *border_right_width;
-	element->GetBorderWidthProperties (&border_top_width, &border_bottom_width, &border_left_width, &border_right_width);
-
-	float border = element->ResolveProperty(border_top_width, containing_block.x);
-	box.SetEdge(Box::BORDER, Box::TOP, Math::Max(0.0f, border));
-	border = element->ResolveProperty(border_right_width, containing_block.x);
-	box.SetEdge(Box::BORDER, Box::RIGHT, Math::Max(0.0f, border));
-	border = element->ResolveProperty(border_bottom_width, containing_block.x);
-	box.SetEdge(Box::BORDER, Box::BOTTOM, Math::Max(0.0f, border));
-	border = element->ResolveProperty(border_left_width, containing_block.x);
-	box.SetEdge(Box::BORDER, Box::LEFT, Math::Max(0.0f, border));
+	box.SetEdge(Box::BORDER, Box::TOP, Math::Max(0.0f, computed.border_top_width));
+	box.SetEdge(Box::BORDER, Box::RIGHT, Math::Max(0.0f, computed.border_right_width));
+	box.SetEdge(Box::BORDER, Box::BOTTOM, Math::Max(0.0f, computed.border_bottom_width));
+	box.SetEdge(Box::BORDER, Box::LEFT, Math::Max(0.0f, computed.border_left_width));
 
 	// Calculate the size of the content area.
 	Vector2f content_area(-1, -1);
@@ -213,13 +206,10 @@ void LayoutEngine::BuildBox(Box& box, const Vector2f& containing_block, Element*
 		box.SetContent(content_area);
 
 		// Evaluate the margins. Any declared as 'auto' will resolve to 0.
-		const Property *margin_top, *margin_bottom, *margin_left, *margin_right;
-		element->GetMarginProperties(&margin_top, &margin_bottom, &margin_left, &margin_right);
-
-		box.SetEdge(Box::MARGIN, Box::TOP, element->ResolveProperty(margin_top, containing_block.x));
-		box.SetEdge(Box::MARGIN, Box::RIGHT, element->ResolveProperty(margin_right, containing_block.x));
-		box.SetEdge(Box::MARGIN, Box::BOTTOM, element->ResolveProperty(margin_bottom, containing_block.x));
-		box.SetEdge(Box::MARGIN, Box::LEFT, element->ResolveProperty(margin_left, containing_block.x));
+		box.SetEdge(Box::MARGIN, Box::TOP, ResolveProperty(computed.margin_top, containing_block.x));
+		box.SetEdge(Box::MARGIN, Box::RIGHT, ResolveProperty(computed.margin_right, containing_block.x));
+		box.SetEdge(Box::MARGIN, Box::BOTTOM, ResolveProperty(computed.margin_bottom, containing_block.x));
+		box.SetEdge(Box::MARGIN, Box::LEFT, ResolveProperty(computed.margin_left, containing_block.x));
 	}
 
 	// The element is block, so we need to run the box through the ringer to potentially evaluate auto margins and

+ 25 - 2
Source/Core/RCSS.h

@@ -33,8 +33,6 @@ namespace Core {
 
 #include "../../Include/Rocket/Core/Types.h"
 
-namespace Style
-{
 struct LengthPercentageAuto {
 	enum Type { Length, Percentage, Auto } type = Length;
 	float value = 0;
@@ -44,6 +42,8 @@ struct LengthPercentageAuto {
 struct LengthPercentage {
 	enum Type { Length, Percentage } type = Length;
 	float value = 0;
+	LengthPercentage() {}
+	LengthPercentage(Type type, float value = 0) : type(type), value(value) {}
 };
 
 struct NumberAuto {
@@ -53,6 +53,11 @@ struct NumberAuto {
 	NumberAuto(Type type, float value = 0) : type(type), value(value) {}
 };
 
+
+namespace Style
+{
+
+
 enum class Display { None, Block, Inline, InlineBlock };
 enum class Position { Static, Relative, Absolute, Fixed };
 
@@ -150,6 +155,24 @@ struct ComputedValues
 };
 }
 
+// Note: Auto must be manually handled during layout, here it returns zero.
+inline float ResolveProperty(LengthPercentageAuto length, float base_value) {
+	if (length.type == LengthPercentageAuto::Length)
+		return length.value;
+	else if (length.type == LengthPercentageAuto::Percentage)
+		return length.value * 0.01f * base_value;
+	return 0.0f;
+}
+
+inline float ResolveProperty(LengthPercentage length, float base_value) {
+	if (length.type == LengthPercentage::Length)
+		return length.value;
+	else if (length.type == LengthPercentage::Percentage)
+		return length.value * 0.01f * base_value;
+	return 0.0f;
+}
+
+
 using ComputedValues = Style::ComputedValues;
 
 }