| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 } | 72 } |
| 73 | 73 |
| 74 const MultiColumnFragmentainerGroup& | 74 const MultiColumnFragmentainerGroup& |
| 75 LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint( | 75 LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint( |
| 76 const LayoutPoint& visual_point) const { | 76 const LayoutPoint& visual_point) const { |
| 77 DCHECK_GT(fragmentainer_groups_.size(), 0u); | 77 DCHECK_GT(fragmentainer_groups_.size(), 0u); |
| 78 LayoutUnit block_offset = | 78 LayoutUnit block_offset = |
| 79 IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X(); | 79 IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X(); |
| 80 for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) { | 80 for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) { |
| 81 const auto& row = fragmentainer_groups_[index]; | 81 const auto& row = fragmentainer_groups_[index]; |
| 82 if (row.LogicalTop() + row.LogicalHeight() > block_offset) | 82 if (row.LogicalTop() + row.GroupLogicalHeight() > block_offset) |
| 83 return row; | 83 return row; |
| 84 } | 84 } |
| 85 return fragmentainer_groups_.Last(); | 85 return fragmentainer_groups_.Last(); |
| 86 } | 86 } |
| 87 | 87 |
| 88 LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset( | 88 LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset( |
| 89 LayoutUnit offset_in_flow_thread) const { | 89 LayoutUnit offset_in_flow_thread) const { |
| 90 const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup(); | 90 const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup(); |
| 91 if (!last_row.LogicalHeight() && fragmentainer_groups_.size() == 1) { | 91 if (!last_row.GroupLogicalHeight() && fragmentainer_groups_.size() == 1) { |
| 92 // In the first layout pass of an auto-height multicol container, height | 92 // In the first layout pass of an auto-height multicol container, height |
| 93 // isn't set. No need to perform the series of complicated dance steps below | 93 // isn't set. No need to perform the series of complicated dance steps below |
| 94 // to figure out that we should simply return 0. Bail now. | 94 // to figure out that we should simply return 0. Bail now. |
| 95 return LayoutUnit(); | 95 return LayoutUnit(); |
| 96 } | 96 } |
| 97 if (offset_in_flow_thread >= last_row.LogicalTopInFlowThread() + | 97 if (offset_in_flow_thread >= last_row.LogicalTopInFlowThread() + |
| 98 FragmentainerGroupCapacity(last_row)) { | 98 FragmentainerGroupCapacity(last_row)) { |
| 99 // The offset is outside the bounds of the fragmentainer groups that we have | 99 // The offset is outside the bounds of the fragmentainer groups that we have |
| 100 // established at this point. If we're nested inside another fragmentation | 100 // established at this point. If we're nested inside another fragmentation |
| 101 // context, we need to calculate the height on our own. | 101 // context, we need to calculate the height on our own. |
| 102 const LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread(); | 102 const LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread(); |
| 103 if (FragmentationContext* enclosing_fragmentation_context = | 103 if (FragmentationContext* enclosing_fragmentation_context = |
| 104 flow_thread->EnclosingFragmentationContext()) { | 104 flow_thread->EnclosingFragmentationContext()) { |
| 105 // We'd ideally like to translate |offsetInFlowThread| to an offset in the | 105 // We'd ideally like to translate |offsetInFlowThread| to an offset in the |
| 106 // coordinate space of the enclosing fragmentation context here, but | 106 // coordinate space of the enclosing fragmentation context here, but |
| 107 // that's hard, since the offset is out of bounds. So just use the bottom | 107 // that's hard, since the offset is out of bounds. So just use the bottom |
| 108 // we have found so far. | 108 // we have found so far. |
| 109 LayoutUnit enclosing_context_bottom = | 109 LayoutUnit enclosing_context_bottom = |
| 110 last_row.BlockOffsetInEnclosingFragmentationContext() + | 110 last_row.BlockOffsetInEnclosingFragmentationContext() + |
| 111 last_row.LogicalHeight(); | 111 last_row.GroupLogicalHeight(); |
| 112 LayoutUnit enclosing_fragmentainer_height = | 112 LayoutUnit enclosing_fragmentainer_height = |
| 113 enclosing_fragmentation_context->FragmentainerLogicalHeightAt( | 113 enclosing_fragmentation_context->FragmentainerLogicalHeightAt( |
| 114 enclosing_context_bottom); | 114 enclosing_context_bottom); |
| 115 // Constrain against specified height / max-height. | 115 // Constrain against specified height / max-height. |
| 116 LayoutUnit current_multicol_height = LogicalTopFromMulticolContentEdge() + | 116 LayoutUnit current_multicol_height = LogicalTopFromMulticolContentEdge() + |
| 117 last_row.LogicalTop() + | 117 last_row.LogicalTop() + |
| 118 last_row.LogicalHeight(); | 118 last_row.GroupLogicalHeight(); |
| 119 LayoutUnit multicol_height_with_extra_row = | 119 LayoutUnit multicol_height_with_extra_row = |
| 120 current_multicol_height + enclosing_fragmentainer_height; | 120 current_multicol_height + enclosing_fragmentainer_height; |
| 121 multicol_height_with_extra_row = | 121 multicol_height_with_extra_row = |
| 122 std::min(multicol_height_with_extra_row, | 122 std::min(multicol_height_with_extra_row, |
| 123 flow_thread->MaxColumnLogicalHeight()); | 123 flow_thread->MaxColumnLogicalHeight()); |
| 124 return std::max(LayoutUnit(1), | 124 return std::max(LayoutUnit(1), |
| 125 multicol_height_with_extra_row - current_multicol_height); | 125 multicol_height_with_extra_row - current_multicol_height); |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 return FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, | 128 return FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, |
| 129 kAssociateWithLatterPage) | 129 kAssociateWithLatterPage) |
| 130 .LogicalHeight(); | 130 .ColumnLogicalHeight(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 LayoutUnit LayoutMultiColumnSet::PageRemainingLogicalHeightForOffset( | 133 LayoutUnit LayoutMultiColumnSet::PageRemainingLogicalHeightForOffset( |
| 134 LayoutUnit offset_in_flow_thread, | 134 LayoutUnit offset_in_flow_thread, |
| 135 PageBoundaryRule page_boundary_rule) const { | 135 PageBoundaryRule page_boundary_rule) const { |
| 136 const MultiColumnFragmentainerGroup& row = | 136 const MultiColumnFragmentainerGroup& row = |
| 137 FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, | 137 FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, |
| 138 page_boundary_rule); | 138 page_boundary_rule); |
| 139 LayoutUnit page_logical_height = row.LogicalHeight(); | 139 LayoutUnit page_logical_height = row.ColumnLogicalHeight(); |
| 140 LayoutUnit page_logical_bottom = | 140 LayoutUnit page_logical_bottom = |
| 141 row.ColumnLogicalTopForOffset(offset_in_flow_thread) + | 141 row.ColumnLogicalTopForOffset(offset_in_flow_thread) + |
| 142 page_logical_height; | 142 page_logical_height; |
| 143 LayoutUnit remaining_logical_height = | 143 LayoutUnit remaining_logical_height = |
| 144 page_logical_bottom - offset_in_flow_thread; | 144 page_logical_bottom - offset_in_flow_thread; |
| 145 | 145 |
| 146 if (page_boundary_rule == kAssociateWithFormerPage) { | 146 if (page_boundary_rule == kAssociateWithFormerPage) { |
| 147 // An offset exactly at a column boundary will act as being part of the | 147 // An offset exactly at a column boundary will act as being part of the |
| 148 // former column in question (i.e. no remaining space), rather than being | 148 // former column in question (i.e. no remaining space), rather than being |
| 149 // part of the latter (i.e. one whole column length of remaining space). | 149 // part of the latter (i.e. one whole column length of remaining space). |
| 150 remaining_logical_height = | 150 remaining_logical_height = |
| 151 IntMod(remaining_logical_height, page_logical_height); | 151 IntMod(remaining_logical_height, page_logical_height); |
| 152 } else if (!remaining_logical_height) { | 152 } else if (!remaining_logical_height) { |
| 153 // When pageBoundaryRule is AssociateWithLatterPage, we shouldn't just | 153 // When pageBoundaryRule is AssociateWithLatterPage, we shouldn't just |
| 154 // return 0 if there's no space left, because in that case we're at a | 154 // return 0 if there's no space left, because in that case we're at a |
| 155 // column boundary, in which case we should return the amount of space | 155 // column boundary, in which case we should return the amount of space |
| 156 // remaining in the *next* column. Note that the page height itself may be | 156 // remaining in the *next* column. Note that the page height itself may be |
| 157 // 0, though. | 157 // 0, though. |
| 158 remaining_logical_height = page_logical_height; | 158 remaining_logical_height = page_logical_height; |
| 159 } | 159 } |
| 160 return remaining_logical_height; | 160 return remaining_logical_height; |
| 161 } | 161 } |
| 162 | 162 |
| 163 bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const { | 163 bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const { |
| 164 return FirstFragmentainerGroup().LogicalHeight(); | 164 return FirstFragmentainerGroup().ColumnLogicalHeight(); |
| 165 } | 165 } |
| 166 | 166 |
| 167 bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const { | 167 bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const { |
| 168 if (!IsPageLogicalHeightKnown()) { | 168 if (!IsPageLogicalHeightKnown()) { |
| 169 // If we have no clue about the height of the multicol container, bail. This | 169 // If we have no clue about the height of the multicol container, bail. This |
| 170 // situation occurs initially when an auto-height multicol container is | 170 // situation occurs initially when an auto-height multicol container is |
| 171 // nested inside another auto-height multicol container. We need at least an | 171 // nested inside another auto-height multicol container. We need at least an |
| 172 // estimated height of the outer multicol container before we can check what | 172 // estimated height of the outer multicol container before we can check what |
| 173 // an inner fragmentainer group has room for. | 173 // an inner fragmentainer group has room for. |
| 174 // Its height is indefinite for now. | 174 // Its height is indefinite for now. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 // multicol), we need to look beyond the first row here. | 207 // multicol), we need to look beyond the first row here. |
| 208 const MultiColumnFragmentainerGroup& first_row = FirstFragmentainerGroup(); | 208 const MultiColumnFragmentainerGroup& first_row = FirstFragmentainerGroup(); |
| 209 LayoutUnit first_row_logical_bottom_in_flow_thread = | 209 LayoutUnit first_row_logical_bottom_in_flow_thread = |
| 210 first_row.LogicalTopInFlowThread() + | 210 first_row.LogicalTopInFlowThread() + |
| 211 FragmentainerGroupCapacity(first_row); | 211 FragmentainerGroupCapacity(first_row); |
| 212 if (flow_thread_offset >= first_row_logical_bottom_in_flow_thread) | 212 if (flow_thread_offset >= first_row_logical_bottom_in_flow_thread) |
| 213 return flow_thread_offset; // We're not in the first row. Give up. | 213 return flow_thread_offset; // We're not in the first row. Give up. |
| 214 LayoutUnit new_logical_height = | 214 LayoutUnit new_logical_height = |
| 215 enclosing_fragmentation_context->FragmentainerLogicalHeightAt( | 215 enclosing_fragmentation_context->FragmentainerLogicalHeightAt( |
| 216 first_row.BlockOffsetInEnclosingFragmentationContext() + | 216 first_row.BlockOffsetInEnclosingFragmentationContext() + |
| 217 first_row.LogicalHeight()); | 217 first_row.GroupLogicalHeight()); |
| 218 if (content_logical_height > new_logical_height) { | 218 if (content_logical_height > new_logical_height) { |
| 219 // The next outer column or page doesn't have enough space either. Give up | 219 // The next outer column or page doesn't have enough space either. Give up |
| 220 // and stay where we are. | 220 // and stay where we are. |
| 221 return flow_thread_offset; | 221 return flow_thread_offset; |
| 222 } | 222 } |
| 223 return first_row_logical_bottom_in_flow_thread; | 223 return first_row_logical_bottom_in_flow_thread; |
| 224 } | 224 } |
| 225 | 225 |
| 226 LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const { | 226 LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const { |
| 227 for (LayoutObject* sibling = NextSibling(); sibling; | 227 for (LayoutObject* sibling = NextSibling(); sibling; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 // multicol container. When setting up a new fragmentainer group, we always | 276 // multicol container. When setting up a new fragmentainer group, we always |
| 277 // constrain against the remaining portion of any specified | 277 // constrain against the remaining portion of any specified |
| 278 // height/max-height. This means that we shouldn't allow creation of | 278 // height/max-height. This means that we shouldn't allow creation of |
| 279 // fragmentainer groups below the bottom of the multicol container, or we'd | 279 // fragmentainer groups below the bottom of the multicol container, or we'd |
| 280 // end up with zero-height fragmentainer groups (or actually 1px; see | 280 // end up with zero-height fragmentainer groups (or actually 1px; see |
| 281 // heightAdjustedForRowOffset() in MultiColumnFragmentainerGroup, which | 281 // heightAdjustedForRowOffset() in MultiColumnFragmentainerGroup, which |
| 282 // guards against zero-height groups), i.e. potentially a lot of pretty | 282 // guards against zero-height groups), i.e. potentially a lot of pretty |
| 283 // useless fragmentainer groups, and possibly broken layout too. Instead, | 283 // useless fragmentainer groups, and possibly broken layout too. Instead, |
| 284 // we'll just allow additional (overflowing) columns to be created in the | 284 // we'll just allow additional (overflowing) columns to be created in the |
| 285 // last fragmentainer group, similar to what we do when we're not nested. | 285 // last fragmentainer group, similar to what we do when we're not nested. |
| 286 LayoutUnit logical_bottom = last_row.LogicalTop() + last_row.LogicalHeight(); | 286 LayoutUnit logical_bottom = |
| 287 last_row.LogicalTop() + last_row.GroupLogicalHeight(); |
| 287 LayoutUnit space_used = logical_bottom + LogicalTopFromMulticolContentEdge(); | 288 LayoutUnit space_used = logical_bottom + LogicalTopFromMulticolContentEdge(); |
| 288 LayoutUnit max_column_height = | 289 LayoutUnit max_column_height = |
| 289 MultiColumnFlowThread()->MaxColumnLogicalHeight(); | 290 MultiColumnFlowThread()->MaxColumnLogicalHeight(); |
| 290 return max_column_height - space_used > LayoutUnit(); | 291 return max_column_height - space_used > LayoutUnit(); |
| 291 } | 292 } |
| 292 | 293 |
| 293 MultiColumnFragmentainerGroup& | 294 MultiColumnFragmentainerGroup& |
| 294 LayoutMultiColumnSet::AppendNewFragmentainerGroup() { | 295 LayoutMultiColumnSet::AppendNewFragmentainerGroup() { |
| 295 MultiColumnFragmentainerGroup new_group(*this); | 296 MultiColumnFragmentainerGroup new_group(*this); |
| 296 { // Extra scope here for previousGroup; it's potentially invalid once we | 297 { // Extra scope here for previousGroup; it's potentially invalid once we |
| 297 // modify the m_fragmentainerGroups Vector. | 298 // modify the m_fragmentainerGroups Vector. |
| 298 MultiColumnFragmentainerGroup& previous_group = | 299 MultiColumnFragmentainerGroup& previous_group = |
| 299 fragmentainer_groups_.Last(); | 300 fragmentainer_groups_.Last(); |
| 300 | 301 |
| 301 // This is the flow thread block offset where |previousGroup| ends and | 302 // This is the flow thread block offset where |previousGroup| ends and |
| 302 // |newGroup| takes over. | 303 // |newGroup| takes over. |
| 303 LayoutUnit block_offset_in_flow_thread = | 304 LayoutUnit block_offset_in_flow_thread = |
| 304 previous_group.LogicalTopInFlowThread() + | 305 previous_group.LogicalTopInFlowThread() + |
| 305 FragmentainerGroupCapacity(previous_group); | 306 FragmentainerGroupCapacity(previous_group); |
| 306 previous_group.SetLogicalBottomInFlowThread(block_offset_in_flow_thread); | 307 previous_group.SetLogicalBottomInFlowThread(block_offset_in_flow_thread); |
| 307 new_group.SetLogicalTopInFlowThread(block_offset_in_flow_thread); | 308 new_group.SetLogicalTopInFlowThread(block_offset_in_flow_thread); |
| 308 new_group.SetLogicalTop(previous_group.LogicalTop() + | 309 new_group.SetLogicalTop(previous_group.LogicalTop() + |
| 309 previous_group.LogicalHeight()); | 310 previous_group.GroupLogicalHeight()); |
| 310 new_group.ResetColumnHeight(); | 311 new_group.ResetColumnHeight(); |
| 311 } | 312 } |
| 312 fragmentainer_groups_.Append(new_group); | 313 fragmentainer_groups_.Append(new_group); |
| 313 return fragmentainer_groups_.Last(); | 314 return fragmentainer_groups_.Last(); |
| 314 } | 315 } |
| 315 | 316 |
| 316 LayoutUnit LayoutMultiColumnSet::LogicalTopFromMulticolContentEdge() const { | 317 LayoutUnit LayoutMultiColumnSet::LogicalTopFromMulticolContentEdge() const { |
| 317 // We subtract the position of the first column set or spanner placeholder, | 318 // We subtract the position of the first column set or spanner placeholder, |
| 318 // rather than the "before" border+padding of the multicol container. This | 319 // rather than the "before" border+padding of the multicol container. This |
| 319 // distinction doesn't matter after layout, but during layout it does: | 320 // distinction doesn't matter after layout, but during layout it does: |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 min_logical_width = flow_thread_->MinPreferredLogicalWidth(); | 456 min_logical_width = flow_thread_->MinPreferredLogicalWidth(); |
| 456 max_logical_width = flow_thread_->MaxPreferredLogicalWidth(); | 457 max_logical_width = flow_thread_->MaxPreferredLogicalWidth(); |
| 457 } | 458 } |
| 458 | 459 |
| 459 void LayoutMultiColumnSet::ComputeLogicalHeight( | 460 void LayoutMultiColumnSet::ComputeLogicalHeight( |
| 460 LayoutUnit, | 461 LayoutUnit, |
| 461 LayoutUnit logical_top, | 462 LayoutUnit logical_top, |
| 462 LogicalExtentComputedValues& computed_values) const { | 463 LogicalExtentComputedValues& computed_values) const { |
| 463 LayoutUnit logical_height; | 464 LayoutUnit logical_height; |
| 464 for (const auto& group : fragmentainer_groups_) | 465 for (const auto& group : fragmentainer_groups_) |
| 465 logical_height += group.LogicalHeight(); | 466 logical_height += group.GroupLogicalHeight(); |
| 466 computed_values.extent_ = logical_height; | 467 computed_values.extent_ = logical_height; |
| 467 computed_values.position_ = logical_top; | 468 computed_values.position_ = logical_top; |
| 468 } | 469 } |
| 469 | 470 |
| 470 PositionWithAffinity LayoutMultiColumnSet::PositionForPoint( | 471 PositionWithAffinity LayoutMultiColumnSet::PositionForPoint( |
| 471 const LayoutPoint& point) { | 472 const LayoutPoint& point) { |
| 472 // Convert the visual point to a flow thread point. | 473 // Convert the visual point to a flow thread point. |
| 473 const MultiColumnFragmentainerGroup& row = | 474 const MultiColumnFragmentainerGroup& row = |
| 474 FragmentainerGroupAtVisualPoint(point); | 475 FragmentainerGroupAtVisualPoint(point); |
| 475 LayoutPoint flow_thread_point = row.VisualPointToFlowThreadPoint( | 476 LayoutPoint flow_thread_point = row.VisualPointToFlowThreadPoint( |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 // Now add in column rule bounds, if present. | 626 // Now add in column rule bounds, if present. |
| 626 Vector<LayoutRect> column_rule_bounds; | 627 Vector<LayoutRect> column_rule_bounds; |
| 627 if (ComputeColumnRuleBounds(LayoutPoint(), column_rule_bounds)) { | 628 if (ComputeColumnRuleBounds(LayoutPoint(), column_rule_bounds)) { |
| 628 for (auto& bound : column_rule_bounds) | 629 for (auto& bound : column_rule_bounds) |
| 629 block_flow_bounds.Unite(bound); | 630 block_flow_bounds.Unite(bound); |
| 630 } | 631 } |
| 631 return block_flow_bounds; | 632 return block_flow_bounds; |
| 632 } | 633 } |
| 633 | 634 |
| 634 } // namespace blink | 635 } // namespace blink |
| OLD | NEW |