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

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

Issue 2634493007: Introduce LayoutObject::AncestorSkipInfo. (Closed)
Patch Set: Turn AncestorSkipInfo into a proper class with private data members. Only look for filters when tol… 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,
864 bool* filterSkipped) const {
865 DCHECK(!ancestorSkipped || !*ancestorSkipped);
866 DCHECK(!filterSkipped || !*filterSkipped);
867
868 // We technically just want our containing block, but we may not have one if 863 // 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. 864 // 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()) { 865 for (LayoutObject* object = parent(); object; object = object->parent()) {
871 if (object->canContainAbsolutePositionObjects()) 866 if (object->canContainAbsolutePositionObjects())
872 return object; 867 return object;
873 868 if (skipInfo)
874 if (ancestorSkipped && object == ancestor) 869 skipInfo->update(*object);
875 *ancestorSkipped = true;
876
877 if (filterSkipped && object->hasFilterInducingProperty())
878 *filterSkipped = true;
879 } 870 }
880 return nullptr; 871 return nullptr;
881 } 872 }
882 873
883 LayoutBlock* LayoutObject::containerForFixedPosition( 874 LayoutBlock* LayoutObject::containerForFixedPosition(
884 const LayoutBoxModelObject* ancestor, 875 AncestorSkipInfo* skipInfo) const {
885 bool* ancestorSkipped,
886 bool* filterSkipped) const {
887 DCHECK(!ancestorSkipped || !*ancestorSkipped);
888 DCHECK(!filterSkipped || !*filterSkipped);
889 DCHECK(!isText()); 876 DCHECK(!isText());
890 877
891 LayoutObject* object = parent(); 878 LayoutObject* object = parent();
892 for (; object && !object->canContainFixedPositionObjects(); 879 for (; object && !object->canContainFixedPositionObjects();
893 object = object->parent()) { 880 object = object->parent()) {
894 if (ancestorSkipped && object == ancestor) 881 if (skipInfo)
895 *ancestorSkipped = true; 882 skipInfo->update(*object);
896
897 if (filterSkipped && object->hasFilterInducingProperty())
898 *filterSkipped = true;
899 } 883 }
900 884
901 ASSERT(!object || !object->isAnonymousBlock()); 885 ASSERT(!object || !object->isAnonymousBlock());
902 return toLayoutBlock(object); 886 return toLayoutBlock(object);
903 } 887 }
904 888
905 LayoutBlock* LayoutObject::containingBlockForAbsolutePosition( 889 LayoutBlock* LayoutObject::containingBlockForAbsolutePosition(
906 const LayoutBoxModelObject* ancestor, 890 AncestorSkipInfo* skipInfo) const {
907 bool* ancestorSkipped, 891 LayoutObject* object = containerForAbsolutePosition(skipInfo);
908 bool* filterSkipped) const {
909 LayoutObject* object =
910 containerForAbsolutePosition(ancestor, ancestorSkipped, filterSkipped);
911 892
912 // For relpositioned inlines, we return the nearest non-anonymous enclosing 893 // 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 894 // 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 895 // having a positioned objects list in all LayoutInlines and lets us return a
915 // strongly-typed LayoutBlock* result from this method. The container() method 896 // strongly-typed LayoutBlock* result from this method. The container() method
916 // can actually be used to obtain the inline directly. 897 // can actually be used to obtain the inline directly.
917 if (object && object->isInline() && !object->isAtomicInlineLevel()) { 898 if (object && object->isInline() && !object->isAtomicInlineLevel()) {
918 DCHECK(object->style()->hasInFlowPosition()); 899 DCHECK(object->style()->hasInFlowPosition());
919 object = object->containingBlock(ancestor, ancestorSkipped, filterSkipped); 900 object = object->containingBlock(skipInfo);
920 } 901 }
921 902
922 if (object && !object->isLayoutBlock()) 903 if (object && !object->isLayoutBlock())
923 object = object->containingBlock(ancestor, ancestorSkipped, filterSkipped); 904 object = object->containingBlock(skipInfo);
924 905
925 while (object && object->isAnonymousBlock()) 906 while (object && object->isAnonymousBlock())
926 object = object->containingBlock(ancestor, ancestorSkipped, filterSkipped); 907 object = object->containingBlock(skipInfo);
927 908
928 if (!object || !object->isLayoutBlock()) 909 if (!object || !object->isLayoutBlock())
929 return nullptr; // This can still happen in case of an orphaned tree 910 return nullptr; // This can still happen in case of an orphaned tree
930 911
931 return toLayoutBlock(object); 912 return toLayoutBlock(object);
932 } 913 }
933 914
934 LayoutBlock* LayoutObject::containingBlock(const LayoutBoxModelObject* ancestor, 915 LayoutBlock* LayoutObject::containingBlock(AncestorSkipInfo* skipInfo) const {
935 bool* ancestorSkipped,
936 bool* filterSkipped) const {
937 LayoutObject* object = parent(); 916 LayoutObject* object = parent();
938 if (!object && isLayoutScrollbarPart()) 917 if (!object && isLayoutScrollbarPart())
939 object = toLayoutScrollbarPart(this)->layoutObjectOwningScrollbar(); 918 object = toLayoutScrollbarPart(this)->layoutObjectOwningScrollbar();
940 if (!isTextOrSVGChild()) { 919 if (!isTextOrSVGChild()) {
941 if (m_style->position() == FixedPosition) { 920 if (m_style->position() == FixedPosition)
942 return containerForFixedPosition(ancestor, ancestorSkipped, 921 return containerForFixedPosition(skipInfo);
943 filterSkipped); 922 if (m_style->position() == AbsolutePosition)
944 } 923 return containingBlockForAbsolutePosition(skipInfo);
945 if (m_style->position() == AbsolutePosition) {
946 return containingBlockForAbsolutePosition(ancestor, ancestorSkipped,
947 filterSkipped);
948 }
949 } 924 }
950 if (isColumnSpanAll()) { 925 if (isColumnSpanAll()) {
951 object = spannerPlaceholder()->containingBlock(); 926 object = spannerPlaceholder()->containingBlock();
952 } else { 927 } else {
953 while (object && ((object->isInline() && !object->isAtomicInlineLevel()) || 928 while (object && ((object->isInline() && !object->isAtomicInlineLevel()) ||
954 !object->isLayoutBlock())) { 929 !object->isLayoutBlock())) {
955 if (ancestorSkipped && object == ancestor) 930 if (skipInfo)
956 *ancestorSkipped = true; 931 skipInfo->update(*object);
957
958 if (filterSkipped && object->hasFilterInducingProperty())
959 *filterSkipped = true;
960 object = object->parent(); 932 object = object->parent();
961 } 933 }
962 } 934 }
963 935
964 if (!object || !object->isLayoutBlock()) 936 if (!object || !object->isLayoutBlock())
965 return nullptr; // This can still happen in case of an orphaned tree 937 return nullptr; // This can still happen in case of an orphaned tree
966 938
967 return toLayoutBlock(object); 939 return toLayoutBlock(object);
968 } 940 }
969 941
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after
2069 transformState.flatten(); 2041 transformState.flatten();
2070 return transformState.lastPlanarQuad(); 2042 return transformState.lastPlanarQuad();
2071 } 2043 }
2072 2044
2073 void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, 2045 void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor,
2074 TransformState& transformState, 2046 TransformState& transformState,
2075 MapCoordinatesFlags mode) const { 2047 MapCoordinatesFlags mode) const {
2076 if (ancestor == this) 2048 if (ancestor == this)
2077 return; 2049 return;
2078 2050
2079 bool ancestorSkipped; 2051 AncestorSkipInfo skipInfo(ancestor);
2080 const LayoutObject* container = this->container(ancestor, &ancestorSkipped); 2052 const LayoutObject* container = this->container(&skipInfo);
2081 if (!container) 2053 if (!container)
2082 return; 2054 return;
2083 2055
2084 if (mode & ApplyContainerFlip) { 2056 if (mode & ApplyContainerFlip) {
2085 if (isBox()) { 2057 if (isBox()) {
2086 mode &= ~ApplyContainerFlip; 2058 mode &= ~ApplyContainerFlip;
2087 } else if (container->isBox()) { 2059 } else if (container->isBox()) {
2088 if (container->style()->isFlippedBlocksWritingMode()) { 2060 if (container->style()->isFlippedBlocksWritingMode()) {
2089 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint()); 2061 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
2090 transformState.move(toLayoutBox(container)->flipForWritingMode( 2062 transformState.move(toLayoutBox(container)->flipForWritingMode(
(...skipping 24 matching lines...) Expand all
2115 getTransformFromContainer(container, containerOffset, t); 2087 getTransformFromContainer(container, containerOffset, t);
2116 transformState.applyTransform(t, preserve3D 2088 transformState.applyTransform(t, preserve3D
2117 ? TransformState::AccumulateTransform 2089 ? TransformState::AccumulateTransform
2118 : TransformState::FlattenTransform); 2090 : TransformState::FlattenTransform);
2119 } else { 2091 } else {
2120 transformState.move(containerOffset.width(), containerOffset.height(), 2092 transformState.move(containerOffset.width(), containerOffset.height(),
2121 preserve3D ? TransformState::AccumulateTransform 2093 preserve3D ? TransformState::AccumulateTransform
2122 : TransformState::FlattenTransform); 2094 : TransformState::FlattenTransform);
2123 } 2095 }
2124 2096
2125 if (ancestorSkipped) { 2097 if (skipInfo.ancestorSkipped()) {
2126 // There can't be a transform between |ancestor| and |o|, because transforms 2098 // 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 2099 // create containers, so it should be safe to just subtract the delta
2128 // between the ancestor and |o|. 2100 // between the ancestor and |o|.
2129 LayoutSize containerOffset = 2101 LayoutSize containerOffset =
2130 ancestor->offsetFromAncestorContainer(container); 2102 ancestor->offsetFromAncestorContainer(container);
2131 transformState.move(-containerOffset.width(), -containerOffset.height(), 2103 transformState.move(-containerOffset.width(), -containerOffset.height(),
2132 preserve3D ? TransformState::AccumulateTransform 2104 preserve3D ? TransformState::AccumulateTransform
2133 : TransformState::FlattenTransform); 2105 : TransformState::FlattenTransform);
2134 // If the ancestor is fixed, then the rect is already in its coordinates so 2106 // If the ancestor is fixed, then the rect is already in its coordinates so
2135 // doesn't need viewport-adjusting. 2107 // doesn't need viewport-adjusting.
(...skipping 14 matching lines...) Expand all
2150 ASSERT_NOT_REACHED(); 2122 ASSERT_NOT_REACHED();
2151 return nullptr; 2123 return nullptr;
2152 } 2124 }
2153 2125
2154 void LayoutObject::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, 2126 void LayoutObject::mapAncestorToLocal(const LayoutBoxModelObject* ancestor,
2155 TransformState& transformState, 2127 TransformState& transformState,
2156 MapCoordinatesFlags mode) const { 2128 MapCoordinatesFlags mode) const {
2157 if (this == ancestor) 2129 if (this == ancestor)
2158 return; 2130 return;
2159 2131
2160 bool ancestorSkipped; 2132 AncestorSkipInfo skipInfo(ancestor);
2161 LayoutObject* container = this->container(ancestor, &ancestorSkipped); 2133 LayoutObject* container = this->container(&skipInfo);
2162 if (!container) 2134 if (!container)
2163 return; 2135 return;
2164 2136
2165 bool applyContainerFlip = false; 2137 bool applyContainerFlip = false;
2166 if (mode & ApplyContainerFlip) { 2138 if (mode & ApplyContainerFlip) {
2167 if (isBox()) { 2139 if (isBox()) {
2168 mode &= ~ApplyContainerFlip; 2140 mode &= ~ApplyContainerFlip;
2169 } else if (container->isBox()) { 2141 } else if (container->isBox()) {
2170 applyContainerFlip = container->style()->isFlippedBlocksWritingMode(); 2142 applyContainerFlip = container->style()->isFlippedBlocksWritingMode();
2171 mode &= ~ApplyContainerFlip; 2143 mode &= ~ApplyContainerFlip;
2172 } 2144 }
2173 } 2145 }
2174 2146
2175 if (!ancestorSkipped) 2147 if (!skipInfo.ancestorSkipped())
2176 container->mapAncestorToLocal(ancestor, transformState, mode); 2148 container->mapAncestorToLocal(ancestor, transformState, mode);
2177 2149
2178 LayoutSize containerOffset = offsetFromContainer(container); 2150 LayoutSize containerOffset = offsetFromContainer(container);
2179 bool preserve3D = 2151 bool preserve3D =
2180 mode & UseTransforms && 2152 mode & UseTransforms &&
2181 (container->style()->preserves3D() || style()->preserves3D()); 2153 (container->style()->preserves3D() || style()->preserves3D());
2182 if (mode & UseTransforms && shouldUseTransformFromContainer(container)) { 2154 if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
2183 TransformationMatrix t; 2155 TransformationMatrix t;
2184 getTransformFromContainer(container, containerOffset, t); 2156 getTransformFromContainer(container, containerOffset, t);
2185 transformState.applyTransform(t, preserve3D 2157 transformState.applyTransform(t, preserve3D
(...skipping 14 matching lines...) Expand all
2200 toLayoutFlowThread(this)->visualPointToFlowThreadPoint(visualPoint)); 2172 toLayoutFlowThread(this)->visualPointToFlowThreadPoint(visualPoint));
2201 } 2173 }
2202 2174
2203 if (applyContainerFlip) { 2175 if (applyContainerFlip) {
2204 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint()); 2176 IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
2205 transformState.move( 2177 transformState.move(
2206 centerPoint - 2178 centerPoint -
2207 toLayoutBox(container)->flipForWritingMode(LayoutPoint(centerPoint))); 2179 toLayoutBox(container)->flipForWritingMode(LayoutPoint(centerPoint)));
2208 } 2180 }
2209 2181
2210 if (ancestorSkipped) { 2182 if (skipInfo.ancestorSkipped()) {
2211 containerOffset = ancestor->offsetFromAncestorContainer(container); 2183 containerOffset = ancestor->offsetFromAncestorContainer(container);
2212 transformState.move(-containerOffset.width(), -containerOffset.height()); 2184 transformState.move(-containerOffset.width(), -containerOffset.height());
2213 // If the ancestor is fixed, then the rect is already in its coordinates so 2185 // If the ancestor is fixed, then the rect is already in its coordinates so
2214 // doesn't need viewport-adjusting. 2186 // doesn't need viewport-adjusting.
2215 if (ancestor->style()->position() != FixedPosition && 2187 if (ancestor->style()->position() != FixedPosition &&
2216 container->isLayoutView() && styleRef().position() == FixedPosition) { 2188 container->isLayoutView() && styleRef().position() == FixedPosition) {
2217 LayoutSize adjustment = toLayoutView(container)->offsetForFixedPosition(); 2189 LayoutSize adjustment = toLayoutView(container)->offsetForFixedPosition();
2218 transformState.move(adjustment.width(), adjustment.height()); 2190 transformState.move(adjustment.width(), adjustment.height());
2219 } 2191 }
2220 } 2192 }
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 return RespectImageOrientation; 2444 return RespectImageOrientation;
2473 2445
2474 if (layoutObject->style() && 2446 if (layoutObject->style() &&
2475 layoutObject->style()->respectImageOrientation() == 2447 layoutObject->style()->respectImageOrientation() ==
2476 RespectImageOrientation) 2448 RespectImageOrientation)
2477 return RespectImageOrientation; 2449 return RespectImageOrientation;
2478 2450
2479 return DoNotRespectImageOrientation; 2451 return DoNotRespectImageOrientation;
2480 } 2452 }
2481 2453
2482 LayoutObject* LayoutObject::container(const LayoutBoxModelObject* ancestor, 2454 LayoutObject* LayoutObject::container(AncestorSkipInfo* skipInfo) const {
2483 bool* ancestorSkipped, 2455 // TODO(mstensho): Get rid of this. Nobody should call this method with those
2484 bool* filterSkipped) const { 2456 // flags already set.
2485 if (ancestorSkipped) 2457 if (skipInfo)
2486 *ancestorSkipped = false; 2458 skipInfo->resetOutput();
2487 if (filterSkipped)
2488 *filterSkipped = false;
2489 2459
2490 if (isTextOrSVGChild()) 2460 if (isTextOrSVGChild())
2491 return parent(); 2461 return parent();
2492 2462
2493 EPosition pos = m_style->position(); 2463 EPosition pos = m_style->position();
2494 if (pos == FixedPosition) 2464 if (pos == FixedPosition)
2495 return containerForFixedPosition(ancestor, ancestorSkipped, filterSkipped); 2465 return containerForFixedPosition(skipInfo);
2496 2466
2497 if (pos == AbsolutePosition) { 2467 if (pos == AbsolutePosition) {
2498 return containerForAbsolutePosition(ancestor, ancestorSkipped, 2468 return containerForAbsolutePosition(skipInfo);
2499 filterSkipped);
2500 } 2469 }
2501 2470
2502 if (isColumnSpanAll()) { 2471 if (isColumnSpanAll()) {
2503 LayoutObject* multicolContainer = spannerPlaceholder()->container(); 2472 LayoutObject* multicolContainer = spannerPlaceholder()->container();
2504 if ((ancestorSkipped && ancestor) || filterSkipped) { 2473 if (skipInfo) {
2505 // We jumped directly from the spanner to the multicol container. Need to 2474 // We jumped directly from the spanner to the multicol container. Need to
2506 // check if we skipped |ancestor| or filter/reflection on the way. 2475 // check if we skipped |ancestor| or filter/reflection on the way.
2507 for (LayoutObject* walker = parent(); 2476 for (LayoutObject* walker = parent();
2508 walker && walker != multicolContainer; walker = walker->parent()) { 2477 walker && walker != multicolContainer; walker = walker->parent())
2509 if (ancestorSkipped && walker == ancestor) 2478 skipInfo->update(*walker);
2510 *ancestorSkipped = true;
2511 if (filterSkipped && walker->hasFilterInducingProperty())
2512 *filterSkipped = true;
2513 }
2514 } 2479 }
2515 return multicolContainer; 2480 return multicolContainer;
2516 } 2481 }
2517 2482
2518 if (isFloating()) 2483 if (isFloating())
2519 return containingBlock(ancestor, ancestorSkipped, filterSkipped); 2484 return containingBlock(skipInfo);
2520 2485
2521 return parent(); 2486 return parent();
2522 } 2487 }
2523 2488
2524 inline LayoutObject* LayoutObject::paintInvalidationParent() const { 2489 inline LayoutObject* LayoutObject::paintInvalidationParent() const {
2525 if (isLayoutView()) 2490 if (isLayoutView())
2526 return LayoutAPIShim::layoutObjectFrom(frame()->ownerLayoutItem()); 2491 return LayoutAPIShim::layoutObjectFrom(frame()->ownerLayoutItem());
2527 return parent(); 2492 return parent();
2528 } 2493 }
2529 2494
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
3508 const blink::LayoutObject* root = object1; 3473 const blink::LayoutObject* root = object1;
3509 while (root->parent()) 3474 while (root->parent())
3510 root = root->parent(); 3475 root = root->parent();
3511 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0); 3476 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0);
3512 } else { 3477 } else {
3513 WTFLogAlways("%s", "Cannot showLayoutTree. Root is (nil)"); 3478 WTFLogAlways("%s", "Cannot showLayoutTree. Root is (nil)");
3514 } 3479 }
3515 } 3480 }
3516 3481
3517 #endif 3482 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutObject.h ('k') | third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698