Example #1
0
// Generates the clipping region for an element.
bool ElementUtilities::GetClippingRegion(Vector2i& clip_origin, Vector2i& clip_dimensions, Element* element)
{
	clip_origin = Vector2i(-1, -1);
	clip_dimensions = Vector2i(-1, -1);
	
	int num_ignored_clips = element->GetClippingIgnoreDepth();
	if (num_ignored_clips < 0)
		return false;

	// Search through the element's ancestors, finding all elements that clip their overflow and have overflow to clip.
	// For each that we find, we combine their clipping region with the existing clipping region, and so build up a
	// complete clipping region for the element.
	Element* clipping_element = element->GetParentNode();

	while (clipping_element != NULL)
	{
		// Merge the existing clip region with the current clip region if we aren't ignoring clip regions.
		if (num_ignored_clips == 0 && clipping_element->IsClippingEnabled())
		{
			Vector2f element_origin_f = clipping_element->GetAbsoluteOffset(Box::CONTENT);
			Vector2f element_dimensions_f = clipping_element->GetBox().GetSize(Box::CONTENT);

			Vector2i element_origin(Math::RealToInteger(element_origin_f.x), Math::RealToInteger(element_origin_f.y));
			Vector2i element_dimensions(Math::RealToInteger(element_dimensions_f.x), Math::RealToInteger(element_dimensions_f.y));

			if (clip_dimensions == Vector2i(-1, -1))
			{
				clip_origin = element_origin;
				clip_dimensions = element_dimensions;
			}
			else
			{
				Vector2i top_left(Math::Max(clip_origin.x, element_origin.x),
								  Math::Max(clip_origin.y, element_origin.y));

				Vector2i bottom_right(Math::Min(clip_origin.x + clip_dimensions.x, element_origin.x + element_dimensions.x),
									  Math::Min(clip_origin.y + clip_dimensions.y, element_origin.y + element_dimensions.y));

				clip_origin = top_left;
				clip_dimensions.x = Math::Max(0, bottom_right.x - top_left.x);
				clip_dimensions.y = Math::Max(0, bottom_right.y - top_left.y);
			}
		}

		// If this region is meant to clip and we're skipping regions, update the counter.
		if (num_ignored_clips > 0)
		{
			if (clipping_element->IsClippingEnabled())
				num_ignored_clips--;
		}

		// Determine how many clip regions this ancestor ignores, and inherit the value. If this region ignores all
		// clipping regions, then we do too.
		int clipping_element_ignore_clips = clipping_element->GetClippingIgnoreDepth();
		if (clipping_element_ignore_clips < 0)
			break;
		
		num_ignored_clips = Math::Max(num_ignored_clips, clipping_element_ignore_clips);

		// Climb the tree to this region's parent.
		clipping_element = clipping_element->GetParentNode();
	}
	
	return clip_dimensions.x >= 0 && clip_dimensions.y >= 0;
}
// Generates the clipping region for an element.
bool ElementUtilities::GetClippingRegion(Vector2i& clip_origin, Vector2i& clip_dimensions, Element* element)
{
	clip_origin = Vector2i(-1, -1);
	clip_dimensions = Vector2i(-1, -1);
	
	int num_ignored_clips = element->GetClippingIgnoreDepth();
	if (num_ignored_clips < 0)
		return false;

	// Search through the element's ancestors, finding all elements that clip their overflow and have overflow to clip.
	// For each that we find, we combine their clipping region with the existing clipping region, and so build up a
	// complete clipping region for the element.
	Element* clipping_element = element->GetParentNode();

	while (clipping_element != NULL)
	{
		// Merge the existing clip region with the current clip region if we aren't ignoring clip regions.
		if (num_ignored_clips == 0 && clipping_element->IsClippingEnabled())
		{
			// Ignore nodes that don't clip.
			if (clipping_element->GetClientWidth() < clipping_element->GetScrollWidth()
				|| clipping_element->GetClientHeight() < clipping_element->GetScrollHeight())
			{				
				Vector2f element_origin_f = clipping_element->GetAbsoluteOffset(Box::CONTENT);
				Vector2f element_dimensions_f = clipping_element->GetBox().GetSize(Box::CONTENT);
				
				Vector2i element_origin(Math::RealToInteger(element_origin_f.x), Math::RealToInteger(element_origin_f.y));
				Vector2i element_dimensions(Math::RealToInteger(element_dimensions_f.x), Math::RealToInteger(element_dimensions_f.y));
				
				bool clip_x = element->GetProperty(OVERFLOW_X)->Get< int >() != OVERFLOW_VISIBLE;
				bool clip_y = element->GetProperty(OVERFLOW_Y)->Get< int >() != OVERFLOW_VISIBLE;
				ROCKET_ASSERT(!clip_x || !clip_y || (clip_x && clip_y));
				
				//TODO: REPLACE FOLLOWING BUG FIX FOR OVERFLOW
				if( !( clip_x && clip_y ) )
				{
					clip_x = true;
					clip_y = true;
				}
				//END TODO

				if (!clip_x)
				{
					element_origin.x = 0;
					element_dimensions.x = clip_dimensions.x < 0 ? element->GetContext()->GetDimensions().x : clip_dimensions.x;
				}
				else if (!clip_y)
				{
					element_origin.y = 0;
					element_dimensions.y = clip_dimensions.y < 0 ? element->GetContext()->GetDimensions().y : clip_dimensions.y;
				}
		
				if (clip_dimensions == Vector2i(-1, -1))
				{
					clip_origin = element_origin;
					clip_dimensions = element_dimensions;
				}
				else
				{
					Vector2i top_left(Math::Max(clip_origin.x, element_origin.x),
									  Math::Max(clip_origin.y, element_origin.y));
					
					Vector2i bottom_right(Math::Min(clip_origin.x + clip_dimensions.x, element_origin.x + element_dimensions.x),
										  Math::Min(clip_origin.y + clip_dimensions.y, element_origin.y + element_dimensions.y));
					
					clip_origin = top_left;
					clip_dimensions.x = Math::Max(0, bottom_right.x - top_left.x);
					clip_dimensions.y = Math::Max(0, bottom_right.y - top_left.y);
				}
			}
		}

		// If this region is meant to clip and we're skipping regions, update the counter.
		if (num_ignored_clips > 0)
		{
			if (clipping_element->IsClippingEnabled())
				num_ignored_clips--;
		}

		// Determine how many clip regions this ancestor ignores, and inherit the value. If this region ignores all
		// clipping regions, then we do too.
		int clipping_element_ignore_clips = clipping_element->GetClippingIgnoreDepth();
		if (clipping_element_ignore_clips < 0)
			break;
		
		num_ignored_clips = Math::Max(num_ignored_clips, clipping_element_ignore_clips);

		// Climb the tree to this region's parent.
		clipping_element = clipping_element->GetParentNode();
	}
	
	return clip_dimensions.x >= 0 && clip_dimensions.y >= 0;
}