| 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 14 matching lines...) Expand all Loading... |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "core/rendering/RenderMultiColumnFlowThread.h" | 27 #include "core/rendering/RenderMultiColumnFlowThread.h" |
| 28 | 28 |
| 29 #include "core/rendering/RenderMultiColumnSet.h" | 29 #include "core/rendering/RenderMultiColumnSet.h" |
| 30 | 30 |
| 31 namespace WebCore { | 31 namespace WebCore { |
| 32 | 32 |
| 33 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread() | 33 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread() |
| 34 : m_columnCount(1) | 34 : m_columnCount(1) |
| 35 , m_columnWidth(0) | |
| 36 , m_columnHeightAvailable(0) | 35 , m_columnHeightAvailable(0) |
| 37 , m_inBalancingPass(false) | 36 , m_inBalancingPass(false) |
| 38 , m_needsColumnHeightsRecalculation(false) | 37 , m_needsColumnHeightsRecalculation(false) |
| 39 { | 38 { |
| 40 setFlowThreadState(InsideInFlowThread); | 39 setFlowThreadState(InsideInFlowThread); |
| 41 } | 40 } |
| 42 | 41 |
| 43 RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread() | 42 RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread() |
| 44 { | 43 { |
| 45 } | 44 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 | 129 |
| 131 LayoutPoint flowThreadPoint(point); | 130 LayoutPoint flowThreadPoint(point); |
| 132 flipForWritingMode(flowThreadPoint); | 131 flipForWritingMode(flowThreadPoint); |
| 133 LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : f
lowThreadPoint.x(); | 132 LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : f
lowThreadPoint.x(); |
| 134 RenderRegion* renderRegion = regionAtBlockOffset(blockOffset); | 133 RenderRegion* renderRegion = regionAtBlockOffset(blockOffset); |
| 135 if (!renderRegion) | 134 if (!renderRegion) |
| 136 return LayoutSize(0, 0); | 135 return LayoutSize(0, 0); |
| 137 return toRenderMultiColumnSet(renderRegion)->flowThreadTranslationAtOffset(b
lockOffset); | 136 return toRenderMultiColumnSet(renderRegion)->flowThreadTranslationAtOffset(b
lockOffset); |
| 138 } | 137 } |
| 139 | 138 |
| 139 bool RenderMultiColumnFlowThread::needsNewWidth() const |
| 140 { |
| 141 LayoutUnit newWidth; |
| 142 unsigned dummyColumnCount; // We only care if used column-width changes. |
| 143 calculateColumnCountAndWidth(newWidth, dummyColumnCount); |
| 144 return newWidth != logicalWidth(); |
| 145 } |
| 146 |
| 140 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa
youtScope& layoutScope) | 147 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa
youtScope& layoutScope) |
| 141 { | 148 { |
| 142 if (relayoutChildren) | 149 if (relayoutChildren) |
| 143 layoutScope.setChildNeedsLayout(this); | 150 layoutScope.setChildNeedsLayout(this); |
| 144 | 151 |
| 145 if (!needsLayout()) { | 152 if (!needsLayout()) { |
| 146 // Just before the multicol container (our parent RenderBlockFlow) finis
hes laying out, it | 153 // Just before the multicol container (our parent RenderBlockFlow) finis
hes laying out, it |
| 147 // will call recalculateColumnHeights() on us unconditionally, but we on
ly want that method | 154 // will call recalculateColumnHeights() on us unconditionally, but we on
ly want that method |
| 148 // to do any work if we actually laid out the flow thread. Otherwise, th
e balancing | 155 // to do any work if we actually laid out the flow thread. Otherwise, th
e balancing |
| 149 // machinery would kick in needlessly, and trigger additional layout pas
ses. Furthermore, we | 156 // machinery would kick in needlessly, and trigger additional layout pas
ses. Furthermore, we |
| 150 // actually depend on a proper flowthread layout pass in order to do bal
ancing, since it's | 157 // actually depend on a proper flowthread layout pass in order to do bal
ancing, since it's |
| 151 // flowthread layout that sets up content runs. | 158 // flowthread layout that sets up content runs. |
| 152 m_needsColumnHeightsRecalculation = false; | 159 m_needsColumnHeightsRecalculation = false; |
| 153 return; | 160 return; |
| 154 } | 161 } |
| 155 | 162 |
| 156 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col
umnSet = columnSet->nextSiblingMultiColumnSet()) { | 163 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col
umnSet = columnSet->nextSiblingMultiColumnSet()) { |
| 157 if (!m_inBalancingPass) { | 164 if (!m_inBalancingPass) { |
| 158 // This is the initial layout pass. We need to reset the column heig
ht, because contents | 165 // This is the initial layout pass. We need to reset the column heig
ht, because contents |
| 159 // typically have changed. | 166 // typically have changed. |
| 160 columnSet->resetColumnHeight(); | 167 columnSet->resetColumnHeight(); |
| 161 | |
| 162 columnSet->setComputedColumnWidthAndCount(columnWidth(), columnCount
()); | |
| 163 } | 168 } |
| 164 } | 169 } |
| 165 | 170 |
| 166 invalidateRegions(); | 171 invalidateRegions(); |
| 167 m_needsColumnHeightsRecalculation = requiresBalancing(); | 172 m_needsColumnHeightsRecalculation = requiresBalancing(); |
| 168 layout(); | 173 layout(); |
| 169 } | 174 } |
| 170 | 175 |
| 171 bool RenderMultiColumnFlowThread::computeColumnCountAndWidth() | |
| 172 { | |
| 173 RenderBlock* columnBlock = multiColumnBlockFlow(); | |
| 174 LayoutUnit oldColumnWidth = m_columnWidth; | |
| 175 | |
| 176 // Calculate our column width and column count. | |
| 177 m_columnCount = 1; | |
| 178 m_columnWidth = columnBlock->contentLogicalWidth(); | |
| 179 | |
| 180 const RenderStyle* columnStyle = columnBlock->style(); | |
| 181 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt
h()); | |
| 182 | |
| 183 LayoutUnit availWidth = m_columnWidth; | |
| 184 LayoutUnit colGap = columnBlock->columnGap(); | |
| 185 LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->columnWidth
())); | |
| 186 int colCount = max<int>(1, columnStyle->columnCount()); | |
| 187 | |
| 188 if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount())
{ | |
| 189 m_columnCount = colCount; | |
| 190 m_columnWidth = std::max<LayoutUnit>(0, (availWidth - ((m_columnCount -
1) * colGap)) / m_columnCount); | |
| 191 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC
ount()) { | |
| 192 m_columnCount = std::max<LayoutUnit>(1, (availWidth + colGap) / (colWidt
h + colGap)); | |
| 193 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; | |
| 194 } else { | |
| 195 m_columnCount = std::max<LayoutUnit>(std::min<LayoutUnit>(colCount, (ava
ilWidth + colGap) / (colWidth + colGap)), 1); | |
| 196 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; | |
| 197 } | |
| 198 | |
| 199 return m_columnWidth != oldColumnWidth; | |
| 200 } | |
| 201 | |
| 202 bool RenderMultiColumnFlowThread::recalculateColumnHeights() | 176 bool RenderMultiColumnFlowThread::recalculateColumnHeights() |
| 203 { | 177 { |
| 204 // All column sets that needed layout have now been laid out, so we can fina
lly validate them. | 178 // All column sets that needed layout have now been laid out, so we can fina
lly validate them. |
| 205 validateRegions(); | 179 validateRegions(); |
| 206 | 180 |
| 207 if (!m_needsColumnHeightsRecalculation) | 181 if (!m_needsColumnHeightsRecalculation) |
| 208 return false; | 182 return false; |
| 209 | 183 |
| 210 // Column heights may change here because of balancing. We may have to do mu
ltiple layout | 184 // Column heights may change here because of balancing. We may have to do mu
ltiple layout |
| 211 // passes, depending on how the contents is fitted to the changed column hei
ghts. In most | 185 // passes, depending on how the contents is fitted to the changed column hei
ghts. In most |
| (...skipping 12 matching lines...) Expand all Loading... |
| 224 } | 198 } |
| 225 } | 199 } |
| 226 | 200 |
| 227 if (needsRelayout) | 201 if (needsRelayout) |
| 228 setChildNeedsLayout(MarkOnlyThis); | 202 setChildNeedsLayout(MarkOnlyThis); |
| 229 | 203 |
| 230 m_inBalancingPass = needsRelayout; | 204 m_inBalancingPass = needsRelayout; |
| 231 return needsRelayout; | 205 return needsRelayout; |
| 232 } | 206 } |
| 233 | 207 |
| 208 void RenderMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width
, unsigned& count) const |
| 209 { |
| 210 RenderBlock* columnBlock = multiColumnBlockFlow(); |
| 211 const RenderStyle* columnStyle = columnBlock->style(); |
| 212 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); |
| 213 LayoutUnit columnGap = columnBlock->columnGap(); |
| 214 LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->
columnWidth())); |
| 215 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); |
| 216 |
| 217 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt
h()); |
| 218 if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount())
{ |
| 219 count = computedColumnCount; |
| 220 width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnG
ap)) / count); |
| 221 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC
ount()) { |
| 222 count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computed
ColumnWidth + columnGap)); |
| 223 width = ((availableWidth + columnGap) / count) - columnGap; |
| 224 } else { |
| 225 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, (
availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1); |
| 226 width = ((availableWidth + columnGap) / count) - columnGap; |
| 227 } |
| 228 } |
| 229 |
| 234 const char* RenderMultiColumnFlowThread::renderName() const | 230 const char* RenderMultiColumnFlowThread::renderName() const |
| 235 { | 231 { |
| 236 return "RenderMultiColumnFlowThread"; | 232 return "RenderMultiColumnFlowThread"; |
| 237 } | 233 } |
| 238 | 234 |
| 239 void RenderMultiColumnFlowThread::addRegionToThread(RenderRegion* renderRegion) | 235 void RenderMultiColumnFlowThread::addRegionToThread(RenderRegion* renderRegion) |
| 240 { | 236 { |
| 241 RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion); | 237 RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion); |
| 242 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet())
{ | 238 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet())
{ |
| 243 RenderRegionList::iterator it = m_regionList.find(nextSet); | 239 RenderRegionList::iterator it = m_regionList.find(nextSet); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 262 | 258 |
| 263 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight,
LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const | 259 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight,
LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const |
| 264 { | 260 { |
| 265 // We simply remain at our intrinsic height. | 261 // We simply remain at our intrinsic height. |
| 266 computedValues.m_extent = logicalHeight; | 262 computedValues.m_extent = logicalHeight; |
| 267 computedValues.m_position = logicalTop; | 263 computedValues.m_position = logicalTop; |
| 268 } | 264 } |
| 269 | 265 |
| 270 void RenderMultiColumnFlowThread::updateLogicalWidth() | 266 void RenderMultiColumnFlowThread::updateLogicalWidth() |
| 271 { | 267 { |
| 272 setLogicalWidth(columnWidth()); | 268 LayoutUnit columnWidth; |
| 269 calculateColumnCountAndWidth(columnWidth, m_columnCount); |
| 270 setLogicalWidth(columnWidth); |
| 273 } | 271 } |
| 274 | 272 |
| 275 void RenderMultiColumnFlowThread::layout() | 273 void RenderMultiColumnFlowThread::layout() |
| 276 { | 274 { |
| 277 RenderFlowThread::layout(); | 275 RenderFlowThread::layout(); |
| 278 if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) | 276 if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) |
| 279 lastSet->expandToEncompassFlowThreadContentsIfNeeded(); | 277 lastSet->expandToEncompassFlowThreadContentsIfNeeded(); |
| 280 } | 278 } |
| 281 | 279 |
| 282 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa
ceShortage) | 280 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa
ceShortage) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 311 if (offsetBreakAdjustment) | 309 if (offsetBreakAdjustment) |
| 312 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe
mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); | 310 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe
mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); |
| 313 return true; | 311 return true; |
| 314 } | 312 } |
| 315 return false; | 313 return false; |
| 316 } | 314 } |
| 317 | 315 |
| 318 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const | 316 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const |
| 319 { | 317 { |
| 320 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) | 318 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) |
| 321 return columnSet->computedColumnHeight(); | 319 return columnSet->pageLogicalHeight(); |
| 322 return false; | 320 return false; |
| 323 } | 321 } |
| 324 | 322 |
| 325 } | 323 } |
| OLD | NEW |