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 |