Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutBox.cpp

Issue 2727093002: Account for perspective and preserve-3d in mapToVisualRectInAncestorSpace (Closed)
Patch Set: none Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/LayoutBox.cpp
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 85e242f342eff412113a0fca91f4dfa3ec93e381..b5a5cd99d2179e28add1be0e9df42ee540b04314 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -1160,14 +1160,15 @@ LayoutRect LayoutBox::clippingRect() const {
}
bool LayoutBox::mapScrollingContentsRectToBoxSpace(
- LayoutRect& rect,
+ TransformState& transformState,
+ TransformState::TransformAccumulation accumulation,
VisualRectFlags visualRectFlags) const {
if (!hasClipRelatedProperty())
return true;
if (hasOverflowClip()) {
LayoutSize offset = LayoutSize(-scrolledContentOffset());
- rect.move(offset);
+ transformState.move(offset, accumulation);
}
// This won't work fully correctly for fixed-position elements, who should
@@ -1175,6 +1176,8 @@ bool LayoutBox::mapScrollingContentsRectToBoxSpace(
// block chain.
LayoutRect clipRect = clippingRect();
+ transformState.flatten();
+ LayoutRect rect(transformState.lastPlanarQuad().enclosingBoundingBox());
bool doesIntersect;
if (visualRectFlags & EdgeInclusive) {
doesIntersect = rect.inclusiveIntersect(clipRect);
@@ -1182,6 +1185,7 @@ bool LayoutBox::mapScrollingContentsRectToBoxSpace(
rect.intersect(clipRect);
doesIntersect = !rect.isEmpty();
}
+ transformState.setQuad(FloatQuad(FloatRect(rect)));
return doesIntersect;
}
@@ -2308,35 +2312,36 @@ LayoutRect LayoutBox::localVisualRect() const {
}
void LayoutBox::inflateVisualRectForFilterUnderContainer(
- LayoutRect& rect,
+ TransformState& transformState,
const LayoutObject& container,
const LayoutBoxModelObject* ancestorToStopAt) const {
+ transformState.flatten();
// Apply visual overflow caused by reflections and filters defined on objects
// between this object and container (not included) or ancestorToStopAt
// (included).
LayoutSize offsetFromContainer = this->offsetFromContainer(&container);
- rect.move(offsetFromContainer);
+ transformState.move(offsetFromContainer);
for (LayoutObject* parent = this->parent(); parent && parent != container;
parent = parent->parent()) {
if (parent->isBox()) {
// Convert rect into coordinate space of parent to apply parent's
// reflection and filter.
LayoutSize parentOffset = parent->offsetFromAncestorContainer(&container);
- rect.move(-parentOffset);
- toLayoutBox(parent)->inflateVisualRectForFilter(rect);
- rect.move(parentOffset);
+ transformState.move(-parentOffset);
+ toLayoutBox(parent)->inflateVisualRectForFilter(transformState);
+ transformState.move(parentOffset);
}
if (parent == ancestorToStopAt)
break;
}
- rect.move(-offsetFromContainer);
+ transformState.move(-offsetFromContainer);
}
-bool LayoutBox::mapToVisualRectInAncestorSpace(
+bool LayoutBox::mapToVisualRectInAncestorSpaceInternal(
const LayoutBoxModelObject* ancestor,
- LayoutRect& rect,
+ TransformState& transformState,
VisualRectFlags visualRectFlags) const {
- inflateVisualRectForFilter(rect);
+ inflateVisualRectForFilter(transformState);
if (ancestor == this)
return true;
@@ -2356,60 +2361,78 @@ bool LayoutBox::mapToVisualRectInAncestorSpace(
if (!container)
return true;
- if (skipInfo.filterSkipped())
- inflateVisualRectForFilterUnderContainer(rect, *container, ancestor);
-
- // We are now in our parent container's coordinate space. Apply our transform
- // to obtain a bounding box in the parent's coordinate space that encloses us.
- if (hasLayer() && layer()->transform()) {
- // Use enclosingIntRect because we cannot properly compute pixel snapping
- // for painted elements within the transform since we don't know the desired
- // subpixel accumulation at this point, and the transform may include a
- // scale.
- rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect)));
- }
- LayoutPoint topLeft = rect.location();
+ LayoutPoint containerOffset;
if (container->isBox()) {
- topLeft.moveBy(physicalLocation(toLayoutBox(container)));
+ containerOffset.moveBy(physicalLocation(toLayoutBox(container)));
+
// If the row is the ancestor, however, add its offset back in. In effect,
// this passes from the joint <td> / <tr> coordinate space to the parent
// space, then back to <tr> / <td>.
if (tableRowContainer) {
- topLeft.moveBy(
+ containerOffset.moveBy(
-tableRowContainer->physicalLocation(toLayoutBox(container)));
}
} else if (container->isRuby()) {
// TODO(wkorman): Generalize Ruby specialization and/or document more
// clearly. See the accompanying specialization in
- // LayoutInline::mapToVisualRectInAncestorSpace.
- topLeft.moveBy(physicalLocation());
+ // LayoutInline::mapToVisualRectInAncestorSpaceInternal.
+ containerOffset.moveBy(physicalLocation());
} else {
- topLeft.moveBy(location());
+ containerOffset.moveBy(location());
}
const ComputedStyle& styleToUse = styleRef();
EPosition position = styleToUse.position();
if (position == EPosition::kAbsolute && container->isInFlowPositioned() &&
container->isLayoutInline()) {
- topLeft +=
- toLayoutInline(container)->offsetForInFlowPositionedInline(*this);
+ containerOffset.move(
+ toLayoutInline(container)->offsetForInFlowPositionedInline(*this));
} else if (styleToUse.hasInFlowPosition() && layer()) {
// Apply the relative position offset when invalidating a rectangle. The
// layer is translated, but the layout box isn't, so we need to do this to
// get the right dirty rect. Since this is called from
// LayoutObject::setStyle, the relative position flag on the LayoutObject
// has been cleared, so use the one on the style().
- topLeft += layer()->offsetForInFlowPosition();
+ containerOffset.move(layer()->offsetForInFlowPosition());
+ }
+
+ bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
+
+ TransformState::TransformAccumulation accumulation =
+ preserve3D ? TransformState::AccumulateTransform
+ : TransformState::FlattenTransform;
+
+ if (skipInfo.filterSkipped()) {
+ inflateVisualRectForFilterUnderContainer(transformState, *container,
+ ancestor);
+ }
+
+ // We are now in our parent container's coordinate space. Apply our transform
+ // to obtain a bounding box in the parent's coordinate space that encloses us.
+ if (shouldUseTransformFromContainer(container)) {
+ TransformationMatrix t;
+ getTransformFromContainer(container, toLayoutSize(containerOffset), t);
+ transformState.applyTransform(t, accumulation);
+
+ // Use enclosingBoundingBox because we cannot properly compute pixel
+ // snapping for painted elements within the transform since we don't know
+ // the desired subpixel accumulation at this point, and the transform may
+ // include a scale.
+ if (!preserve3D) {
+ transformState.flatten();
+ transformState.setQuad(
+ FloatQuad(transformState.lastPlanarQuad().enclosingBoundingBox()));
+ }
+ } else {
+ transformState.move(toLayoutSize(containerOffset), accumulation);
}
// FIXME: We ignore the lightweight clipping rect that controls use, since if
// |o| is in mid-layout, its controlClipRect will be wrong. For overflow clip
// we use the values cached by the layer.
- rect.setLocation(topLeft);
-
if (container->isBox() && container != ancestor &&
!toLayoutBox(container)->mapScrollingContentsRectToBoxSpace(
- rect, visualRectFlags))
+ transformState, accumulation, visualRectFlags))
return false;
if (skipInfo.ancestorSkipped()) {
@@ -2417,27 +2440,35 @@ bool LayoutBox::mapToVisualRectInAncestorSpace(
// ancestor's coordinates.
LayoutSize containerOffset =
ancestor->offsetFromAncestorContainer(container);
- rect.move(-containerOffset);
+ transformState.move(-containerOffset, accumulation);
// If the ancestor is fixed, then the rect is already in its coordinates so
// doesn't need viewport-adjusting.
if (ancestor->style()->position() != EPosition::kFixed &&
- container->isLayoutView() && position == EPosition::kFixed)
- rect.move(toLayoutView(container)->offsetForFixedPosition(true));
+ container->isLayoutView() && position == EPosition::kFixed) {
+ transformState.move(toLayoutView(container)->offsetForFixedPosition(true),
+ accumulation);
+ }
return true;
}
if (container->isLayoutView())
- return toLayoutView(container)->mapToVisualRectInAncestorSpace(
- ancestor, rect, position == EPosition::kFixed ? IsFixed : 0,
+ return toLayoutView(container)->mapToVisualRectInAncestorSpaceInternal(
+ ancestor, transformState, position == EPosition::kFixed ? IsFixed : 0,
visualRectFlags);
else
- return container->mapToVisualRectInAncestorSpace(ancestor, rect,
- visualRectFlags);
+ return container->mapToVisualRectInAncestorSpaceInternal(
+ ancestor, transformState, visualRectFlags);
}
-void LayoutBox::inflateVisualRectForFilter(LayoutRect& visualRect) const {
- if (layer() && layer()->hasFilterInducingProperty())
- visualRect = layer()->mapLayoutRectForFilter(visualRect);
+void LayoutBox::inflateVisualRectForFilter(
+ TransformState& transformState) const {
+ if (!layer() || !layer()->hasFilterInducingProperty())
+ return;
+
+ transformState.flatten();
+ LayoutRect rect(transformState.lastPlanarQuad().boundingBox());
+ transformState.setQuad(
+ FloatQuad(FloatRect(layer()->mapLayoutRectForFilter(rect))));
}
void LayoutBox::updateLogicalWidth() {
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutBox.h ('k') | third_party/WebKit/Source/core/layout/LayoutFlowThread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698