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) 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |