| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2012 Apple Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 24 */ | |
| 25 | |
| 26 #include "config.h" | |
| 27 #include "core/rendering/RenderMultiColumnBlock.h" | |
| 28 | |
| 29 #include "core/rendering/RenderMultiColumnFlowThread.h" | |
| 30 #include "core/rendering/RenderMultiColumnSet.h" | |
| 31 #include "core/rendering/RenderView.h" | |
| 32 | |
| 33 using namespace std; | |
| 34 | |
| 35 namespace WebCore { | |
| 36 | |
| 37 RenderMultiColumnBlock::RenderMultiColumnBlock(Element* element) | |
| 38 : RenderBlockFlow(element) | |
| 39 , m_flowThread(0) | |
| 40 , m_columnCount(1) | |
| 41 , m_columnWidth(0) | |
| 42 , m_columnHeightAvailable(0) | |
| 43 , m_inBalancingPass(false) | |
| 44 , m_needsRebalancing(false) | |
| 45 { | |
| 46 } | |
| 47 | |
| 48 void RenderMultiColumnBlock::styleDidChange(StyleDifference diff, const RenderSt
yle* oldStyle) | |
| 49 { | |
| 50 RenderBlockFlow::styleDidChange(diff, oldStyle); | |
| 51 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBo
x()) | |
| 52 child->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BL
OCK)); | |
| 53 } | |
| 54 | |
| 55 void RenderMultiColumnBlock::computeColumnCountAndWidth() | |
| 56 { | |
| 57 // Calculate our column width and column count. | |
| 58 // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibli
ng4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 | |
| 59 m_columnCount = 1; | |
| 60 m_columnWidth = contentLogicalWidth(); | |
| 61 | |
| 62 ASSERT(!style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth()); | |
| 63 | |
| 64 LayoutUnit availWidth = m_columnWidth; | |
| 65 LayoutUnit colGap = columnGap(); | |
| 66 LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()))
; | |
| 67 int colCount = max<int>(1, style()->columnCount()); | |
| 68 | |
| 69 if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) { | |
| 70 m_columnCount = colCount; | |
| 71 m_columnWidth = max<LayoutUnit>(0, (availWidth - ((m_columnCount - 1) *
colGap)) / m_columnCount); | |
| 72 } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount())
{ | |
| 73 m_columnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidth + c
olGap)); | |
| 74 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; | |
| 75 } else { | |
| 76 m_columnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWidth +
colGap) / (colWidth + colGap)), 1); | |
| 77 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 bool RenderMultiColumnBlock::updateLogicalWidthAndColumnWidth() | |
| 82 { | |
| 83 bool relayoutChildren = RenderBlockFlow::updateLogicalWidthAndColumnWidth(); | |
| 84 LayoutUnit oldColumnWidth = m_columnWidth; | |
| 85 computeColumnCountAndWidth(); | |
| 86 if (m_columnWidth != oldColumnWidth) | |
| 87 relayoutChildren = true; | |
| 88 return relayoutChildren; | |
| 89 } | |
| 90 | |
| 91 void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& /
*pageLogicalHeight*/, bool& /*pageLogicalHeightChanged*/, bool& /*hasSpecifiedPa
geLogicalHeight*/) | |
| 92 { | |
| 93 // We don't actually update any of the variables. We just subclassed to adju
st our column height. | |
| 94 updateLogicalHeight(); | |
| 95 m_columnHeightAvailable = max<LayoutUnit>(contentLogicalHeight(), 0); | |
| 96 setLogicalHeight(0); | |
| 97 } | |
| 98 | |
| 99 bool RenderMultiColumnBlock::shouldRelayoutMultiColumnBlock() | |
| 100 { | |
| 101 if (!m_needsRebalancing) | |
| 102 return false; | |
| 103 | |
| 104 // Column heights may change here because of balancing. We may have to do mu
ltiple layout | |
| 105 // passes, depending on how the contents is fitted to the changed column hei
ghts. In most | |
| 106 // cases, laying out again twice or even just once will suffice. Sometimes w
e need more | |
| 107 // passes than that, though, but the number of retries should not exceed the
number of | |
| 108 // columns, unless we have a bug. | |
| 109 bool needsRelayout = false; | |
| 110 for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->n
extSiblingBox()) { | |
| 111 if (childBox != m_flowThread && childBox->isRenderMultiColumnSet()) { | |
| 112 RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox)
; | |
| 113 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) { | |
| 114 multicolSet->setChildNeedsLayout(MarkOnlyThis); | |
| 115 needsRelayout = true; | |
| 116 } | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 if (needsRelayout) | |
| 121 m_flowThread->setChildNeedsLayout(MarkOnlyThis); | |
| 122 | |
| 123 m_inBalancingPass = needsRelayout; | |
| 124 return needsRelayout; | |
| 125 } | |
| 126 | |
| 127 void RenderMultiColumnBlock::addChild(RenderObject* newChild, RenderObject* befo
reChild) | |
| 128 { | |
| 129 if (!m_flowThread) { | |
| 130 m_flowThread = RenderMultiColumnFlowThread::createAnonymous(&document())
; | |
| 131 m_flowThread->setStyle(RenderStyle::createAnonymousStyleWithDisplay(styl
e(), BLOCK)); | |
| 132 RenderBlockFlow::addChild(m_flowThread); | |
| 133 } | |
| 134 m_flowThread->addChild(newChild, beforeChild); | |
| 135 } | |
| 136 | |
| 137 RenderObject* RenderMultiColumnBlock::layoutSpecialExcludedChild(bool relayoutCh
ildren, SubtreeLayoutScope& layoutScope) | |
| 138 { | |
| 139 if (!m_flowThread) | |
| 140 return 0; | |
| 141 | |
| 142 // Update the dimensions of our regions before we lay out the flow thread. | |
| 143 // FIXME: Eventually this is going to get way more complicated, and we will
be destroying regions | |
| 144 // instead of trying to keep them around. | |
| 145 bool shouldInvalidateRegions = false; | |
| 146 for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->n
extSiblingBox()) { | |
| 147 if (childBox == m_flowThread) | |
| 148 continue; | |
| 149 | |
| 150 if (relayoutChildren || childBox->needsLayout()) { | |
| 151 if (!m_inBalancingPass && childBox->isRenderMultiColumnSet()) | |
| 152 toRenderMultiColumnSet(childBox)->prepareForLayout(); | |
| 153 shouldInvalidateRegions = true; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 if (shouldInvalidateRegions) | |
| 158 m_flowThread->invalidateRegions(); | |
| 159 | |
| 160 if (relayoutChildren) | |
| 161 layoutScope.setChildNeedsLayout(m_flowThread); | |
| 162 | |
| 163 if (requiresBalancing()) { | |
| 164 // At the end of multicol layout, relayoutForPagination() is called unco
nditionally, but if | |
| 165 // no children are to be laid out (e.g. fixed width with layout already
being up-to-date), | |
| 166 // we want to prevent it from doing any work, so that the column balanci
ng machinery doesn't | |
| 167 // kick in and trigger additional unnecessary layout passes. Actually, i
t's not just a good | |
| 168 // idea in general to not waste time on balancing content that hasn't be
en re-laid out; we | |
| 169 // are actually required to guarantee this. The calculation of implicit
breaks needs to be | |
| 170 // preceded by a proper layout pass, since it's layout that sets up cont
ent runs, and the | |
| 171 // runs get deleted right after every pass. | |
| 172 m_needsRebalancing = shouldInvalidateRegions || m_flowThread->needsLayou
t(); | |
| 173 } | |
| 174 | |
| 175 setLogicalTopForChild(m_flowThread, borderBefore() + paddingBefore()); | |
| 176 m_flowThread->layoutIfNeeded(); | |
| 177 determineLogicalLeftPositionForChild(m_flowThread); | |
| 178 | |
| 179 return m_flowThread; | |
| 180 } | |
| 181 | |
| 182 const char* RenderMultiColumnBlock::renderName() const | |
| 183 { | |
| 184 if (isFloating()) | |
| 185 return "RenderMultiColumnBlock (floating)"; | |
| 186 if (isOutOfFlowPositioned()) | |
| 187 return "RenderMultiColumnBlock (positioned)"; | |
| 188 if (isAnonymousBlock()) | |
| 189 return "RenderMultiColumnBlock (anonymous)"; | |
| 190 // FIXME: Temporary hack while the new generated content system is being imp
lemented. | |
| 191 if (isPseudoElement()) | |
| 192 return "RenderMultiColumnBlock (generated)"; | |
| 193 if (isAnonymous()) | |
| 194 return "RenderMultiColumnBlock (generated)"; | |
| 195 if (isRelPositioned()) | |
| 196 return "RenderMultiColumnBlock (relative positioned)"; | |
| 197 return "RenderMultiColumnBlock"; | |
| 198 } | |
| 199 | |
| 200 } | |
| OLD | NEW |