Chromium Code Reviews| 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 2094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2105 return; | 2105 return; |
| 2106 m_rareData->m_spannerPlaceholder = nullptr; | 2106 m_rareData->m_spannerPlaceholder = nullptr; |
| 2107 } | 2107 } |
| 2108 | 2108 |
| 2109 void LayoutBox::setPaginationStrut(LayoutUnit strut) { | 2109 void LayoutBox::setPaginationStrut(LayoutUnit strut) { |
| 2110 if (!strut && !m_rareData) | 2110 if (!strut && !m_rareData) |
| 2111 return; | 2111 return; |
| 2112 ensureRareData().m_paginationStrut = strut; | 2112 ensureRareData().m_paginationStrut = strut; |
| 2113 } | 2113 } |
| 2114 | 2114 |
| 2115 bool LayoutBox::isBreakBetweenControllable(EBreak breakValue) const { | 2115 bool LayoutBox::isBreakBetweenControllable(EBreakBetween breakValue) const { |
| 2116 if (breakValue == BreakAuto) | 2116 if (breakValue == EBreakBetween::kAuto) |
| 2117 return true; | 2117 return true; |
| 2118 // We currently only support non-auto break-before and break-after values on | 2118 // We currently only support non-auto break-before and break-after values on |
| 2119 // in-flow block level elements, which is the minimum requirement according to | 2119 // in-flow block level elements, which is the minimum requirement according to |
| 2120 // the spec. | 2120 // the spec. |
| 2121 if (isInline() || isFloatingOrOutOfFlowPositioned()) | 2121 if (isInline() || isFloatingOrOutOfFlowPositioned()) |
| 2122 return false; | 2122 return false; |
| 2123 const LayoutBlock* curr = containingBlock(); | 2123 const LayoutBlock* curr = containingBlock(); |
| 2124 if (!curr || !curr->isLayoutBlockFlow()) | 2124 if (!curr || !curr->isLayoutBlockFlow()) |
| 2125 return false; | 2125 return false; |
| 2126 const LayoutView* layoutView = view(); | 2126 const LayoutView* layoutView = view(); |
| 2127 bool viewIsPaginated = layoutView->fragmentationContext(); | 2127 bool viewIsPaginated = layoutView->fragmentationContext(); |
| 2128 if (!viewIsPaginated && !flowThreadContainingBlock()) | 2128 if (!viewIsPaginated && !flowThreadContainingBlock()) |
| 2129 return false; | 2129 return false; |
| 2130 while (curr) { | 2130 while (curr) { |
| 2131 if (curr == layoutView) | 2131 if (curr == layoutView) { |
| 2132 return viewIsPaginated && breakValue != BreakColumn && | 2132 return viewIsPaginated && breakValue != EBreakBetween::kColumn && |
| 2133 breakValue != BreakAvoidColumn; | 2133 breakValue != EBreakBetween::kAvoidColumn; |
| 2134 } | |
| 2134 if (curr->isLayoutFlowThread()) { | 2135 if (curr->isLayoutFlowThread()) { |
| 2135 if (breakValue == | 2136 if (breakValue == |
| 2136 BreakAvoid) // Valid in any kind of fragmentation context. | 2137 EBreakBetween::kAvoid) // Valid in any kind of fragmentation context. |
| 2137 return true; | 2138 return true; |
| 2138 bool isMulticolValue = | 2139 bool isMulticolValue = breakValue == EBreakBetween::kColumn || |
| 2139 breakValue == BreakColumn || breakValue == BreakAvoidColumn; | 2140 breakValue == EBreakBetween::kAvoidColumn; |
| 2140 if (toLayoutFlowThread(curr)->isLayoutPagedFlowThread()) | 2141 if (toLayoutFlowThread(curr)->isLayoutPagedFlowThread()) |
| 2141 return !isMulticolValue; | 2142 return !isMulticolValue; |
| 2142 if (isMulticolValue) | 2143 if (isMulticolValue) |
| 2143 return true; | 2144 return true; |
| 2144 // If this is a flow thread for a multicol container, and we have a break | 2145 // If this is a flow thread for a multicol container, and we have a break |
| 2145 // value for paged, we need to keep looking. | 2146 // value for paged, we need to keep looking. |
| 2146 } | 2147 } |
| 2147 if (curr->isFloatingOrOutOfFlowPositioned()) | 2148 if (curr->isFloatingOrOutOfFlowPositioned()) |
| 2148 return false; | 2149 return false; |
| 2149 curr = curr->containingBlock(); | 2150 curr = curr->containingBlock(); |
| 2150 } | 2151 } |
| 2151 ASSERT_NOT_REACHED(); | 2152 ASSERT_NOT_REACHED(); |
| 2152 return false; | 2153 return false; |
| 2153 } | 2154 } |
| 2154 | 2155 |
| 2155 bool LayoutBox::isBreakInsideControllable(EBreak breakValue) const { | 2156 bool LayoutBox::isBreakInsideControllable(EBreakInside breakValue) const { |
| 2156 ASSERT(!isForcedFragmentainerBreakValue(breakValue)); | 2157 if (breakValue == EBreakInside::kAuto) |
| 2157 if (breakValue == BreakAuto) | |
|
amoylan
2017/02/07 04:35:02
This ASSERT is not required now that we have split
mstensho (USE GERRIT)
2017/02/07 10:21:34
Acknowledged. Good stuff!
| |
| 2158 return true; | 2158 return true; |
| 2159 // First check multicol. | 2159 // First check multicol. |
| 2160 const LayoutFlowThread* flowThread = flowThreadContainingBlock(); | 2160 const LayoutFlowThread* flowThread = flowThreadContainingBlock(); |
| 2161 // 'avoid-column' is only valid in a multicol context. | 2161 // 'avoid-column' is only valid in a multicol context. |
| 2162 if (breakValue == BreakAvoidColumn) | 2162 if (breakValue == EBreakInside::kAvoidColumn) |
| 2163 return flowThread && !flowThread->isLayoutPagedFlowThread(); | 2163 return flowThread && !flowThread->isLayoutPagedFlowThread(); |
| 2164 // 'avoid' is valid in any kind of fragmentation context. | 2164 // 'avoid' is valid in any kind of fragmentation context. |
| 2165 if (breakValue == BreakAvoid && flowThread) | 2165 if (breakValue == EBreakInside::kAvoid && flowThread) |
| 2166 return true; | 2166 return true; |
| 2167 ASSERT(breakValue == BreakAvoidPage || breakValue == BreakAvoid); | 2167 DCHECK(breakValue == EBreakInside::kAvoidPage || |
| 2168 breakValue == EBreakInside::kAvoid); | |
| 2168 if (view()->fragmentationContext()) | 2169 if (view()->fragmentationContext()) |
| 2169 return true; // The view is paginated, probably because we're printing. | 2170 return true; // The view is paginated, probably because we're printing. |
| 2170 if (!flowThread) | 2171 if (!flowThread) |
| 2171 return false; // We're not inside any pagination context | 2172 return false; // We're not inside any pagination context |
| 2172 // We're inside a flow thread. We need to be contained by a flow thread for | 2173 // We're inside a flow thread. We need to be contained by a flow thread for |
| 2173 // paged overflow in order for pagination values to be valid, though. | 2174 // paged overflow in order for pagination values to be valid, though. |
| 2174 for (const LayoutBlock* ancestor = flowThread; ancestor; | 2175 for (const LayoutBlock* ancestor = flowThread; ancestor; |
| 2175 ancestor = ancestor->containingBlock()) { | 2176 ancestor = ancestor->containingBlock()) { |
| 2176 if (ancestor->isLayoutFlowThread() && | 2177 if (ancestor->isLayoutFlowThread() && |
| 2177 toLayoutFlowThread(ancestor)->isLayoutPagedFlowThread()) | 2178 toLayoutFlowThread(ancestor)->isLayoutPagedFlowThread()) |
| 2178 return true; | 2179 return true; |
| 2179 } | 2180 } |
| 2180 return false; | 2181 return false; |
| 2181 } | 2182 } |
| 2182 | 2183 |
| 2183 EBreak LayoutBox::breakAfter() const { | 2184 EBreakBetween LayoutBox::breakAfter() const { |
| 2184 EBreak breakValue = style()->breakAfter(); | 2185 EBreakBetween breakValue = style()->breakAfter(); |
| 2185 if (breakValue == BreakAuto || isBreakBetweenControllable(breakValue)) | 2186 if (breakValue == EBreakBetween::kAuto || |
| 2187 isBreakBetweenControllable(breakValue)) | |
| 2186 return breakValue; | 2188 return breakValue; |
| 2187 return BreakAuto; | 2189 return EBreakBetween::kAuto; |
| 2188 } | 2190 } |
| 2189 | 2191 |
| 2190 EBreak LayoutBox::breakBefore() const { | 2192 EBreakBetween LayoutBox::breakBefore() const { |
| 2191 EBreak breakValue = style()->breakBefore(); | 2193 EBreakBetween breakValue = style()->breakBefore(); |
| 2192 if (breakValue == BreakAuto || isBreakBetweenControllable(breakValue)) | 2194 if (breakValue == EBreakBetween::kAuto || |
| 2195 isBreakBetweenControllable(breakValue)) | |
| 2193 return breakValue; | 2196 return breakValue; |
| 2194 return BreakAuto; | 2197 return EBreakBetween::kAuto; |
| 2195 } | 2198 } |
| 2196 | 2199 |
| 2197 EBreak LayoutBox::breakInside() const { | 2200 EBreakInside LayoutBox::breakInside() const { |
| 2198 EBreak breakValue = style()->breakInside(); | 2201 EBreakInside breakValue = style()->breakInside(); |
| 2199 if (breakValue == BreakAuto || isBreakInsideControllable(breakValue)) | 2202 if (breakValue == EBreakInside::kAuto || |
| 2203 isBreakInsideControllable(breakValue)) | |
| 2200 return breakValue; | 2204 return breakValue; |
| 2201 return BreakAuto; | 2205 return EBreakInside::kAuto; |
| 2202 } | 2206 } |
| 2203 | 2207 |
| 2204 // At a class A break point [1], the break value with the highest precedence | 2208 // At a class A break point [1], the break value with the highest precedence |
| 2205 // wins. If the two values have the same precedence (e.g. "left" and "right"), | 2209 // wins. If the two values have the same precedence (e.g. "left" and "right"), |
| 2206 // the value specified on a latter object wins. | 2210 // the value specified on a latter object wins. |
| 2207 // | 2211 // |
| 2208 // [1] https://drafts.csswg.org/css-break/#possible-breaks | 2212 // [1] https://drafts.csswg.org/css-break/#possible-breaks |
| 2209 static inline int fragmentainerBreakPrecedence(EBreak breakValue) { | 2213 static inline int fragmentainerBreakPrecedence(EBreakBetween breakValue) { |
| 2210 // "auto" has the lowest priority. | 2214 // "auto" has the lowest priority. |
| 2211 // "avoid*" values win over "auto". | 2215 // "avoid*" values win over "auto". |
| 2212 // "avoid-page" wins over "avoid-column". | 2216 // "avoid-page" wins over "avoid-column". |
| 2213 // "avoid" wins over "avoid-page". | 2217 // "avoid" wins over "avoid-page". |
| 2214 // Forced break values win over "avoid". | 2218 // Forced break values win over "avoid". |
| 2215 // Any forced page break value wins over "column" forced break. | 2219 // Any forced page break value wins over "column" forced break. |
| 2216 // More specific break values (left, right, recto, verso) wins over generic | 2220 // More specific break values (left, right, recto, verso) wins over generic |
| 2217 // "page" values. | 2221 // "page" values. |
| 2218 | 2222 |
| 2219 switch (breakValue) { | 2223 switch (breakValue) { |
| 2220 default: | 2224 default: |
| 2221 ASSERT_NOT_REACHED(); | 2225 ASSERT_NOT_REACHED(); |
| 2222 // fall-through | 2226 // fall-through |
| 2223 case BreakAuto: | 2227 case EBreakBetween::kAuto: |
| 2224 return 0; | 2228 return 0; |
| 2225 case BreakAvoidColumn: | 2229 case EBreakBetween::kAvoidColumn: |
| 2226 return 1; | 2230 return 1; |
| 2227 case BreakAvoidPage: | 2231 case EBreakBetween::kAvoidPage: |
| 2228 return 2; | 2232 return 2; |
| 2229 case BreakAvoid: | 2233 case EBreakBetween::kAvoid: |
| 2230 return 3; | 2234 return 3; |
| 2231 case BreakColumn: | 2235 case EBreakBetween::kColumn: |
| 2232 return 4; | 2236 return 4; |
| 2233 case BreakPage: | 2237 case EBreakBetween::kPage: |
| 2234 return 5; | 2238 return 5; |
| 2235 case BreakLeft: | 2239 case EBreakBetween::kLeft: |
| 2236 case BreakRight: | 2240 case EBreakBetween::kRight: |
| 2237 case BreakRecto: | 2241 case EBreakBetween::kRecto: |
| 2238 case BreakVerso: | 2242 case EBreakBetween::kVerso: |
| 2239 return 6; | 2243 return 6; |
| 2240 } | 2244 } |
| 2241 } | 2245 } |
| 2242 | 2246 |
| 2243 EBreak LayoutBox::joinFragmentainerBreakValues(EBreak firstValue, | 2247 EBreakBetween LayoutBox::joinFragmentainerBreakValues( |
| 2244 EBreak secondValue) { | 2248 EBreakBetween firstValue, |
| 2249 EBreakBetween secondValue) { | |
| 2245 if (fragmentainerBreakPrecedence(secondValue) >= | 2250 if (fragmentainerBreakPrecedence(secondValue) >= |
| 2246 fragmentainerBreakPrecedence(firstValue)) | 2251 fragmentainerBreakPrecedence(firstValue)) |
| 2247 return secondValue; | 2252 return secondValue; |
| 2248 return firstValue; | 2253 return firstValue; |
| 2249 } | 2254 } |
| 2250 | 2255 |
| 2251 EBreak LayoutBox::classABreakPointValue(EBreak previousBreakAfterValue) const { | 2256 EBreakBetween LayoutBox::classABreakPointValue( |
| 2257 EBreakBetween previousBreakAfterValue) const { | |
| 2252 // First assert that we're at a class A break point. | 2258 // First assert that we're at a class A break point. |
| 2253 ASSERT(isBreakBetweenControllable(previousBreakAfterValue)); | 2259 ASSERT(isBreakBetweenControllable(previousBreakAfterValue)); |
| 2254 | 2260 |
| 2255 return joinFragmentainerBreakValues(previousBreakAfterValue, breakBefore()); | 2261 return joinFragmentainerBreakValues(previousBreakAfterValue, breakBefore()); |
| 2256 } | 2262 } |
| 2257 | 2263 |
| 2258 bool LayoutBox::needsForcedBreakBefore(EBreak previousBreakAfterValue) const { | 2264 bool LayoutBox::needsForcedBreakBefore( |
| 2265 EBreakBetween previousBreakAfterValue) const { | |
| 2259 // Forced break values are only honored when specified on in-flow objects, but | 2266 // Forced break values are only honored when specified on in-flow objects, but |
| 2260 // floats and out-of-flow positioned objects may be affected by a break-after | 2267 // floats and out-of-flow positioned objects may be affected by a break-after |
| 2261 // value of the previous in-flow object, even though we're not at a class A | 2268 // value of the previous in-flow object, even though we're not at a class A |
| 2262 // break point. | 2269 // break point. |
| 2263 EBreak breakValue = isFloatingOrOutOfFlowPositioned() | 2270 EBreakBetween breakValue = |
| 2264 ? previousBreakAfterValue | 2271 isFloatingOrOutOfFlowPositioned() |
| 2265 : classABreakPointValue(previousBreakAfterValue); | 2272 ? previousBreakAfterValue |
| 2273 : classABreakPointValue(previousBreakAfterValue); | |
| 2266 return isForcedFragmentainerBreakValue(breakValue); | 2274 return isForcedFragmentainerBreakValue(breakValue); |
| 2267 } | 2275 } |
| 2268 | 2276 |
| 2269 bool LayoutBox::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const { | 2277 bool LayoutBox::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const { |
| 2270 if (hasNonCompositedScrollbars() || getSelectionState() != SelectionNone || | 2278 if (hasNonCompositedScrollbars() || getSelectionState() != SelectionNone || |
| 2271 hasBoxDecorationBackground() || styleRef().hasBoxDecorations() || | 2279 hasBoxDecorationBackground() || styleRef().hasBoxDecorations() || |
| 2272 styleRef().hasVisualOverflowingEffect()) | 2280 styleRef().hasVisualOverflowingEffect()) |
| 2273 return false; | 2281 return false; |
| 2274 | 2282 |
| 2275 // If the box has clip or mask, we need issue paint invalidation to cover | 2283 // If the box has clip or mask, we need issue paint invalidation to cover |
| (...skipping 2753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5029 } | 5037 } |
| 5030 | 5038 |
| 5031 LayoutBox::PaginationBreakability LayoutBox::getPaginationBreakability() const { | 5039 LayoutBox::PaginationBreakability LayoutBox::getPaginationBreakability() const { |
| 5032 // TODO(mstensho): It is wrong to check isAtomicInlineLevel() as we | 5040 // TODO(mstensho): It is wrong to check isAtomicInlineLevel() as we |
| 5033 // actually look for replaced elements. | 5041 // actually look for replaced elements. |
| 5034 if (isAtomicInlineLevel() || hasUnsplittableScrollingOverflow() || | 5042 if (isAtomicInlineLevel() || hasUnsplittableScrollingOverflow() || |
| 5035 (parent() && isWritingModeRoot()) || | 5043 (parent() && isWritingModeRoot()) || |
| 5036 (isOutOfFlowPositioned() && style()->position() == FixedPosition)) | 5044 (isOutOfFlowPositioned() && style()->position() == FixedPosition)) |
| 5037 return ForbidBreaks; | 5045 return ForbidBreaks; |
| 5038 | 5046 |
| 5039 EBreak breakValue = breakInside(); | 5047 EBreakInside breakValue = breakInside(); |
| 5040 if (breakValue == BreakAvoid || breakValue == BreakAvoidPage || | 5048 if (breakValue == EBreakInside::kAvoid || |
| 5041 breakValue == BreakAvoidColumn) | 5049 breakValue == EBreakInside::kAvoidPage || |
| 5050 breakValue == EBreakInside::kAvoidColumn) | |
| 5042 return AvoidBreaks; | 5051 return AvoidBreaks; |
| 5043 return AllowAnyBreaks; | 5052 return AllowAnyBreaks; |
| 5044 } | 5053 } |
| 5045 | 5054 |
| 5046 LayoutUnit LayoutBox::lineHeight(bool /*firstLine*/, | 5055 LayoutUnit LayoutBox::lineHeight(bool /*firstLine*/, |
| 5047 LineDirectionMode direction, | 5056 LineDirectionMode direction, |
| 5048 LinePositionMode /*linePositionMode*/) const { | 5057 LinePositionMode /*linePositionMode*/) const { |
| 5049 if (isAtomicInlineLevel()) | 5058 if (isAtomicInlineLevel()) |
| 5050 return direction == HorizontalLine ? marginHeight() + size().height() | 5059 return direction == HorizontalLine ? marginHeight() + size().height() |
| 5051 : marginWidth() + size().width(); | 5060 : marginWidth() + size().width(); |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5697 block->adjustChildDebugRect(rect); | 5706 block->adjustChildDebugRect(rect); |
| 5698 | 5707 |
| 5699 return rect; | 5708 return rect; |
| 5700 } | 5709 } |
| 5701 | 5710 |
| 5702 bool LayoutBox::shouldClipOverflow() const { | 5711 bool LayoutBox::shouldClipOverflow() const { |
| 5703 return hasOverflowClip() || styleRef().containsPaint() || hasControlClip(); | 5712 return hasOverflowClip() || styleRef().containsPaint() || hasControlClip(); |
| 5704 } | 5713 } |
| 5705 | 5714 |
| 5706 } // namespace blink | 5715 } // namespace blink |
| OLD | NEW |