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

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

Issue 2634493007: Introduce LayoutObject::AncestorSkipInfo. (Closed)
Patch Set: Created 3 years, 11 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) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) 5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc.
7 * All rights reserved. 7 * All rights reserved.
8 * Copyright (C) 2009 Google Inc. All rights reserved. 8 * Copyright (C) 2009 Google Inc. All rights reserved.
9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
10 * (http://www.torchmobile.com/) 10 * (http://www.torchmobile.com/)
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 o->m_bitfields.setPreferredLogicalWidthsDirty(true); 852 o->m_bitfields.setPreferredLogicalWidthsDirty(true);
853 // A positioned object has no effect on the min/max width of its containing 853 // A positioned object has no effect on the min/max width of its containing
854 // block ever. We can optimize this case and not go up any further. 854 // block ever. We can optimize this case and not go up any further.
855 if (o->style()->hasOutOfFlowPosition()) 855 if (o->style()->hasOutOfFlowPosition())
856 break; 856 break;
857 o = container; 857 o = container;
858 } 858 }
859 } 859 }
860 860
861 LayoutObject* LayoutObject::containerForAbsolutePosition( 861 LayoutObject* LayoutObject::containerForAbsolutePosition(
862 const LayoutBoxModelObject* ancestor, 862 AncestorSkipInfo* skipInfo) const {
863 bool* ancestorSkipped, 863 DCHECK(!skipInfo || !skipInfo->ancestorSkipped);
864 bool* filterSkipped) const { 864 DCHECK(!skipInfo || !skipInfo->filterSkipped);
Xianzhu 2017/01/15 19:41:13 What do you think about removing these DCHECKs? I
mstensho (USE GERRIT) 2017/01/15 21:09:25 Sounds good to me. I also prefer doing nothing.
mstensho (USE GERRIT) 2017/01/16 09:34:04 Actually, I prefer to postpone this and do it as p
mstensho (USE GERRIT) 2017/01/16 14:39:02 Had to remove these now, since it's now forbidden
865 DCHECK(!ancestorSkipped || !*ancestorSkipped);
866 DCHECK(!filterSkipped || !*filterSkipped);
867 865
868 // We technically just want our containing block, but we may not have one if 866 // We technically just want our containing block, but we may not have one if
869 // we're part of an uninstalled subtree. We'll climb as high as we can though. 867 // we're part of an uninstalled subtree. We'll climb as high as we can though.
870 for (LayoutObject* object = parent(); object; object = object->parent()) { 868 for (LayoutObject* object = parent(); object; object = object->parent()) {
871 if (object->canContainAbsolutePositionObjects()) 869 if (object->canContainAbsolutePositionObjects())
872 return object; 870 return object;
873 871 if (skipInfo)
874 if (ancestorSkipped && object == ancestor) 872 skipInfo->update(*object);
875 *ancestorSkipped = true;
876
877 if (filterSkipped && object->hasFilterInducingProperty())
878 *filterSkipped = true;
879 } 873 }
880 return nullptr; 874 return nullptr;
881 } 875 }
882 876
883 LayoutBlock* LayoutObject::containerForFixedPosition( 877 LayoutBlock* LayoutObject::containerForFixedPosition(
884 const LayoutBoxModelObject* ancestor, 878 AncestorSkipInfo* skipInfo) const {
885 bool* ancestorSkipped, 879 DCHECK(!skipInfo || !skipInfo->ancestorSkipped);
886 bool* filterSkipped) const { 880 DCHECK(!skipInfo || !skipInfo->filterSkipped);
887 DCHECK(!ancestorSkipped || !*ancestorSkipped);
888 DCHECK(!filterSkipped || !*filterSkipped);
889 DCHECK(!isText()); 881 DCHECK(!isText());
890 882
891 LayoutObject* object = parent(); 883 LayoutObject* object = parent();
892 for (; object && !object->canContainFixedPositionObjects(); 884 for (; object && !object->canContainFixedPositionObjects();
893 object = object->parent()) { 885 object = object->parent()) {
894 if (ancestorSkipped && object == ancestor) 886 if (skipInfo)
895 *ancestorSkipped = true; 887 skipInfo->update(*object);
896
897 if (filterSkipped && object->hasFilterInducingProperty())
898 *filterSkipped = true;
899 } 888 }
900 889
901 ASSERT(!object || !object->isAnonymousBlock()); 890 ASSERT(!object || !object->isAnonymousBlock());
902 return toLayoutBlock(object); 891 return toLayoutBlock(object);
903 } 892 }
904 893
905 LayoutBlock* LayoutObject::containingBlockForAbsolutePosition( 894 LayoutBlock* LayoutObject::containingBlockForAbsolutePosition(
906 const LayoutBoxModelObject* ancestor, 895 AncestorSkipInfo* skipInfo) const {
907 bool* ancestorSkipped, 896 LayoutObject* object = containerForAbsolutePosition(skipInfo);
908 bool* filterSkipped) const {
909 LayoutObject* object =
910 containerForAbsolutePosition(ancestor, ancestorSkipped, filterSkipped);
911 897
912 // For relpositioned inlines, we return the nearest non-anonymous enclosing 898 // For relpositioned inlines, we return the nearest non-anonymous enclosing
913 // block. We don't try to return the inline itself. This allows us to avoid 899 // block. We don't try to return the inline itself. This allows us to avoid
914 // having a positioned objects list in all LayoutInlines and lets us return a 900 // having a positioned objects list in all LayoutInlines and lets us return a
915 // strongly-typed LayoutBlock* result from this method. The container() method 901 // strongly-typed LayoutBlock* result from this method. The container() method
916 // can actually be used to obtain the inline directly. 902 // can actually be used to obtain the inline directly.
917 if (object && object->isInline() && !object->isAtomicInlineLevel()) { 903 if (object && object->isInline() && !object->isAtomicInlineLevel()) {
918 DCHECK(object->style()->hasInFlowPosition()); 904 DCHECK(object->style()->hasInFlowPosition());
919 object = object->containingBlock(ancestor, ancestorSkipped, filterSkipped); 905 object = object->containingBlock(skipInfo);
920 } 906 }
921 907
922 if (object && !object->isLayoutBlock()) 908 if (object && !object->isLayoutBlock())
923 object = object->containingBlock(ancestor, ancestorSkipped, filterSkipped); 909 object = object->containingBlock(skipInfo);
924 910
925 while (object && object->isAnonymousBlock()) 911 while (object && object->isAnonymousBlock())
926 object = object->containingBlock(ancestor, ancestorSkipped, filterSkipped); 912 object = object->containingBlock(skipInfo);
927 913
928 if (!object || !object->isLayoutBlock()) 914 if (!object || !object->isLayoutBlock())
929 return nullptr; // This can still happen in case of an orphaned tree 915 return nullptr; // This can still happen in case of an orphaned tree
930 916
931 return toLayoutBlock(object); 917 return toLayoutBlock(object);
932 } 918 }
933 919
934 LayoutBlock* LayoutObject::containingBlock(const LayoutBoxModelObject* ancestor, 920 LayoutBlock* LayoutObject::containingBlock(AncestorSkipInfo* skipInfo) const {
935 bool* ancestorSkipped,
936 bool* filterSkipped) const {
937 LayoutObject* object = parent(); 921 LayoutObject* object = parent();
938 if (!object && isLayoutScrollbarPart()) 922 if (!object && isLayoutScrollbarPart())
939 object = toLayoutScrollbarPart(this)->layoutObjectOwningScrollbar(); 923 object = toLayoutScrollbarPart(this)->layoutObjectOwningScrollbar();
940 if (!isTextOrSVGChild()) { 924 if (!isTextOrSVGChild()) {
941 if (m_style->position() == FixedPosition) { 925 if (m_style->position() == FixedPosition)
942 return containerForFixedPosition(ancestor, ancestorSkipped, 926 return containerForFixedPosition(skipInfo);
943 filterSkipped); 927 if (m_style->position() == AbsolutePosition)
944 } 928 return containingBlockForAbsolutePosition(skipInfo);
945 if (m_style->position() == AbsolutePosition) {
946 return containingBlockForAbsolutePosition(ancestor, ancestorSkipped,
947 filterSkipped);
948 }
949 } 929 }
950 if (isColumnSpanAll()) { 930 if (isColumnSpanAll()) {
951 object = spannerPlaceholder()->containingBlock(); 931 object = spannerPlaceholder()->containingBlock();
952 } else { 932 } else {
953 while (object && ((object->isInline() && !object->isAtomicInlineLevel()) || 933 while (object && ((object->isInline() && !object->isAtomicInlineLevel()) ||
954 !object->isLayoutBlock())) { 934 !object->isLayoutBlock())) {
955 if (ancestorSkipped && object == ancestor) 935 if (skipInfo)
956 *ancestorSkipped = true; 936 skipInfo->update(*object);
957
958 if (filterSkipped && object->hasFilterInducingProperty())
959 *filterSkipped = true;
960 object = object->parent(); 937 object = object->parent();
961 } 938 }
962 } 939 }
963 940
964 if (!object || !object->isLayoutBlock()) 941 if (!object || !object->isLayoutBlock())
965 return nullptr; // This can still happen in case of an orphaned tree 942 return nullptr; // This can still happen in case of an orphaned tree
966 943
967 return toLayoutBlock(object); 944 return toLayoutBlock(object);
968 } 945 }
969 946
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after
2069 transformState.flatten(); 2046 transformState.flatten();
2070 return transformState.lastPlanarQuad(); 2047 return transformState.lastPlanarQuad();
2071 } 2048 }
2072 2049
2073 void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, 2050 void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor,
2074 TransformState& transformState, 2051 TransformState& transformState,
2075 MapCoordinatesFlags mode) const { 2052 MapCoordinatesFlags mode) const {
2076 if (ancestor == this) 2053 if (ancestor == this)
2077 return; 2054 return;
2078 2055
2079 bool ancestorSkipped; 2056 AncestorSkipInfo skipInfo(ancestor);
2080 const LayoutObject* container = this->container(ancestor, &ancestorSkipped); 2057 const LayoutObject* container = this->container(&skipInfo);
2081 if (!container) 2058 if (!container)
2082 return; 2059 return;
2083 2060
2084 if (mode & ApplyContainerFlip) { 2061 if (mode & ApplyContainerFlip) {
2085 if (isBox()) { 2062 if (isBox()) {
2086 mode &= ~ApplyContainerFlip; 2063 mode &= ~ApplyContainerFlip;
2087 } else if (container->isBox()) { 2064 } else if (container->isBox()) {
2088 if (container->style()->isFlippedBlocksWritingMode()) { 2065 if (container->style()->isFlippedBlocksWritingMode()) {
2089 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint()); 2066 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
2090 transformState.move(toLayoutBox(container)->flipForWritingMode( 2067 transformState.move(toLayoutBox(container)->flipForWritingMode(
(...skipping 24 matching lines...) Expand all
2115 getTransformFromContainer(container, containerOffset, t); 2092 getTransformFromContainer(container, containerOffset, t);
2116 transformState.applyTransform(t, preserve3D 2093 transformState.applyTransform(t, preserve3D
2117 ? TransformState::AccumulateTransform 2094 ? TransformState::AccumulateTransform
2118 : TransformState::FlattenTransform); 2095 : TransformState::FlattenTransform);
2119 } else { 2096 } else {
2120 transformState.move(containerOffset.width(), containerOffset.height(), 2097 transformState.move(containerOffset.width(), containerOffset.height(),
2121 preserve3D ? TransformState::AccumulateTransform 2098 preserve3D ? TransformState::AccumulateTransform
2122 : TransformState::FlattenTransform); 2099 : TransformState::FlattenTransform);
2123 } 2100 }
2124 2101
2125 if (ancestorSkipped) { 2102 if (skipInfo.ancestorSkipped) {
2126 // There can't be a transform between |ancestor| and |o|, because transforms 2103 // There can't be a transform between |ancestor| and |o|, because transforms
2127 // create containers, so it should be safe to just subtract the delta 2104 // create containers, so it should be safe to just subtract the delta
2128 // between the ancestor and |o|. 2105 // between the ancestor and |o|.
2129 LayoutSize containerOffset = 2106 LayoutSize containerOffset =
2130 ancestor->offsetFromAncestorContainer(container); 2107 ancestor->offsetFromAncestorContainer(container);
2131 transformState.move(-containerOffset.width(), -containerOffset.height(), 2108 transformState.move(-containerOffset.width(), -containerOffset.height(),
2132 preserve3D ? TransformState::AccumulateTransform 2109 preserve3D ? TransformState::AccumulateTransform
2133 : TransformState::FlattenTransform); 2110 : TransformState::FlattenTransform);
2134 // If the ancestor is fixed, then the rect is already in its coordinates so 2111 // If the ancestor is fixed, then the rect is already in its coordinates so
2135 // doesn't need viewport-adjusting. 2112 // doesn't need viewport-adjusting.
(...skipping 14 matching lines...) Expand all
2150 ASSERT_NOT_REACHED(); 2127 ASSERT_NOT_REACHED();
2151 return nullptr; 2128 return nullptr;
2152 } 2129 }
2153 2130
2154 void LayoutObject::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, 2131 void LayoutObject::mapAncestorToLocal(const LayoutBoxModelObject* ancestor,
2155 TransformState& transformState, 2132 TransformState& transformState,
2156 MapCoordinatesFlags mode) const { 2133 MapCoordinatesFlags mode) const {
2157 if (this == ancestor) 2134 if (this == ancestor)
2158 return; 2135 return;
2159 2136
2160 bool ancestorSkipped; 2137 AncestorSkipInfo skipInfo(ancestor);
2161 LayoutObject* container = this->container(ancestor, &ancestorSkipped); 2138 LayoutObject* container = this->container(&skipInfo);
2162 if (!container) 2139 if (!container)
2163 return; 2140 return;
2164 2141
2165 bool applyContainerFlip = false; 2142 bool applyContainerFlip = false;
2166 if (mode & ApplyContainerFlip) { 2143 if (mode & ApplyContainerFlip) {
2167 if (isBox()) { 2144 if (isBox()) {
2168 mode &= ~ApplyContainerFlip; 2145 mode &= ~ApplyContainerFlip;
2169 } else if (container->isBox()) { 2146 } else if (container->isBox()) {
2170 applyContainerFlip = container->style()->isFlippedBlocksWritingMode(); 2147 applyContainerFlip = container->style()->isFlippedBlocksWritingMode();
2171 mode &= ~ApplyContainerFlip; 2148 mode &= ~ApplyContainerFlip;
2172 } 2149 }
2173 } 2150 }
2174 2151
2175 if (!ancestorSkipped) 2152 if (!skipInfo.ancestorSkipped)
2176 container->mapAncestorToLocal(ancestor, transformState, mode); 2153 container->mapAncestorToLocal(ancestor, transformState, mode);
2177 2154
2178 LayoutSize containerOffset = offsetFromContainer(container); 2155 LayoutSize containerOffset = offsetFromContainer(container);
2179 bool preserve3D = 2156 bool preserve3D =
2180 mode & UseTransforms && 2157 mode & UseTransforms &&
2181 (container->style()->preserves3D() || style()->preserves3D()); 2158 (container->style()->preserves3D() || style()->preserves3D());
2182 if (mode & UseTransforms && shouldUseTransformFromContainer(container)) { 2159 if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
2183 TransformationMatrix t; 2160 TransformationMatrix t;
2184 getTransformFromContainer(container, containerOffset, t); 2161 getTransformFromContainer(container, containerOffset, t);
2185 transformState.applyTransform(t, preserve3D 2162 transformState.applyTransform(t, preserve3D
(...skipping 14 matching lines...) Expand all
2200 toLayoutFlowThread(this)->visualPointToFlowThreadPoint(visualPoint)); 2177 toLayoutFlowThread(this)->visualPointToFlowThreadPoint(visualPoint));
2201 } 2178 }
2202 2179
2203 if (applyContainerFlip) { 2180 if (applyContainerFlip) {
2204 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint()); 2181 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
2205 transformState.move( 2182 transformState.move(
2206 centerPoint - 2183 centerPoint -
2207 toLayoutBox(container)->flipForWritingMode(LayoutPoint(centerPoint))); 2184 toLayoutBox(container)->flipForWritingMode(LayoutPoint(centerPoint)));
2208 } 2185 }
2209 2186
2210 if (ancestorSkipped) { 2187 if (skipInfo.ancestorSkipped) {
2211 containerOffset = ancestor->offsetFromAncestorContainer(container); 2188 containerOffset = ancestor->offsetFromAncestorContainer(container);
2212 transformState.move(-containerOffset.width(), -containerOffset.height()); 2189 transformState.move(-containerOffset.width(), -containerOffset.height());
2213 // If the ancestor is fixed, then the rect is already in its coordinates so 2190 // If the ancestor is fixed, then the rect is already in its coordinates so
2214 // doesn't need viewport-adjusting. 2191 // doesn't need viewport-adjusting.
2215 if (ancestor->style()->position() != FixedPosition && 2192 if (ancestor->style()->position() != FixedPosition &&
2216 container->isLayoutView() && styleRef().position() == FixedPosition) { 2193 container->isLayoutView() && styleRef().position() == FixedPosition) {
2217 LayoutSize adjustment = toLayoutView(container)->offsetForFixedPosition(); 2194 LayoutSize adjustment = toLayoutView(container)->offsetForFixedPosition();
2218 transformState.move(adjustment.width(), adjustment.height()); 2195 transformState.move(adjustment.width(), adjustment.height());
2219 } 2196 }
2220 } 2197 }
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 return RespectImageOrientation; 2449 return RespectImageOrientation;
2473 2450
2474 if (layoutObject->style() && 2451 if (layoutObject->style() &&
2475 layoutObject->style()->respectImageOrientation() == 2452 layoutObject->style()->respectImageOrientation() ==
2476 RespectImageOrientation) 2453 RespectImageOrientation)
2477 return RespectImageOrientation; 2454 return RespectImageOrientation;
2478 2455
2479 return DoNotRespectImageOrientation; 2456 return DoNotRespectImageOrientation;
2480 } 2457 }
2481 2458
2482 LayoutObject* LayoutObject::container(const LayoutBoxModelObject* ancestor, 2459 void LayoutObject::AncestorSkipInfo::update(const LayoutObject& object) {
2483 bool* ancestorSkipped, 2460 if (&object == ancestor)
2484 bool* filterSkipped) const { 2461 ancestorSkipped = true;
2485 if (ancestorSkipped) 2462 if (object.hasFilterInducingProperty())
2486 *ancestorSkipped = false; 2463 filterSkipped = true;
2487 if (filterSkipped) 2464 }
2488 *filterSkipped = false; 2465
2466 LayoutObject* LayoutObject::container(AncestorSkipInfo* skipInfo) const {
2467 if (skipInfo)
2468 skipInfo->resetOutput();
mstensho (USE GERRIT) 2017/01/15 21:09:25 What about this, then? Why reset here, but nowhere
Xianzhu 2017/01/15 23:05:05 I would like to also remove this. Either in this C
mstensho (USE GERRIT) 2017/01/16 09:34:04 OK, I'll do it in a follow-up.
2489 2469
2490 if (isTextOrSVGChild()) 2470 if (isTextOrSVGChild())
2491 return parent(); 2471 return parent();
2492 2472
2493 EPosition pos = m_style->position(); 2473 EPosition pos = m_style->position();
2494 if (pos == FixedPosition) 2474 if (pos == FixedPosition)
2495 return containerForFixedPosition(ancestor, ancestorSkipped, filterSkipped); 2475 return containerForFixedPosition(skipInfo);
2496 2476
2497 if (pos == AbsolutePosition) { 2477 if (pos == AbsolutePosition) {
2498 return containerForAbsolutePosition(ancestor, ancestorSkipped, 2478 return containerForAbsolutePosition(skipInfo);
2499 filterSkipped);
2500 } 2479 }
2501 2480
2502 if (isColumnSpanAll()) { 2481 if (isColumnSpanAll()) {
2503 LayoutObject* multicolContainer = spannerPlaceholder()->container(); 2482 LayoutObject* multicolContainer = spannerPlaceholder()->container();
2504 if ((ancestorSkipped && ancestor) || filterSkipped) { 2483 if (skipInfo) {
2505 // We jumped directly from the spanner to the multicol container. Need to 2484 // We jumped directly from the spanner to the multicol container. Need to
2506 // check if we skipped |ancestor| or filter/reflection on the way. 2485 // check if we skipped |ancestor| or filter/reflection on the way.
2507 for (LayoutObject* walker = parent(); 2486 for (LayoutObject* walker = parent();
2508 walker && walker != multicolContainer; walker = walker->parent()) { 2487 walker && walker != multicolContainer; walker = walker->parent())
2509 if (ancestorSkipped && walker == ancestor) 2488 skipInfo->update(*walker);
2510 *ancestorSkipped = true;
2511 if (filterSkipped && walker->hasFilterInducingProperty())
2512 *filterSkipped = true;
2513 }
2514 } 2489 }
2515 return multicolContainer; 2490 return multicolContainer;
2516 } 2491 }
2517 2492
2518 if (isFloating()) 2493 if (isFloating())
2519 return containingBlock(ancestor, ancestorSkipped, filterSkipped); 2494 return containingBlock(skipInfo);
2520 2495
2521 return parent(); 2496 return parent();
2522 } 2497 }
2523 2498
2524 inline LayoutObject* LayoutObject::paintInvalidationParent() const { 2499 inline LayoutObject* LayoutObject::paintInvalidationParent() const {
2525 if (isLayoutView()) 2500 if (isLayoutView())
2526 return LayoutAPIShim::layoutObjectFrom(frame()->ownerLayoutItem()); 2501 return LayoutAPIShim::layoutObjectFrom(frame()->ownerLayoutItem());
2527 return parent(); 2502 return parent();
2528 } 2503 }
2529 2504
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
3508 const blink::LayoutObject* root = object1; 3483 const blink::LayoutObject* root = object1;
3509 while (root->parent()) 3484 while (root->parent())
3510 root = root->parent(); 3485 root = root->parent();
3511 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0); 3486 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0);
3512 } else { 3487 } else {
3513 WTFLogAlways("%s", "Cannot showLayoutTree. Root is (nil)"); 3488 WTFLogAlways("%s", "Cannot showLayoutTree. Root is (nil)");
3514 } 3489 }
3515 } 3490 }
3516 3491
3517 #endif 3492 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698