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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBox.cpp

Issue 2808613002: Apply container offset and scroll between transform and container perspective. (Closed)
Patch Set: none Created 3 years, 8 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc.
7 * All rights reserved. 7 * All rights reserved.
8 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 8 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 LayoutRect result = LayoutRect(LayoutRect::InfiniteIntRect()); 1161 LayoutRect result = LayoutRect(LayoutRect::InfiniteIntRect());
1162 if (ShouldClipOverflow()) 1162 if (ShouldClipOverflow())
1163 result = OverflowClipRect(LayoutPoint()); 1163 result = OverflowClipRect(LayoutPoint());
1164 1164
1165 if (HasClip()) 1165 if (HasClip())
1166 result.Intersect(ClipRect(LayoutPoint())); 1166 result.Intersect(ClipRect(LayoutPoint()));
1167 1167
1168 return result; 1168 return result;
1169 } 1169 }
1170 1170
1171 bool LayoutBox::MapVisualRectToContainer(
1172 const LayoutObject* container_object,
1173 const LayoutPoint& container_offset,
1174 const LayoutObject* ancestor,
1175 VisualRectFlags visual_rect_flags,
1176 TransformState& transform_state) const {
1177 bool preserve3D = container_object->Style()->Preserves3D();
1178
1179 TransformState::TransformAccumulation accumulation =
1180 preserve3D ? TransformState::kAccumulateTransform
1181 : TransformState::kFlattenTransform;
1182
1183 // If there is no transform on this box, adjust for container offset and
1184 // container scrolling, then apply container clip.
1185 if (!ShouldUseTransformFromContainer(container_object)) {
1186 transform_state.MoveBy(container_offset, accumulation);
1187 if (container_object->IsBox() && container_object != ancestor &&
1188 !ToLayoutBox(container_object)
1189 ->MapScrollingContentsRectToBoxSpace(transform_state, accumulation,
1190 visual_rect_flags))
1191 return false;
1192 return true;
1193 }
1194
1195 // Otherwise, apply the following:
1196 // 1. Transform.
1197 // 2. Container offset.
1198 // 3. Container scroll offset.
1199 // 4. Perspective applied by container.
1200 // 5. Transform flattening.
1201 // 6. Expansion for pixel snapping.
1202 // 7. Container clip.
1203
1204 // 1. Transform.
1205 TransformationMatrix transform;
1206 if (Layer() && Layer()->Transform())
1207 transform.Multiply(Layer()->CurrentTransform());
1208
1209 // 2. Container offset.
1210 transform.TranslateRight(container_offset.X().ToFloat(),
1211 container_offset.Y().ToFloat());
1212
1213 // 3. Container scroll offset.
1214 if (container_object->IsBox() && container_object != ancestor &&
1215 container_object->HasOverflowClip()) {
1216 IntSize offset = -ToLayoutBox(container_object)->ScrolledContentOffset();
1217 transform.TranslateRight(offset.Width(), offset.Height());
1218 }
1219
1220 // 4. Perspective applied by container.
1221 if (container_object && container_object->HasLayer() &&
1222 container_object->Style()->HasPerspective()) {
1223 // Perspective on the container affects us, so we have to factor it in here.
1224 DCHECK(container_object->HasLayer());
1225 FloatPoint perspective_origin =
1226 ToLayoutBoxModelObject(container_object)->Layer()->PerspectiveOrigin();
1227
1228 TransformationMatrix perspective_matrix;
1229 perspective_matrix.ApplyPerspective(
1230 container_object->Style()->Perspective());
1231 perspective_matrix.ApplyTransformOrigin(perspective_origin.X(),
1232 perspective_origin.Y(), 0);
1233
1234 // TODO(chrishtr): This applies perspective before the transform. Why?
chrishtr 2017/04/10 19:37:35 ??? Weird.
trchen 2017/04/10 21:15:18 This looks correct. See explanation above.
1235 transform = perspective_matrix * transform;
1236 }
1237
1238 // 5. Transform flattening.
1239 transform_state.ApplyTransform(transform, accumulation);
1240
1241 // 6. Expansion for pixel snapping.
1242 // Use enclosingBoundingBox because we cannot properly compute pixel
1243 // snapping for painted elements within the transform since we don't know
1244 // the desired subpixel accumulation at this point, and the transform may
1245 // include a scale.
1246 if (!preserve3D) {
1247 transform_state.Flatten();
1248 transform_state.SetQuad(
1249 FloatQuad(transform_state.LastPlanarQuad().EnclosingBoundingBox()));
1250 }
1251
1252 // 7. Container clip.
1253 if (container_object->IsBox() && container_object != ancestor &&
1254 container_object->HasClipRelatedProperty()) {
1255 return ToLayoutBox(container_object)
1256 ->ApplyBoxClips(transform_state, accumulation, visual_rect_flags);
1257 }
1258
1259 return true;
1260 }
1261
1171 bool LayoutBox::MapScrollingContentsRectToBoxSpace( 1262 bool LayoutBox::MapScrollingContentsRectToBoxSpace(
1172 TransformState& transform_state, 1263 TransformState& transform_state,
1173 TransformState::TransformAccumulation accumulation, 1264 TransformState::TransformAccumulation accumulation,
1174 VisualRectFlags visual_rect_flags) const { 1265 VisualRectFlags visual_rect_flags) const {
1175 if (!HasClipRelatedProperty()) 1266 if (!HasClipRelatedProperty())
1176 return true; 1267 return true;
1177 1268
1178 if (HasOverflowClip()) { 1269 if (HasOverflowClip()) {
1179 LayoutSize offset = LayoutSize(-ScrolledContentOffset()); 1270 LayoutSize offset = LayoutSize(-ScrolledContentOffset());
1180 transform_state.Move(offset, accumulation); 1271 transform_state.Move(offset, accumulation);
1181 } 1272 }
1182 1273
1274 return ApplyBoxClips(transform_state, accumulation, visual_rect_flags);
1275 }
1276
1277 bool LayoutBox::ApplyBoxClips(
1278 TransformState& transform_state,
1279 TransformState::TransformAccumulation accumulation,
1280 VisualRectFlags visual_rect_flags) const {
1183 // This won't work fully correctly for fixed-position elements, who should 1281 // This won't work fully correctly for fixed-position elements, who should
1184 // receive CSS clip but for whom the current object is not in the containing 1282 // receive CSS clip but for whom the current object is not in the containing
1185 // block chain. 1283 // block chain.
1186 LayoutRect clip_rect = ClippingRect(); 1284 LayoutRect clip_rect = ClippingRect();
1187 1285
1188 transform_state.Flatten(); 1286 transform_state.Flatten();
1189 LayoutRect rect(transform_state.LastPlanarQuad().EnclosingBoundingBox()); 1287 LayoutRect rect(transform_state.LastPlanarQuad().EnclosingBoundingBox());
1190 bool does_intersect; 1288 bool does_intersect;
1191 if (visual_rect_flags & kEdgeInclusive) { 1289 if (visual_rect_flags & kEdgeInclusive) {
1192 does_intersect = rect.InclusiveIntersect(clip_rect); 1290 does_intersect = rect.InclusiveIntersect(clip_rect);
(...skipping 1229 matching lines...) Expand 10 before | Expand all | Expand 10 after
2422 ToLayoutInline(container)->OffsetForInFlowPositionedInline(*this)); 2520 ToLayoutInline(container)->OffsetForInFlowPositionedInline(*this));
2423 } else if (style_to_use.HasInFlowPosition() && Layer()) { 2521 } else if (style_to_use.HasInFlowPosition() && Layer()) {
2424 // Apply the relative position offset when invalidating a rectangle. The 2522 // Apply the relative position offset when invalidating a rectangle. The
2425 // layer is translated, but the layout box isn't, so we need to do this to 2523 // layer is translated, but the layout box isn't, so we need to do this to
2426 // get the right dirty rect. Since this is called from 2524 // get the right dirty rect. Since this is called from
2427 // LayoutObject::setStyle, the relative position flag on the LayoutObject 2525 // LayoutObject::setStyle, the relative position flag on the LayoutObject
2428 // has been cleared, so use the one on the style(). 2526 // has been cleared, so use the one on the style().
2429 container_offset.Move(Layer()->OffsetForInFlowPosition()); 2527 container_offset.Move(Layer()->OffsetForInFlowPosition());
2430 } 2528 }
2431 2529
2432 bool preserve3d = container->Style()->Preserves3D();
2433
2434 TransformState::TransformAccumulation accumulation =
2435 preserve3d ? TransformState::kAccumulateTransform
2436 : TransformState::kFlattenTransform;
2437
2438 if (skip_info.FilterSkipped()) { 2530 if (skip_info.FilterSkipped()) {
2439 InflateVisualRectForFilterUnderContainer(transform_state, *container, 2531 InflateVisualRectForFilterUnderContainer(transform_state, *container,
2440 ancestor); 2532 ancestor);
2441 } 2533 }
2442 2534
2443 // We are now in our parent container's coordinate space. Apply our transform 2535 if (!MapVisualRectToContainer(container, container_offset, ancestor,
2444 // to obtain a bounding box in the parent's coordinate space that encloses us. 2536 visual_rect_flags, transform_state))
2445 if (ShouldUseTransformFromContainer(container)) {
2446 TransformationMatrix t;
2447 GetTransformFromContainer(container, ToLayoutSize(container_offset), t);
2448 transform_state.ApplyTransform(t, accumulation);
2449
2450 // Use enclosingBoundingBox because we cannot properly compute pixel
2451 // snapping for painted elements within the transform since we don't know
2452 // the desired subpixel accumulation at this point, and the transform may
2453 // include a scale.
2454 if (!preserve3d) {
2455 transform_state.Flatten();
2456 transform_state.SetQuad(
2457 FloatQuad(transform_state.LastPlanarQuad().EnclosingBoundingBox()));
2458 }
2459 } else {
2460 transform_state.Move(ToLayoutSize(container_offset), accumulation);
2461 }
2462
2463 // FIXME: We ignore the lightweight clipping rect that controls use, since if
2464 // |o| is in mid-layout, its controlClipRect will be wrong. For overflow clip
2465 // we use the values cached by the layer.
2466 if (container->IsBox() && container != ancestor &&
2467 !ToLayoutBox(container)->MapScrollingContentsRectToBoxSpace(
2468 transform_state, accumulation, visual_rect_flags))
2469 return false; 2537 return false;
2470 2538
2471 if (skip_info.AncestorSkipped()) { 2539 if (skip_info.AncestorSkipped()) {
2540 bool preserve3D = container->Style()->Preserves3D();
2541 TransformState::TransformAccumulation accumulation =
2542 preserve3D ? TransformState::kAccumulateTransform
2543 : TransformState::kFlattenTransform;
2544
2472 // If the ancestor is below the container, then we need to map the rect into 2545 // If the ancestor is below the container, then we need to map the rect into
2473 // ancestor's coordinates. 2546 // ancestor's coordinates.
2474 LayoutSize container_offset = 2547 LayoutSize container_offset =
2475 ancestor->OffsetFromAncestorContainer(container); 2548 ancestor->OffsetFromAncestorContainer(container);
2476 transform_state.Move(-container_offset, accumulation); 2549 transform_state.Move(-container_offset, accumulation);
2477 // If the ancestor is fixed, then the rect is already in its coordinates so 2550 // If the ancestor is fixed, then the rect is already in its coordinates so
2478 // doesn't need viewport-adjusting. 2551 // doesn't need viewport-adjusting.
2479 if (ancestor->Style()->GetPosition() != EPosition::kFixed && 2552 if (ancestor->Style()->GetPosition() != EPosition::kFixed &&
2480 container->IsLayoutView() && position == EPosition::kFixed) { 2553 container->IsLayoutView() && position == EPosition::kFixed) {
2481 transform_state.Move( 2554 transform_state.Move(
(...skipping 3337 matching lines...) Expand 10 before | Expand all | Expand 10 after
5819 void LayoutBox::MutableForPainting:: 5892 void LayoutBox::MutableForPainting::
5820 SavePreviousContentBoxSizeAndLayoutOverflowRect() { 5893 SavePreviousContentBoxSizeAndLayoutOverflowRect() {
5821 auto& rare_data = GetLayoutBox().EnsureRareData(); 5894 auto& rare_data = GetLayoutBox().EnsureRareData();
5822 rare_data.has_previous_content_box_size_and_layout_overflow_rect_ = true; 5895 rare_data.has_previous_content_box_size_and_layout_overflow_rect_ = true;
5823 rare_data.previous_content_box_size_ = GetLayoutBox().ContentBoxRect().size(); 5896 rare_data.previous_content_box_size_ = GetLayoutBox().ContentBoxRect().size();
5824 rare_data.previous_layout_overflow_rect_ = 5897 rare_data.previous_layout_overflow_rect_ =
5825 GetLayoutBox().LayoutOverflowRect(); 5898 GetLayoutBox().LayoutOverflowRect();
5826 } 5899 }
5827 5900
5828 } // namespace blink 5901 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698