Ver Fonte

Merge pull request #252 from fr00b0/absolute-position-size

Sizing of absoultely positioned elements
David Wimsey há 10 anos atrás
pai
commit
1b36dbcda6

+ 2 - 0
Include/Rocket/Core/Element.h

@@ -227,6 +227,8 @@ public:
 	/// @return The value of this property for this element.
 	/// @return The value of this property for this element.
 	float ResolveProperty(const Property *property, float base_value);
 	float ResolveProperty(const Property *property, float base_value);
 
 
+	/// Returns 'top', 'bottom', 'left' and 'right' properties from element's style or local cache.
+	void GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right );
 	/// Returns 'border-width' properties from element's style or local cache.
 	/// 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);
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);
 	/// Returns 'margin' properties from element's style or local cache.
 	/// Returns 'margin' properties from element's style or local cache.

+ 6 - 1
Source/Core/Element.cpp

@@ -537,6 +537,11 @@ float Element::ResolveProperty(const Property *property, float base_value)
 	return style->ResolveProperty(property, base_value);
 	return style->ResolveProperty(property, base_value);
 }
 }
 
 
+void Element::GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right )
+{
+	style->GetOffsetProperties(top, bottom, left, right);
+}
+
 void Element::GetBorderWidthProperties(const Property **border_top, const Property **border_bottom, const Property **border_left, const Property **bottom_right)
 void Element::GetBorderWidthProperties(const Property **border_top, const Property **border_bottom, const Property **border_left, const Property **bottom_right)
 {
 {
 	style->GetBorderWidthProperties(border_top, border_bottom, border_left, bottom_right);
 	style->GetBorderWidthProperties(border_top, border_bottom, border_left, bottom_right);
@@ -1836,7 +1841,7 @@ void Element::UpdateOffset()
 			// If the element is anchored right, then the position is set first so the element's right-most edge
 			// 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
 			// (including margins) will render up against the containing box's right-most content edge, and then
 			// offset by the resolved value.
 			// offset by the resolved value.
-			if (right != NULL && right->unit != Property::KEYWORD)
+			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(RIGHT, containing_block.x) + GetBox().GetSize(Box::BORDER).x + GetBox().GetEdge(Box::MARGIN, Box::RIGHT));
 
 
 			const Property *top = GetLocalProperty(TOP);
 			const Property *top = GetLocalProperty(TOP);

+ 5 - 0
Source/Core/ElementStyle.cpp

@@ -729,6 +729,11 @@ void ElementStyle::DirtyInheritedProperties(const PropertyNameList& properties)
 	element->OnPropertyChange(properties);
 	element->OnPropertyChange(properties);
 }
 }
 
 
+void ElementStyle::GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right )
+{
+	cache->GetOffsetProperties(top, bottom, left, right);
+}
+
 void ElementStyle::GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **bottom_right_width)
 void ElementStyle::GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **bottom_right_width)
 {
 {
 	cache->GetBorderWidthProperties(border_top_width, border_bottom_width, border_left_width, bottom_right_width);
 	cache->GetBorderWidthProperties(border_top_width, border_bottom_width, border_left_width, bottom_right_width);

+ 2 - 0
Source/Core/ElementStyle.h

@@ -143,6 +143,8 @@ public:
 	// Dirties rem properties.
 	// Dirties rem properties.
 	void DirtyRemProperties();
 	void DirtyRemProperties();
 
 
+	/// Returns 'top', 'bottom', 'left' and 'right' properties from element's style or local cache.
+	void GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right );	
 	/// Returns 'border-width' properties from element's style or local cache.
 	/// 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);
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);
 	/// Returns 'margin' properties from element's style or local cache.
 	/// Returns 'margin' properties from element's style or local cache.

+ 38 - 0
Source/Core/ElementStyleCache.cpp

@@ -33,6 +33,7 @@ namespace Rocket {
 namespace Core {
 namespace Core {
 
 
 ElementStyleCache::ElementStyleCache(ElementStyle *style) : style(style), 
 ElementStyleCache::ElementStyleCache(ElementStyle *style) : style(style), 
+	top(NULL), bottom(NULL), left(NULL), right(NULL),
 	border_top_width(NULL), border_bottom_width(NULL), border_left_width(NULL), border_right_width(NULL),
 	border_top_width(NULL), border_bottom_width(NULL), border_left_width(NULL), border_right_width(NULL),
 	margin_top(NULL), margin_bottom(NULL), margin_left(NULL), margin_right(NULL),
 	margin_top(NULL), margin_bottom(NULL), margin_left(NULL), margin_right(NULL),
 	padding_top(NULL), padding_bottom(NULL), padding_left(NULL), padding_right(NULL),
 	padding_top(NULL), padding_bottom(NULL), padding_left(NULL), padding_right(NULL),
@@ -46,6 +47,7 @@ ElementStyleCache::ElementStyleCache(ElementStyle *style) : style(style),
 
 
 void ElementStyleCache::Clear()
 void ElementStyleCache::Clear()
 {
 {
+	ClearOffset();
 	ClearBorder();
 	ClearBorder();
 	ClearMargin();
 	ClearMargin();
 	ClearPadding();
 	ClearPadding();
@@ -65,6 +67,11 @@ void ElementStyleCache::ClearInherited()
 	ClearVerticalAlign();
 	ClearVerticalAlign();
 }
 }
 
 
+void ElementStyleCache::ClearOffset()
+{
+	top = bottom = left = right = NULL;
+}
+
 void ElementStyleCache::ClearBorder()
 void ElementStyleCache::ClearBorder()
 {
 {
 	border_top_width = border_bottom_width = border_left_width = border_right_width = NULL;
 	border_top_width = border_bottom_width = border_left_width = border_right_width = NULL;
@@ -131,6 +138,37 @@ void ElementStyleCache::ClearVerticalAlign()
 	vertical_align = NULL;
 	vertical_align = NULL;
 }
 }
 
 
+void ElementStyleCache::GetOffsetProperties(const Property **o_top, const Property **o_bottom, const Property **o_left, const Property **o_right )
+{
+	if (o_top)
+	{
+		if (!top)
+			top = style->GetProperty(TOP);
+		*o_top = top;
+	}
+
+	if (o_bottom)
+	{
+		if (!bottom)
+			bottom = style->GetProperty(BOTTOM);
+		*o_bottom = bottom;
+	}
+
+	if (o_left)
+	{
+		if (!left)
+			left = style->GetProperty(LEFT);
+		*o_left = left;
+	}
+
+	if (o_right)
+	{
+		if (!right)
+			right = style->GetProperty(RIGHT);
+		*o_right = right;
+	}
+}
+
 void ElementStyleCache::GetBorderWidthProperties(const Property **o_border_top_width, const Property **o_border_bottom_width, const Property **o_border_left_width, const Property **o_border_right_width)
 void ElementStyleCache::GetBorderWidthProperties(const Property **o_border_top_width, const Property **o_border_bottom_width, const Property **o_border_left_width, const Property **o_border_right_width)
 {
 {
 	if (o_border_top_width)
 	if (o_border_top_width)

+ 4 - 0
Source/Core/ElementStyleCache.h

@@ -55,6 +55,7 @@ public:
 	void ClearInherited();
 	void ClearInherited();
 
 
 	/// Invalidation functions for individual and grouped non-inherited properties
 	/// Invalidation functions for individual and grouped non-inherited properties
+	void ClearOffset();
 	void ClearBorder();
 	void ClearBorder();
 	void ClearMargin();
 	void ClearMargin();
 	void ClearPadding();
 	void ClearPadding();
@@ -71,6 +72,8 @@ public:
 	void ClearTextTransform();
 	void ClearTextTransform();
 	void ClearVerticalAlign();
 	void ClearVerticalAlign();
 
 
+	/// Returns 'top', 'bottom', 'left' and 'right' properties from element's style or local cache.
+	void GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right );
 	/// Returns 'border-width' properties from element's style or local cache.
 	/// 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);
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);
 	/// Returns 'margin' properties from element's style or local cache.
 	/// Returns 'margin' properties from element's style or local cache.
@@ -107,6 +110,7 @@ private:
 	ElementStyle *style;
 	ElementStyle *style;
 
 
 	/// Cached properties.
 	/// Cached properties.
+	const Property *top, *bottom, *left, *right;
 	const Property *border_top_width, *border_bottom_width, *border_left_width, *border_right_width;
 	const Property *border_top_width, *border_bottom_width, *border_left_width, *border_right_width;
 	const Property *margin_top, *margin_bottom, *margin_left, *margin_right;
 	const Property *margin_top, *margin_bottom, *margin_left, *margin_right;
 	const Property *padding_top, *padding_bottom, *padding_left, *padding_right;
 	const Property *padding_top, *padding_bottom, *padding_left, *padding_right;

+ 45 - 5
Source/Core/LayoutEngine.cpp

@@ -522,17 +522,33 @@ void LayoutEngine::BuildBoxWidth(Box& box, Element* element, float containing_bl
 		}
 		}
 	}
 	}
 
 
-	// If the width is set to auto, then any margins also set to auto are resolved to 0 and the width is set to the
-	// whatever if left of the containing block.
+	// If the width is set to auto, we need to calculate the width
 	if (width_auto)
 	if (width_auto)
 	{
 	{
+		float left = 0.0f, right = 0.0f;
+		// If we are dealing with an absolutely positioned element we need to
+		// consider if the left and right properties are set, since the width can be affected.
+		if (element->GetPosition() == POSITION_ABSOLUTE || 
+			element->GetPosition() == POSITION_FIXED)
+		{
+			Property const *left_property, *right_property;
+			element->GetOffsetProperties( NULL, NULL, &left_property, &right_property );
+			if (left_property->unit != Property::KEYWORD) 
+				left = element->ResolveProperty(left_property, containing_block_width );
+			if (right_property->unit != Property::KEYWORD) 
+				right = element->ResolveProperty(right_property, containing_block_width );
+		}
+
+		// We resolve any auto margins to 0 and the width is set to whatever is left of the containing block.
 		if (margins_auto[0])
 		if (margins_auto[0])
 			box.SetEdge(Box::MARGIN, Box::LEFT, 0);
 			box.SetEdge(Box::MARGIN, Box::LEFT, 0);
 		if (margins_auto[1])
 		if (margins_auto[1])
 			box.SetEdge(Box::MARGIN, Box::RIGHT, 0);
 			box.SetEdge(Box::MARGIN, Box::RIGHT, 0);
 
 
-		content_area.x = containing_block_width - (box.GetCumulativeEdge(Box::CONTENT, Box::LEFT) +
-												   box.GetCumulativeEdge(Box::CONTENT, Box::RIGHT));
+		content_area.x = containing_block_width - (left +
+		                                           box.GetCumulativeEdge(Box::CONTENT, Box::LEFT) +
+		                                           box.GetCumulativeEdge(Box::CONTENT, Box::RIGHT) +
+		                                           right);
 		content_area.x = Math::Max(0.0f, content_area.x);
 		content_area.x = Math::Max(0.0f, content_area.x);
 	}
 	}
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
@@ -622,15 +638,39 @@ void LayoutEngine::BuildBoxHeight(Box& box, Element* element, float containing_b
 		}
 		}
 	}
 	}
 
 
-	// If the height is set to auto, then any margins also set to auto are resolved to 0 and the height is set to -1.
+	// If the height is set to auto, we need to calculate the height
 	if (height_auto)
 	if (height_auto)
 	{
 	{
+		// We resolve any auto margins to 0
 		if (margins_auto[0])
 		if (margins_auto[0])
 			box.SetEdge(Box::MARGIN, Box::TOP, 0);
 			box.SetEdge(Box::MARGIN, Box::TOP, 0);
 		if (margins_auto[1])
 		if (margins_auto[1])
 			box.SetEdge(Box::MARGIN, Box::BOTTOM, 0);
 			box.SetEdge(Box::MARGIN, Box::BOTTOM, 0);
 
 
+		// If the height is set to auto for a box in normal flow, the height is set to -1.
 		content_area.y = -1;
 		content_area.y = -1;
+
+		// But if we are dealing with an absolutely positioned element we need to
+		// consider if the top and bottom properties are set, since the height can be affected.
+		if (element->GetPosition() == POSITION_ABSOLUTE || 
+			element->GetPosition() == POSITION_FIXED)
+		{
+			float top = 0.0f, bottom = 0.0f;
+			Property const *top_property, *bottom_property;
+			element->GetOffsetProperties( &top_property, &bottom_property, NULL, NULL );
+			if (top_property->unit != Property::KEYWORD && bottom_property->unit != Property::KEYWORD ) 
+			{
+				top = element->ResolveProperty(top_property, containing_block_height );
+				bottom = element->ResolveProperty(bottom_property, containing_block_height );
+
+				// The height gets resolved to whatever is left of the containing block
+				content_area.y = containing_block_height - (top +
+				                                            box.GetCumulativeEdge(Box::CONTENT, Box::TOP) +
+				                                            box.GetCumulativeEdge(Box::CONTENT, Box::BOTTOM) +
+				                                            bottom);
+				content_area.y = Math::Max(0.0f, content_area.y);
+			}
+		}
 	}
 	}
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
 	else if (num_auto_margins > 0)
 	else if (num_auto_margins > 0)