OLD | NEW |
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 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1153 if (hasOverflowClip() || style()->containsPaint()) | 1153 if (hasOverflowClip() || style()->containsPaint()) |
1154 result = overflowClipRect(LayoutPoint()); | 1154 result = overflowClipRect(LayoutPoint()); |
1155 | 1155 |
1156 if (hasClip()) | 1156 if (hasClip()) |
1157 result.intersect(clipRect(LayoutPoint())); | 1157 result.intersect(clipRect(LayoutPoint())); |
1158 | 1158 |
1159 return result; | 1159 return result; |
1160 } | 1160 } |
1161 | 1161 |
1162 bool LayoutBox::mapScrollingContentsRectToBoxSpace( | 1162 bool LayoutBox::mapScrollingContentsRectToBoxSpace( |
1163 LayoutRect& rect, | 1163 TransformState& transformState, |
| 1164 TransformState::TransformAccumulation accumulation, |
1164 VisualRectFlags visualRectFlags) const { | 1165 VisualRectFlags visualRectFlags) const { |
1165 if (!hasClipRelatedProperty()) | 1166 if (!hasClipRelatedProperty()) |
1166 return true; | 1167 return true; |
1167 | 1168 |
1168 if (hasOverflowClip()) { | 1169 if (hasOverflowClip()) { |
1169 LayoutSize offset = LayoutSize(-scrolledContentOffset()); | 1170 LayoutSize offset = LayoutSize(-scrolledContentOffset()); |
1170 rect.move(offset); | 1171 transformState.move(offset, accumulation); |
1171 } | 1172 } |
1172 | 1173 |
1173 // This won't work fully correctly for fixed-position elements, who should | 1174 // This won't work fully correctly for fixed-position elements, who should |
1174 // receive CSS clip but for whom the current object is not in the containing | 1175 // receive CSS clip but for whom the current object is not in the containing |
1175 // block chain. | 1176 // block chain. |
1176 LayoutRect clipRect = clippingRect(); | 1177 LayoutRect clipRect = clippingRect(); |
1177 | 1178 |
| 1179 transformState.flatten(); |
| 1180 LayoutRect rect(transformState.lastPlanarQuad().enclosingBoundingBox()); |
1178 bool doesIntersect; | 1181 bool doesIntersect; |
1179 if (visualRectFlags & EdgeInclusive) { | 1182 if (visualRectFlags & EdgeInclusive) { |
1180 doesIntersect = rect.inclusiveIntersect(clipRect); | 1183 doesIntersect = rect.inclusiveIntersect(clipRect); |
1181 } else { | 1184 } else { |
1182 rect.intersect(clipRect); | 1185 rect.intersect(clipRect); |
1183 doesIntersect = !rect.isEmpty(); | 1186 doesIntersect = !rect.isEmpty(); |
1184 } | 1187 } |
| 1188 transformState.setQuad(FloatQuad(FloatRect(rect))); |
1185 | 1189 |
1186 return doesIntersect; | 1190 return doesIntersect; |
1187 } | 1191 } |
1188 | 1192 |
1189 void LayoutBox::computeIntrinsicLogicalWidths( | 1193 void LayoutBox::computeIntrinsicLogicalWidths( |
1190 LayoutUnit& minLogicalWidth, | 1194 LayoutUnit& minLogicalWidth, |
1191 LayoutUnit& maxLogicalWidth) const { | 1195 LayoutUnit& maxLogicalWidth) const { |
1192 minLogicalWidth = minPreferredLogicalWidth() - borderAndPaddingLogicalWidth(); | 1196 minLogicalWidth = minPreferredLogicalWidth() - borderAndPaddingLogicalWidth(); |
1193 maxLogicalWidth = maxPreferredLogicalWidth() - borderAndPaddingLogicalWidth(); | 1197 maxLogicalWidth = maxPreferredLogicalWidth() - borderAndPaddingLogicalWidth(); |
1194 } | 1198 } |
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2301 LayoutRect LayoutBox::localVisualRect() const { | 2305 LayoutRect LayoutBox::localVisualRect() const { |
2302 if (style()->visibility() != EVisibility::kVisible) | 2306 if (style()->visibility() != EVisibility::kVisible) |
2303 return LayoutRect(); | 2307 return LayoutRect(); |
2304 | 2308 |
2305 if (hasMask() && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 2309 if (hasMask() && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
2306 return LayoutRect(layer()->boxForFilterOrMask()); | 2310 return LayoutRect(layer()->boxForFilterOrMask()); |
2307 return selfVisualOverflowRect(); | 2311 return selfVisualOverflowRect(); |
2308 } | 2312 } |
2309 | 2313 |
2310 void LayoutBox::inflateVisualRectForFilterUnderContainer( | 2314 void LayoutBox::inflateVisualRectForFilterUnderContainer( |
2311 LayoutRect& rect, | 2315 TransformState& transformState, |
2312 const LayoutObject& container, | 2316 const LayoutObject& container, |
2313 const LayoutBoxModelObject* ancestorToStopAt) const { | 2317 const LayoutBoxModelObject* ancestorToStopAt) const { |
| 2318 transformState.flatten(); |
2314 // Apply visual overflow caused by reflections and filters defined on objects | 2319 // Apply visual overflow caused by reflections and filters defined on objects |
2315 // between this object and container (not included) or ancestorToStopAt | 2320 // between this object and container (not included) or ancestorToStopAt |
2316 // (included). | 2321 // (included). |
2317 LayoutSize offsetFromContainer = this->offsetFromContainer(&container); | 2322 LayoutSize offsetFromContainer = this->offsetFromContainer(&container); |
2318 rect.move(offsetFromContainer); | 2323 transformState.move(offsetFromContainer); |
2319 for (LayoutObject* parent = this->parent(); parent && parent != container; | 2324 for (LayoutObject* parent = this->parent(); parent && parent != container; |
2320 parent = parent->parent()) { | 2325 parent = parent->parent()) { |
2321 if (parent->isBox()) { | 2326 if (parent->isBox()) { |
2322 // Convert rect into coordinate space of parent to apply parent's | 2327 // Convert rect into coordinate space of parent to apply parent's |
2323 // reflection and filter. | 2328 // reflection and filter. |
2324 LayoutSize parentOffset = parent->offsetFromAncestorContainer(&container); | 2329 LayoutSize parentOffset = parent->offsetFromAncestorContainer(&container); |
2325 rect.move(-parentOffset); | 2330 transformState.move(-parentOffset); |
2326 toLayoutBox(parent)->inflateVisualRectForFilter(rect); | 2331 toLayoutBox(parent)->inflateVisualRectForFilter(transformState); |
2327 rect.move(parentOffset); | 2332 transformState.move(parentOffset); |
2328 } | 2333 } |
2329 if (parent == ancestorToStopAt) | 2334 if (parent == ancestorToStopAt) |
2330 break; | 2335 break; |
2331 } | 2336 } |
2332 rect.move(-offsetFromContainer); | 2337 transformState.move(-offsetFromContainer); |
2333 } | 2338 } |
2334 | 2339 |
2335 bool LayoutBox::mapToVisualRectInAncestorSpace( | 2340 bool LayoutBox::mapToVisualRectInAncestorSpaceInternal( |
2336 const LayoutBoxModelObject* ancestor, | 2341 const LayoutBoxModelObject* ancestor, |
2337 LayoutRect& rect, | 2342 TransformState& transformState, |
2338 VisualRectFlags visualRectFlags) const { | 2343 VisualRectFlags visualRectFlags) const { |
2339 inflateVisualRectForFilter(rect); | 2344 inflateVisualRectForFilter(transformState); |
2340 | 2345 |
2341 if (ancestor == this) | 2346 if (ancestor == this) |
2342 return true; | 2347 return true; |
2343 | 2348 |
2344 AncestorSkipInfo skipInfo(ancestor, true); | 2349 AncestorSkipInfo skipInfo(ancestor, true); |
2345 LayoutObject* container = this->container(&skipInfo); | 2350 LayoutObject* container = this->container(&skipInfo); |
2346 LayoutBox* tableRowContainer = nullptr; | 2351 LayoutBox* tableRowContainer = nullptr; |
2347 // Skip table row because cells and rows are in the same coordinate space (see | 2352 // Skip table row because cells and rows are in the same coordinate space (see |
2348 // below, however for more comments about when |ancestor| is the table row). | 2353 // below, however for more comments about when |ancestor| is the table row). |
2349 if (isTableCell()) { | 2354 if (isTableCell()) { |
2350 DCHECK(container->isTableRow() && parentBox() == container); | 2355 DCHECK(container->isTableRow() && parentBox() == container); |
2351 if (container != ancestor) | 2356 if (container != ancestor) |
2352 container = container->parent(); | 2357 container = container->parent(); |
2353 else | 2358 else |
2354 tableRowContainer = toLayoutBox(container); | 2359 tableRowContainer = toLayoutBox(container); |
2355 } | 2360 } |
2356 if (!container) | 2361 if (!container) |
2357 return true; | 2362 return true; |
2358 | 2363 |
2359 if (skipInfo.filterSkipped()) | 2364 LayoutPoint containerOffset; |
2360 inflateVisualRectForFilterUnderContainer(rect, *container, ancestor); | 2365 if (container->isBox()) { |
| 2366 containerOffset.moveBy(physicalLocation(toLayoutBox(container))); |
2361 | 2367 |
2362 // We are now in our parent container's coordinate space. Apply our transform | |
2363 // to obtain a bounding box in the parent's coordinate space that encloses us. | |
2364 if (hasLayer() && layer()->transform()) { | |
2365 // Use enclosingIntRect because we cannot properly compute pixel snapping | |
2366 // for painted elements within the transform since we don't know the desired | |
2367 // subpixel accumulation at this point, and the transform may include a | |
2368 // scale. | |
2369 rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect))); | |
2370 } | |
2371 LayoutPoint topLeft = rect.location(); | |
2372 if (container->isBox()) { | |
2373 topLeft.moveBy(physicalLocation(toLayoutBox(container))); | |
2374 // If the row is the ancestor, however, add its offset back in. In effect, | 2368 // If the row is the ancestor, however, add its offset back in. In effect, |
2375 // this passes from the joint <td> / <tr> coordinate space to the parent | 2369 // this passes from the joint <td> / <tr> coordinate space to the parent |
2376 // space, then back to <tr> / <td>. | 2370 // space, then back to <tr> / <td>. |
2377 if (tableRowContainer) { | 2371 if (tableRowContainer) { |
2378 topLeft.moveBy( | 2372 containerOffset.moveBy( |
2379 -tableRowContainer->physicalLocation(toLayoutBox(container))); | 2373 -tableRowContainer->physicalLocation(toLayoutBox(container))); |
2380 } | 2374 } |
2381 } else if (container->isRuby()) { | 2375 } else if (container->isRuby()) { |
2382 // TODO(wkorman): Generalize Ruby specialization and/or document more | 2376 // TODO(wkorman): Generalize Ruby specialization and/or document more |
2383 // clearly. See the accompanying specialization in | 2377 // clearly. See the accompanying specialization in |
2384 // LayoutInline::mapToVisualRectInAncestorSpace. | 2378 // LayoutInline::mapToVisualRectInAncestorSpaceInternal. |
2385 topLeft.moveBy(physicalLocation()); | 2379 containerOffset.moveBy(physicalLocation()); |
2386 } else { | 2380 } else { |
2387 topLeft.moveBy(location()); | 2381 containerOffset.moveBy(location()); |
2388 } | 2382 } |
2389 | 2383 |
2390 const ComputedStyle& styleToUse = styleRef(); | 2384 const ComputedStyle& styleToUse = styleRef(); |
2391 EPosition position = styleToUse.position(); | 2385 EPosition position = styleToUse.position(); |
2392 if (position == EPosition::kAbsolute && container->isInFlowPositioned() && | 2386 if (position == EPosition::kAbsolute && container->isInFlowPositioned() && |
2393 container->isLayoutInline()) { | 2387 container->isLayoutInline()) { |
2394 topLeft += | 2388 containerOffset.move( |
2395 toLayoutInline(container)->offsetForInFlowPositionedInline(*this); | 2389 toLayoutInline(container)->offsetForInFlowPositionedInline(*this)); |
2396 } else if (styleToUse.hasInFlowPosition() && layer()) { | 2390 } else if (styleToUse.hasInFlowPosition() && layer()) { |
2397 // Apply the relative position offset when invalidating a rectangle. The | 2391 // Apply the relative position offset when invalidating a rectangle. The |
2398 // layer is translated, but the layout box isn't, so we need to do this to | 2392 // layer is translated, but the layout box isn't, so we need to do this to |
2399 // get the right dirty rect. Since this is called from | 2393 // get the right dirty rect. Since this is called from |
2400 // LayoutObject::setStyle, the relative position flag on the LayoutObject | 2394 // LayoutObject::setStyle, the relative position flag on the LayoutObject |
2401 // has been cleared, so use the one on the style(). | 2395 // has been cleared, so use the one on the style(). |
2402 topLeft += layer()->offsetForInFlowPosition(); | 2396 containerOffset.move(layer()->offsetForInFlowPosition()); |
| 2397 } |
| 2398 |
| 2399 bool preserve3D = container->style()->preserves3D() || style()->preserves3D(); |
| 2400 |
| 2401 TransformState::TransformAccumulation accumulation = |
| 2402 preserve3D ? TransformState::AccumulateTransform |
| 2403 : TransformState::FlattenTransform; |
| 2404 |
| 2405 if (skipInfo.filterSkipped()) { |
| 2406 inflateVisualRectForFilterUnderContainer(transformState, *container, |
| 2407 ancestor); |
| 2408 } |
| 2409 |
| 2410 // We are now in our parent container's coordinate space. Apply our transform |
| 2411 // to obtain a bounding box in the parent's coordinate space that encloses us. |
| 2412 if (shouldUseTransformFromContainer(container)) { |
| 2413 TransformationMatrix t; |
| 2414 getTransformFromContainer(container, toLayoutSize(containerOffset), t); |
| 2415 transformState.applyTransform(t, accumulation); |
| 2416 |
| 2417 // Use enclosingBoundingBox because we cannot properly compute pixel |
| 2418 // snapping for painted elements within the transform since we don't know |
| 2419 // the desired subpixel accumulation at this point, and the transform may |
| 2420 // include a scale. |
| 2421 if (!preserve3D) { |
| 2422 transformState.flatten(); |
| 2423 transformState.setQuad( |
| 2424 FloatQuad(transformState.lastPlanarQuad().enclosingBoundingBox())); |
| 2425 } |
| 2426 } else { |
| 2427 transformState.move(toLayoutSize(containerOffset), accumulation); |
2403 } | 2428 } |
2404 | 2429 |
2405 // FIXME: We ignore the lightweight clipping rect that controls use, since if | 2430 // FIXME: We ignore the lightweight clipping rect that controls use, since if |
2406 // |o| is in mid-layout, its controlClipRect will be wrong. For overflow clip | 2431 // |o| is in mid-layout, its controlClipRect will be wrong. For overflow clip |
2407 // we use the values cached by the layer. | 2432 // we use the values cached by the layer. |
2408 rect.setLocation(topLeft); | |
2409 | |
2410 if (container->isBox() && container != ancestor && | 2433 if (container->isBox() && container != ancestor && |
2411 !toLayoutBox(container)->mapScrollingContentsRectToBoxSpace( | 2434 !toLayoutBox(container)->mapScrollingContentsRectToBoxSpace( |
2412 rect, visualRectFlags)) | 2435 transformState, accumulation, visualRectFlags)) |
2413 return false; | 2436 return false; |
2414 | 2437 |
2415 if (skipInfo.ancestorSkipped()) { | 2438 if (skipInfo.ancestorSkipped()) { |
2416 // If the ancestor is below the container, then we need to map the rect into | 2439 // If the ancestor is below the container, then we need to map the rect into |
2417 // ancestor's coordinates. | 2440 // ancestor's coordinates. |
2418 LayoutSize containerOffset = | 2441 LayoutSize containerOffset = |
2419 ancestor->offsetFromAncestorContainer(container); | 2442 ancestor->offsetFromAncestorContainer(container); |
2420 rect.move(-containerOffset); | 2443 transformState.move(-containerOffset, accumulation); |
2421 // If the ancestor is fixed, then the rect is already in its coordinates so | 2444 // If the ancestor is fixed, then the rect is already in its coordinates so |
2422 // doesn't need viewport-adjusting. | 2445 // doesn't need viewport-adjusting. |
2423 if (ancestor->style()->position() != EPosition::kFixed && | 2446 if (ancestor->style()->position() != EPosition::kFixed && |
2424 container->isLayoutView() && position == EPosition::kFixed) | 2447 container->isLayoutView() && position == EPosition::kFixed) { |
2425 rect.move(toLayoutView(container)->offsetForFixedPosition(true)); | 2448 transformState.move(toLayoutView(container)->offsetForFixedPosition(true), |
| 2449 accumulation); |
| 2450 } |
2426 return true; | 2451 return true; |
2427 } | 2452 } |
2428 | 2453 |
2429 if (container->isLayoutView()) | 2454 if (container->isLayoutView()) |
2430 return toLayoutView(container)->mapToVisualRectInAncestorSpace( | 2455 return toLayoutView(container)->mapToVisualRectInAncestorSpaceInternal( |
2431 ancestor, rect, position == EPosition::kFixed ? IsFixed : 0, | 2456 ancestor, transformState, position == EPosition::kFixed ? IsFixed : 0, |
2432 visualRectFlags); | 2457 visualRectFlags); |
2433 else | 2458 else |
2434 return container->mapToVisualRectInAncestorSpace(ancestor, rect, | 2459 return container->mapToVisualRectInAncestorSpaceInternal( |
2435 visualRectFlags); | 2460 ancestor, transformState, visualRectFlags); |
2436 } | 2461 } |
2437 | 2462 |
2438 void LayoutBox::inflateVisualRectForFilter(LayoutRect& visualRect) const { | 2463 void LayoutBox::inflateVisualRectForFilter( |
2439 if (layer() && layer()->hasFilterInducingProperty()) | 2464 TransformState& transformState) const { |
2440 visualRect = layer()->mapLayoutRectForFilter(visualRect); | 2465 if (!layer() || !layer()->hasFilterInducingProperty()) |
| 2466 return; |
| 2467 |
| 2468 transformState.flatten(); |
| 2469 LayoutRect rect(transformState.lastPlanarQuad().boundingBox()); |
| 2470 transformState.setQuad( |
| 2471 FloatQuad(FloatRect(layer()->mapLayoutRectForFilter(rect)))); |
2441 } | 2472 } |
2442 | 2473 |
2443 void LayoutBox::updateLogicalWidth() { | 2474 void LayoutBox::updateLogicalWidth() { |
2444 LogicalExtentComputedValues computedValues; | 2475 LogicalExtentComputedValues computedValues; |
2445 computeLogicalWidth(computedValues); | 2476 computeLogicalWidth(computedValues); |
2446 | 2477 |
2447 setLogicalWidth(computedValues.m_extent); | 2478 setLogicalWidth(computedValues.m_extent); |
2448 setLogicalLeft(computedValues.m_position); | 2479 setLogicalLeft(computedValues.m_position); |
2449 setMarginStart(computedValues.m_margins.m_start); | 2480 setMarginStart(computedValues.m_margins.m_start); |
2450 setMarginEnd(computedValues.m_margins.m_end); | 2481 setMarginEnd(computedValues.m_margins.m_end); |
(...skipping 3263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5714 | 5745 |
5715 void LayoutBox::MutableForPainting:: | 5746 void LayoutBox::MutableForPainting:: |
5716 savePreviousContentBoxSizeAndLayoutOverflowRect() { | 5747 savePreviousContentBoxSizeAndLayoutOverflowRect() { |
5717 auto& rareData = layoutBox().ensureRareData(); | 5748 auto& rareData = layoutBox().ensureRareData(); |
5718 rareData.m_hasPreviousContentBoxSizeAndLayoutOverflowRect = true; | 5749 rareData.m_hasPreviousContentBoxSizeAndLayoutOverflowRect = true; |
5719 rareData.m_previousContentBoxSize = layoutBox().contentBoxRect().size(); | 5750 rareData.m_previousContentBoxSize = layoutBox().contentBoxRect().size(); |
5720 rareData.m_previousLayoutOverflowRect = layoutBox().layoutOverflowRect(); | 5751 rareData.m_previousLayoutOverflowRect = layoutBox().layoutOverflowRect(); |
5721 } | 5752 } |
5722 | 5753 |
5723 } // namespace blink | 5754 } // namespace blink |
OLD | NEW |