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 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2321 LayoutRect LayoutBox::localVisualRect() const { | 2325 LayoutRect LayoutBox::localVisualRect() const { |
2322 if (style()->visibility() != EVisibility::kVisible) | 2326 if (style()->visibility() != EVisibility::kVisible) |
2323 return LayoutRect(); | 2327 return LayoutRect(); |
2324 | 2328 |
2325 if (hasMask() && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 2329 if (hasMask() && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
2326 return LayoutRect(layer()->boxForFilterOrMask()); | 2330 return LayoutRect(layer()->boxForFilterOrMask()); |
2327 return selfVisualOverflowRect(); | 2331 return selfVisualOverflowRect(); |
2328 } | 2332 } |
2329 | 2333 |
2330 void LayoutBox::inflateVisualRectForFilterUnderContainer( | 2334 void LayoutBox::inflateVisualRectForFilterUnderContainer( |
2331 LayoutRect& rect, | 2335 TransformState& transformState, |
2332 const LayoutObject& container, | 2336 const LayoutObject& container, |
2333 const LayoutBoxModelObject* ancestorToStopAt) const { | 2337 const LayoutBoxModelObject* ancestorToStopAt) const { |
2338 transformState.flatten(); | |
2334 // Apply visual overflow caused by reflections and filters defined on objects | 2339 // Apply visual overflow caused by reflections and filters defined on objects |
2335 // between this object and container (not included) or ancestorToStopAt | 2340 // between this object and container (not included) or ancestorToStopAt |
2336 // (included). | 2341 // (included). |
2337 LayoutSize offsetFromContainer = this->offsetFromContainer(&container); | 2342 LayoutSize offsetFromContainer = this->offsetFromContainer(&container); |
2338 rect.move(offsetFromContainer); | 2343 transformState.move(offsetFromContainer); |
2339 for (LayoutObject* parent = this->parent(); parent && parent != container; | 2344 for (LayoutObject* parent = this->parent(); parent && parent != container; |
2340 parent = parent->parent()) { | 2345 parent = parent->parent()) { |
2341 if (parent->isBox()) { | 2346 if (parent->isBox()) { |
2342 // Convert rect into coordinate space of parent to apply parent's | 2347 // Convert rect into coordinate space of parent to apply parent's |
2343 // reflection and filter. | 2348 // reflection and filter. |
2344 LayoutSize parentOffset = parent->offsetFromAncestorContainer(&container); | 2349 LayoutSize parentOffset = parent->offsetFromAncestorContainer(&container); |
2345 rect.move(-parentOffset); | 2350 transformState.move(-parentOffset); |
2346 toLayoutBox(parent)->inflateVisualRectForFilter(rect); | 2351 toLayoutBox(parent)->inflateVisualRectForFilter(transformState); |
2347 rect.move(parentOffset); | 2352 transformState.move(parentOffset); |
2348 } | 2353 } |
2349 if (parent == ancestorToStopAt) | 2354 if (parent == ancestorToStopAt) |
2350 break; | 2355 break; |
2351 } | 2356 } |
2352 rect.move(-offsetFromContainer); | 2357 transformState.move(-offsetFromContainer); |
2353 } | 2358 } |
2354 | 2359 |
2355 bool LayoutBox::mapToVisualRectInAncestorSpace( | 2360 bool LayoutBox::mapToVisualRectInAncestorSpaceInternal( |
2356 const LayoutBoxModelObject* ancestor, | 2361 const LayoutBoxModelObject* ancestor, |
2357 LayoutRect& rect, | 2362 TransformState& transformState, |
2358 VisualRectFlags visualRectFlags) const { | 2363 VisualRectFlags visualRectFlags) const { |
2359 inflateVisualRectForFilter(rect); | 2364 inflateVisualRectForFilter(transformState); |
2360 | 2365 |
2361 if (ancestor == this) | 2366 if (ancestor == this) |
2362 return true; | 2367 return true; |
2363 | 2368 |
2364 AncestorSkipInfo skipInfo(ancestor, true); | 2369 AncestorSkipInfo skipInfo(ancestor, true); |
2365 LayoutObject* container = this->container(&skipInfo); | 2370 LayoutObject* container = this->container(&skipInfo); |
2366 LayoutBox* tableRowContainer = nullptr; | 2371 LayoutBox* tableRowContainer = nullptr; |
2367 // Skip table row because cells and rows are in the same coordinate space (see | 2372 // Skip table row because cells and rows are in the same coordinate space (see |
2368 // below, however for more comments about when |ancestor| is the table row). | 2373 // below, however for more comments about when |ancestor| is the table row). |
2369 if (isTableCell()) { | 2374 if (isTableCell()) { |
2370 DCHECK(container->isTableRow() && parentBox() == container); | 2375 DCHECK(container->isTableRow() && parentBox() == container); |
2371 if (container != ancestor) | 2376 if (container != ancestor) |
2372 container = container->parent(); | 2377 container = container->parent(); |
2373 else | 2378 else |
2374 tableRowContainer = toLayoutBox(container); | 2379 tableRowContainer = toLayoutBox(container); |
2375 } | 2380 } |
2376 if (!container) | 2381 if (!container) |
2377 return true; | 2382 return true; |
2378 | 2383 |
2379 if (skipInfo.filterSkipped()) | 2384 LayoutPoint containerOffset; |
2380 inflateVisualRectForFilterUnderContainer(rect, *container, ancestor); | 2385 if (container->isBox()) { |
2386 containerOffset.moveBy(physicalLocation(toLayoutBox(container))); | |
2381 | 2387 |
2382 // We are now in our parent container's coordinate space. Apply our transform | |
2383 // to obtain a bounding box in the parent's coordinate space that encloses us. | |
2384 if (hasLayer() && layer()->transform()) { | |
2385 // Use enclosingIntRect because we cannot properly compute pixel snapping | |
2386 // for painted elements within the transform since we don't know the desired | |
2387 // subpixel accumulation at this point, and the transform may include a | |
2388 // scale. | |
2389 rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect))); | |
2390 } | |
2391 LayoutPoint topLeft = rect.location(); | |
2392 if (container->isBox()) { | |
2393 topLeft.moveBy(physicalLocation(toLayoutBox(container))); | |
2394 // If the row is the ancestor, however, add its offset back in. In effect, | 2388 // If the row is the ancestor, however, add its offset back in. In effect, |
2395 // this passes from the joint <td> / <tr> coordinate space to the parent | 2389 // this passes from the joint <td> / <tr> coordinate space to the parent |
2396 // space, then back to <tr> / <td>. | 2390 // space, then back to <tr> / <td>. |
2397 if (tableRowContainer) { | 2391 if (tableRowContainer) { |
2398 topLeft.moveBy( | 2392 containerOffset.moveBy( |
2399 -tableRowContainer->physicalLocation(toLayoutBox(container))); | 2393 -tableRowContainer->physicalLocation(toLayoutBox(container))); |
2400 } | 2394 } |
2401 } else if (container->isRuby()) { | 2395 } else if (container->isRuby()) { |
2402 // TODO(wkorman): Generalize Ruby specialization and/or document more | 2396 // TODO(wkorman): Generalize Ruby specialization and/or document more |
2403 // clearly. See the accompanying specialization in | 2397 // clearly. See the accompanying specialization in |
2404 // LayoutInline::mapToVisualRectInAncestorSpace. | 2398 // LayoutInline::mapToVisualRectInAncestorSpaceInternal. |
2405 topLeft.moveBy(physicalLocation()); | 2399 containerOffset.moveBy(physicalLocation()); |
2406 } else { | 2400 } else { |
2407 topLeft.moveBy(location()); | 2401 containerOffset.moveBy(location()); |
2408 } | 2402 } |
2409 | 2403 |
2410 const ComputedStyle& styleToUse = styleRef(); | 2404 const ComputedStyle& styleToUse = styleRef(); |
2411 EPosition position = styleToUse.position(); | 2405 EPosition position = styleToUse.position(); |
2412 if (position == EPosition::kAbsolute && container->isInFlowPositioned() && | 2406 if (position == EPosition::kAbsolute && container->isInFlowPositioned() && |
2413 container->isLayoutInline()) { | 2407 container->isLayoutInline()) { |
2414 topLeft += | 2408 containerOffset.move( |
2415 toLayoutInline(container)->offsetForInFlowPositionedInline(*this); | 2409 toLayoutInline(container)->offsetForInFlowPositionedInline(*this)); |
2416 } else if (styleToUse.hasInFlowPosition() && layer()) { | 2410 } else if (styleToUse.hasInFlowPosition() && layer()) { |
2417 // Apply the relative position offset when invalidating a rectangle. The | 2411 // Apply the relative position offset when invalidating a rectangle. The |
2418 // layer is translated, but the layout box isn't, so we need to do this to | 2412 // layer is translated, but the layout box isn't, so we need to do this to |
2419 // get the right dirty rect. Since this is called from | 2413 // get the right dirty rect. Since this is called from |
2420 // LayoutObject::setStyle, the relative position flag on the LayoutObject | 2414 // LayoutObject::setStyle, the relative position flag on the LayoutObject |
2421 // has been cleared, so use the one on the style(). | 2415 // has been cleared, so use the one on the style(). |
2422 topLeft += layer()->offsetForInFlowPosition(); | 2416 containerOffset.move(layer()->offsetForInFlowPosition()); |
2417 } | |
2418 | |
2419 bool preserve3D = | |
2420 ((container->style()->preserves3D() && !container->isText()) || | |
2421 (style()->preserves3D() && !isText())); | |
Xianzhu
2017/03/03 01:24:42
I think !container->isText() and !isText() are bot
chrishtr
2017/03/03 02:45:11
Done.
| |
2422 | |
2423 TransformState::TransformAccumulation accumulation = | |
2424 preserve3D ? TransformState::AccumulateTransform | |
2425 : TransformState::FlattenTransform; | |
2426 | |
2427 if (skipInfo.filterSkipped()) { | |
2428 inflateVisualRectForFilterUnderContainer(transformState, *container, | |
2429 ancestor); | |
2430 } | |
2431 | |
2432 // We are now in our parent container's coordinate space. Apply our transform | |
2433 // to obtain a bounding box in the parent's coordinate space that encloses us. | |
2434 if (shouldUseTransformFromContainer(container)) { | |
2435 TransformationMatrix t; | |
2436 getTransformFromContainer(container, toLayoutSize(containerOffset), t); | |
2437 transformState.applyTransform(t, accumulation); | |
2438 | |
2439 // Use enclosingIntRect because we cannot properly compute pixel snapping | |
Xianzhu
2017/03/03 01:24:42
enclosingIntRect -> enclosingBoundingBox().
Not a
chrishtr
2017/03/03 02:45:11
Will fix in a followup. Changed comment.
| |
2440 // for painted elements within the transform since we don't know the desired | |
2441 // subpixel accumulation at this point, and the transform may include a | |
2442 // scale. | |
2443 if (!preserve3D) { | |
2444 transformState.flatten(); | |
2445 transformState.setQuad( | |
2446 FloatQuad(transformState.lastPlanarQuad().enclosingBoundingBox())); | |
2447 } | |
2448 } else { | |
2449 transformState.move(toLayoutSize(containerOffset), accumulation); | |
2423 } | 2450 } |
2424 | 2451 |
2425 // FIXME: We ignore the lightweight clipping rect that controls use, since if | 2452 // FIXME: We ignore the lightweight clipping rect that controls use, since if |
2426 // |o| is in mid-layout, its controlClipRect will be wrong. For overflow clip | 2453 // |o| is in mid-layout, its controlClipRect will be wrong. For overflow clip |
2427 // we use the values cached by the layer. | 2454 // we use the values cached by the layer. |
2428 rect.setLocation(topLeft); | |
2429 | |
2430 if (container->isBox() && container != ancestor && | 2455 if (container->isBox() && container != ancestor && |
2431 !toLayoutBox(container)->mapScrollingContentsRectToBoxSpace( | 2456 !toLayoutBox(container)->mapScrollingContentsRectToBoxSpace( |
2432 rect, visualRectFlags)) | 2457 transformState, accumulation, visualRectFlags)) |
2433 return false; | 2458 return false; |
2434 | 2459 |
2435 if (skipInfo.ancestorSkipped()) { | 2460 if (skipInfo.ancestorSkipped()) { |
2436 // If the ancestor is below the container, then we need to map the rect into | 2461 // If the ancestor is below the container, then we need to map the rect into |
2437 // ancestor's coordinates. | 2462 // ancestor's coordinates. |
2438 LayoutSize containerOffset = | 2463 LayoutSize containerOffset = |
2439 ancestor->offsetFromAncestorContainer(container); | 2464 ancestor->offsetFromAncestorContainer(container); |
2440 rect.move(-containerOffset); | 2465 transformState.move(-containerOffset, accumulation); |
2441 // If the ancestor is fixed, then the rect is already in its coordinates so | 2466 // If the ancestor is fixed, then the rect is already in its coordinates so |
2442 // doesn't need viewport-adjusting. | 2467 // doesn't need viewport-adjusting. |
2443 if (ancestor->style()->position() != EPosition::kFixed && | 2468 if (ancestor->style()->position() != EPosition::kFixed && |
2444 container->isLayoutView() && position == EPosition::kFixed) | 2469 container->isLayoutView() && position == EPosition::kFixed) { |
2445 rect.move(toLayoutView(container)->offsetForFixedPosition(true)); | 2470 transformState.move(toLayoutView(container)->offsetForFixedPosition(true), |
2471 accumulation); | |
2472 } | |
2446 return true; | 2473 return true; |
2447 } | 2474 } |
2448 | 2475 |
2449 if (container->isLayoutView()) | 2476 if (container->isLayoutView()) |
2450 return toLayoutView(container)->mapToVisualRectInAncestorSpace( | 2477 return toLayoutView(container)->mapToVisualRectInAncestorSpaceInternal( |
2451 ancestor, rect, position == EPosition::kFixed ? IsFixed : 0, | 2478 ancestor, transformState, position == EPosition::kFixed ? IsFixed : 0, |
2452 visualRectFlags); | 2479 visualRectFlags); |
2453 else | 2480 else |
2454 return container->mapToVisualRectInAncestorSpace(ancestor, rect, | 2481 return container->mapToVisualRectInAncestorSpaceInternal( |
2455 visualRectFlags); | 2482 ancestor, transformState, visualRectFlags); |
2456 } | 2483 } |
2457 | 2484 |
2458 void LayoutBox::inflateVisualRectForFilter(LayoutRect& visualRect) const { | 2485 void LayoutBox::inflateVisualRectForFilter( |
2459 if (layer() && layer()->hasFilterInducingProperty()) | 2486 TransformState& transformState) const { |
2460 visualRect = layer()->mapLayoutRectForFilter(visualRect); | 2487 if (!layer() || !layer()->hasFilterInducingProperty()) |
2488 return; | |
2489 | |
2490 transformState.flatten(); | |
2491 LayoutRect rect(transformState.lastPlanarQuad().boundingBox()); | |
2492 transformState.setQuad( | |
2493 FloatQuad(FloatRect(layer()->mapLayoutRectForFilter(rect)))); | |
2461 } | 2494 } |
2462 | 2495 |
2463 void LayoutBox::updateLogicalWidth() { | 2496 void LayoutBox::updateLogicalWidth() { |
2464 LogicalExtentComputedValues computedValues; | 2497 LogicalExtentComputedValues computedValues; |
2465 computeLogicalWidth(computedValues); | 2498 computeLogicalWidth(computedValues); |
2466 | 2499 |
2467 setLogicalWidth(computedValues.m_extent); | 2500 setLogicalWidth(computedValues.m_extent); |
2468 setLogicalLeft(computedValues.m_position); | 2501 setLogicalLeft(computedValues.m_position); |
2469 setMarginStart(computedValues.m_margins.m_start); | 2502 setMarginStart(computedValues.m_margins.m_start); |
2470 setMarginEnd(computedValues.m_margins.m_end); | 2503 setMarginEnd(computedValues.m_margins.m_end); |
(...skipping 3263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5734 | 5767 |
5735 void LayoutBox::MutableForPainting:: | 5768 void LayoutBox::MutableForPainting:: |
5736 savePreviousContentBoxSizeAndLayoutOverflowRect() { | 5769 savePreviousContentBoxSizeAndLayoutOverflowRect() { |
5737 auto& rareData = layoutBox().ensureRareData(); | 5770 auto& rareData = layoutBox().ensureRareData(); |
5738 rareData.m_hasPreviousContentBoxSizeAndLayoutOverflowRect = true; | 5771 rareData.m_hasPreviousContentBoxSizeAndLayoutOverflowRect = true; |
5739 rareData.m_previousContentBoxSize = layoutBox().contentBoxRect().size(); | 5772 rareData.m_previousContentBoxSize = layoutBox().contentBoxRect().size(); |
5740 rareData.m_previousLayoutOverflowRect = layoutBox().layoutOverflowRect(); | 5773 rareData.m_previousLayoutOverflowRect = layoutBox().layoutOverflowRect(); |
5741 } | 5774 } |
5742 | 5775 |
5743 } // namespace blink | 5776 } // namespace blink |
OLD | NEW |