// 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; }