<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[173311] trunk/Source/WebCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/173311">173311</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2014-09-05 07:18:06 -0700 (Fri, 05 Sep 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Move computeInlinePreferredLogicalWidths() from RenderBlock to RenderBlockFlow
https://bugs.webkit.org/show_bug.cgi?id=136461
Reviewed by Darin Adler.
This patch enables us to go from const_cast<RenderBlockFlow*>(this)->computeInlinePreferredLogicalWidths()
to computeInlinePreferredLogicalWidths().
Covered by existing tests.
* rendering/RenderBlock.cpp:
(WebCore::InlineMinMaxIterator::endOfInline): Deleted.
(WebCore::InlineMinMaxIterator::next): Deleted.
(WebCore::getBPMWidth): Deleted.
(WebCore::getBorderPaddingMargin): Deleted.
(WebCore::stripTrailingSpace): Deleted.
(WebCore::preferredWidth): Deleted.
(WebCore::RenderBlock::computeInlinePreferredLogicalWidths): Deleted.
* rendering/RenderBlock.h:
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::computeIntrinsicLogicalWidths):
(WebCore::InlineMinMaxIterator::initial): The (parent == current) condition was used as 'initial' state before.
and in order to make computeInlinePreferredLogicalWidths const, InlineMinMaxIterator() needs to take const RenderObject*.
(WebCore::InlineMinMaxIterator::next):
(WebCore::getBPMWidth):
(WebCore::getBorderPaddingMargin):
(WebCore::stripTrailingSpace):
(WebCore::preferredWidth):
(WebCore::RenderBlockFlow::computeInlinePreferredLogicalWidths):
* rendering/RenderBlockFlow.h:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockcpp">trunk/Source/WebCore/rendering/RenderBlock.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockh">trunk/Source/WebCore/rendering/RenderBlock.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockFlowcpp">trunk/Source/WebCore/rendering/RenderBlockFlow.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockFlowh">trunk/Source/WebCore/rendering/RenderBlockFlow.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173310 => 173311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-09-05 10:25:15 UTC (rev 173310)
+++ trunk/Source/WebCore/ChangeLog        2014-09-05 14:18:06 UTC (rev 173311)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2014-09-05 Zalan Bujtas <zalan@apple.com>
+
+ Move computeInlinePreferredLogicalWidths() from RenderBlock to RenderBlockFlow
+ https://bugs.webkit.org/show_bug.cgi?id=136461
+
+ Reviewed by Darin Adler.
+
+ This patch enables us to go from const_cast<RenderBlockFlow*>(this)->computeInlinePreferredLogicalWidths()
+ to computeInlinePreferredLogicalWidths().
+
+ Covered by existing tests.
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::InlineMinMaxIterator::endOfInline): Deleted.
+ (WebCore::InlineMinMaxIterator::next): Deleted.
+ (WebCore::getBPMWidth): Deleted.
+ (WebCore::getBorderPaddingMargin): Deleted.
+ (WebCore::stripTrailingSpace): Deleted.
+ (WebCore::preferredWidth): Deleted.
+ (WebCore::RenderBlock::computeInlinePreferredLogicalWidths): Deleted.
+ * rendering/RenderBlock.h:
+ * rendering/RenderBlockFlow.cpp:
+ (WebCore::RenderBlockFlow::computeIntrinsicLogicalWidths):
+ (WebCore::InlineMinMaxIterator::initial): The (parent == current) condition was used as 'initial' state before.
+ and in order to make computeInlinePreferredLogicalWidths const, InlineMinMaxIterator() needs to take const RenderObject*.
+ (WebCore::InlineMinMaxIterator::next):
+ (WebCore::getBPMWidth):
+ (WebCore::getBorderPaddingMargin):
+ (WebCore::stripTrailingSpace):
+ (WebCore::preferredWidth):
+ (WebCore::RenderBlockFlow::computeInlinePreferredLogicalWidths):
+ * rendering/RenderBlockFlow.h:
+
</ins><span class="cx"> 2014-09-04 Gyuyoung Kim <gyuyoung.kim@samsung.com>
</span><span class="cx">
</span><span class="cx"> Unreviewed, build fix for EFL and GTK ports since r173272.
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (173310 => 173311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlock.cpp        2014-09-05 10:25:15 UTC (rev 173310)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp        2014-09-05 14:18:06 UTC (rev 173311)
</span><span class="lines">@@ -2799,410 +2799,6 @@
</span><span class="cx"> setPreferredLogicalWidthsDirty(false);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-struct InlineMinMaxIterator {
-/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
- inline min/max width calculations. Note the following about the way it walks:
- (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
- (2) We do not drill into the children of floats or replaced elements, since you can't break
- in the middle of such an element.
- (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
- distinct borders/margin/padding that contribute to the min/max width.
-*/
- RenderObject* parent;
- RenderObject* current;
- bool endOfInline;
-
- InlineMinMaxIterator(RenderObject* p, bool end = false)
- :parent(p), current(p), endOfInline(end) {}
-
- RenderObject* next();
-};
-
-RenderObject* InlineMinMaxIterator::next()
-{
- RenderObject* result = 0;
- bool oldEndOfInline = endOfInline;
- endOfInline = false;
- while (current || current == parent) {
- if (!oldEndOfInline &&
- (current == parent ||
- (!current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned())))
- result = current->firstChildSlow();
- if (!result) {
- // We hit the end of our inline. (It was empty, e.g., <span></span>.)
- if (!oldEndOfInline && current->isRenderInline()) {
- result = current;
- endOfInline = true;
- break;
- }
-
- while (current && current != parent) {
- result = current->nextSibling();
- if (result) break;
- current = current->parent();
- if (current && current != parent && current->isRenderInline()) {
- result = current;
- endOfInline = true;
- break;
- }
- }
- }
-
- if (!result)
- break;
-
- if (!result->isOutOfFlowPositioned() && (result->isTextOrLineBreak() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
- break;
-
- current = result;
- result = 0;
- }
-
- // Update our position.
- current = result;
- return current;
-}
-
-static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
-{
- if (cssUnit.type() != Auto)
- return (cssUnit.isFixed() ? LayoutUnit(cssUnit.value()) : childValue);
- return 0;
-}
-
-static LayoutUnit getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
-{
- const RenderStyle& childStyle = child->style();
- if (endOfInline)
- return getBPMWidth(child->marginEnd(), childStyle.marginEnd()) +
- getBPMWidth(child->paddingEnd(), childStyle.paddingEnd()) +
- child->borderEnd();
- return getBPMWidth(child->marginStart(), childStyle.marginStart()) +
- getBPMWidth(child->paddingStart(), childStyle.paddingStart()) +
- child->borderStart();
-}
-
-static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
- RenderObject* trailingSpaceChild)
-{
- if (trailingSpaceChild && trailingSpaceChild->isText()) {
- // Collapse away the trailing space at the end of a block.
- RenderText* t = toRenderText(trailingSpaceChild);
- const UChar space = ' ';
- const Font& font = t->style().font(); // FIXME: This ignores first-line.
- float spaceWidth = font.width(RenderBlock::constructTextRun(t, font, &space, 1, t->style()));
- inlineMax -= spaceWidth + font.wordSpacing();
- if (inlineMin > inlineMax)
- inlineMin = inlineMax;
- }
-}
-
-static inline LayoutUnit preferredWidth(LayoutUnit preferredWidth, float result)
-{
- return std::max(preferredWidth, LayoutUnit::fromFloatCeil(result));
-}
-
-void RenderBlock::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth)
-{
- float inlineMax = 0;
- float inlineMin = 0;
-
- const RenderStyle& styleToUse = style();
- RenderBlock* containingBlock = this->containingBlock();
- LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
-
- // If we are at the start of a line, we want to ignore all white-space.
- // Also strip spaces if we previously had text that ended in a trailing space.
- bool stripFrontSpaces = true;
- RenderObject* trailingSpaceChild = 0;
-
- // Firefox and Opera will allow a table cell to grow to fit an image inside it under
- // very specific cirucumstances (in order to match common WinIE renderings).
- // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
- bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || !styleToUse.logicalWidth().isIntrinsicOrAuto();
-
- bool autoWrap, oldAutoWrap;
- autoWrap = oldAutoWrap = styleToUse.autoWrap();
-
- InlineMinMaxIterator childIterator(this);
-
- // Only gets added to the max preffered width once.
- bool addedTextIndent = false;
- // Signals the text indent was more negative than the min preferred width
- bool hasRemainingNegativeTextIndent = false;
-
- LayoutUnit textIndent = minimumValueForLength(styleToUse.textIndent(), cw);
- RenderObject* prevFloat = 0;
- bool isPrevChildInlineFlow = false;
- bool shouldBreakLineAfterText = false;
- while (RenderObject* child = childIterator.next()) {
- autoWrap = child->isReplaced() ? child->parent()->style().autoWrap() :
- child->style().autoWrap();
-
- if (!child->isBR()) {
- // Step One: determine whether or not we need to go ahead and
- // terminate our current line. Each discrete chunk can become
- // the new min-width, if it is the widest chunk seen so far, and
- // it can also become the max-width.
-
- // Children fall into three categories:
- // (1) An inline flow object. These objects always have a min/max of 0,
- // and are included in the iteration solely so that their margins can
- // be added in.
- //
- // (2) An inline non-text non-flow object, e.g., an inline replaced element.
- // These objects can always be on a line by themselves, so in this situation
- // we need to go ahead and break the current line, and then add in our own
- // margins and min/max width on its own line, and then terminate the line.
- //
- // (3) A text object. Text runs can have breakable characters at the start,
- // the middle or the end. They may also lose whitespace off the front if
- // we're already ignoring whitespace. In order to compute accurate min-width
- // information, we need three pieces of information.
- // (a) the min-width of the first non-breakable run. Should be 0 if the text string
- // starts with whitespace.
- // (b) the min-width of the last non-breakable run. Should be 0 if the text string
- // ends with whitespace.
- // (c) the min/max width of the string (trimmed for whitespace).
- //
- // If the text string starts with whitespace, then we need to go ahead and
- // terminate our current line (unless we're already in a whitespace stripping
- // mode.
- //
- // If the text string has a breakable character in the middle, but didn't start
- // with whitespace, then we add the width of the first non-breakable run and
- // then end the current line. We then need to use the intermediate min/max width
- // values (if any of them are larger than our current min/max). We then look at
- // the width of the last non-breakable run and use that to start a new line
- // (unless we end in whitespace).
- const RenderStyle& childStyle = child->style();
- float childMin = 0;
- float childMax = 0;
-
- if (!child->isText()) {
- if (child->isLineBreakOpportunity()) {
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- continue;
- }
- // Case (1) and (2). Inline replaced and inline flow elements.
- if (child->isRenderInline()) {
- // Add in padding/border/margin from the appropriate side of
- // the element.
- float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
- childMin += bpm;
- childMax += bpm;
-
- inlineMin += childMin;
- inlineMax += childMax;
-
- child->setPreferredLogicalWidthsDirty(false);
- } else {
- // Inline replaced elts add in their margins to their min/max values.
- LayoutUnit margins = 0;
- Length startMargin = childStyle.marginStart();
- Length endMargin = childStyle.marginEnd();
- if (startMargin.isFixed())
- margins += LayoutUnit::fromFloatCeil(startMargin.value());
- if (endMargin.isFixed())
- margins += LayoutUnit::fromFloatCeil(endMargin.value());
- childMin += margins.ceilToFloat();
- childMax += margins.ceilToFloat();
- }
- }
-
- if (!child->isRenderInline() && !child->isText()) {
- // Case (2). Inline replaced elements and floats.
- // Go ahead and terminate the current line as far as
- // minwidth is concerned.
- childMin += child->minPreferredLogicalWidth().ceilToFloat();
- childMax += child->maxPreferredLogicalWidth().ceilToFloat();
-
- bool clearPreviousFloat;
- if (child->isFloating()) {
- clearPreviousFloat = (prevFloat
- && ((prevFloat->style().floating() == LeftFloat && (childStyle.clear() & CLEFT))
- || (prevFloat->style().floating() == RightFloat && (childStyle.clear() & CRIGHT))));
- prevFloat = child;
- } else
- clearPreviousFloat = false;
-
- bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
- if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- }
-
- // If we're supposed to clear the previous float, then terminate maxwidth as well.
- if (clearPreviousFloat) {
- maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
- inlineMax = 0;
- }
-
- // Add in text-indent. This is added in only once.
- if (!addedTextIndent && !child->isFloating()) {
- LayoutUnit ceiledIndent = textIndent.ceilToFloat();
- childMin += ceiledIndent;
- childMax += ceiledIndent;
-
- if (childMin < 0)
- textIndent = LayoutUnit::fromFloatCeil(childMin);
- else
- addedTextIndent = true;
- }
-
- // Add our width to the max.
- inlineMax += std::max<float>(0, childMax);
-
- if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
- if (child->isFloating())
- minLogicalWidth = preferredWidth(minLogicalWidth, childMin);
- else
- inlineMin += childMin;
- } else {
- // Now check our line.
- minLogicalWidth = preferredWidth(minLogicalWidth, childMin);
-
- // Now start a new line.
- inlineMin = 0;
- }
-
- if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- }
-
- // We are no longer stripping whitespace at the start of
- // a line.
- if (!child->isFloating()) {
- stripFrontSpaces = false;
- trailingSpaceChild = 0;
- }
- } else if (child->isText()) {
- // Case (3). Text.
- RenderText* t = toRenderText(child);
-
- if (t->style().hasTextCombine() && t->isCombineText())
- toRenderCombineText(*t).combineText();
-
- // Determine if we have a breakable character. Pass in
- // whether or not we should ignore any spaces at the front
- // of the string. If those are going to be stripped out,
- // then they shouldn't be considered in the breakable char
- // check.
- bool hasBreakableChar, hasBreak;
- float beginMin, endMin;
- bool beginWS, endWS;
- float beginMax, endMax;
- t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
- hasBreakableChar, hasBreak, beginMax, endMax,
- childMin, childMax, stripFrontSpaces);
-
- // This text object will not be rendered, but it may still provide a breaking opportunity.
- if (!hasBreak && childMax == 0) {
- if (autoWrap && (beginWS || endWS)) {
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- }
- continue;
- }
-
- if (stripFrontSpaces)
- trailingSpaceChild = child;
- else
- trailingSpaceChild = 0;
-
- // Add in text-indent. This is added in only once.
- float ti = 0;
- if (!addedTextIndent || hasRemainingNegativeTextIndent) {
- ti = textIndent.ceilToFloat();
- childMin += ti;
- beginMin += ti;
-
- // It the text indent negative and larger than the child minimum, we re-use the remainder
- // in future minimum calculations, but using the negative value again on the maximum
- // will lead to under-counting the max pref width.
- if (!addedTextIndent) {
- childMax += ti;
- beginMax += ti;
- addedTextIndent = true;
- }
-
- if (childMin < 0) {
- textIndent = childMin;
- hasRemainingNegativeTextIndent = true;
- }
- }
-
- // If we have no breakable characters at all,
- // then this is the easy case. We add ourselves to the current
- // min and max and continue.
- if (!hasBreakableChar) {
- inlineMin += childMin;
- } else {
- // We have a breakable character. Now we need to know if
- // we start and end with whitespace.
- if (beginWS)
- // Go ahead and end the current line.
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- else {
- inlineMin += beginMin;
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- childMin -= ti;
- }
-
- inlineMin = childMin;
-
- if (endWS) {
- // We end in whitespace, which means we can go ahead
- // and end our current line.
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- shouldBreakLineAfterText = false;
- } else {
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- inlineMin = endMin;
- shouldBreakLineAfterText = true;
- }
- }
-
- if (hasBreak) {
- inlineMax += beginMax;
- maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
- maxLogicalWidth = preferredWidth(maxLogicalWidth, childMax);
- inlineMax = endMax;
- addedTextIndent = true;
- } else
- inlineMax += std::max<float>(0, childMax);
- }
-
- // Ignore spaces after a list marker.
- if (child->isListMarker())
- stripFrontSpaces = true;
- } else {
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
- inlineMin = inlineMax = 0;
- stripFrontSpaces = true;
- trailingSpaceChild = 0;
- addedTextIndent = true;
- }
-
- if (!child->isText() && child->isRenderInline())
- isPrevChildInlineFlow = true;
- else
- isPrevChildInlineFlow = false;
-
- oldAutoWrap = autoWrap;
- }
-
- if (styleToUse.collapseWhiteSpace())
- stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
-
- minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
- maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
-}
-
</del><span class="cx"> void RenderBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
</span><span class="cx"> {
</span><span class="cx"> const RenderStyle& styleToUse = style();
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlock.h (173310 => 173311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlock.h        2014-09-05 10:25:15 UTC (rev 173310)
+++ trunk/Source/WebCore/rendering/RenderBlock.h        2014-09-05 14:18:06 UTC (rev 173311)
</span><span class="lines">@@ -441,8 +441,6 @@
</span><span class="cx">
</span><span class="cx"> virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
</span><span class="cx">
</span><del>- // FIXME: Make this method const so we can remove the const_cast in computeIntrinsicLogicalWidths.
- void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
</del><span class="cx"> void computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
</span><span class="cx">
</span><span class="cx"> // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockFlowcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.cpp (173310 => 173311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlockFlow.cpp        2014-09-05 10:25:15 UTC (rev 173310)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.cpp        2014-09-05 14:18:06 UTC (rev 173311)
</span><span class="lines">@@ -32,7 +32,9 @@
</span><span class="cx"> #include "HitTestLocation.h"
</span><span class="cx"> #include "InlineTextBox.h"
</span><span class="cx"> #include "LayoutRepainter.h"
</span><ins>+#include "RenderCombineText.h"
</ins><span class="cx"> #include "RenderFlowThread.h"
</span><ins>+#include "RenderInline.h"
</ins><span class="cx"> #include "RenderIterator.h"
</span><span class="cx"> #include "RenderLayer.h"
</span><span class="cx"> #include "RenderListItem.h"
</span><span class="lines">@@ -351,10 +353,9 @@
</span><span class="cx">
</span><span class="cx"> void RenderBlockFlow::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
</span><span class="cx"> {
</span><del>- if (childrenInline()) {
- // FIXME: Remove this const_cast.
- const_cast<RenderBlockFlow*>(this)->computeInlinePreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
- } else
</del><ins>+ if (childrenInline())
+ computeInlinePreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
+ else
</ins><span class="cx"> computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
</span><span class="cx">
</span><span class="cx"> maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
</span><span class="lines">@@ -3836,5 +3837,416 @@
</span><span class="cx"> return hasLeftOverflow;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+struct InlineMinMaxIterator {
+/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
+ inline min/max width calculations. Note the following about the way it walks:
+ (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
+ (2) We do not drill into the children of floats or replaced elements, since you can't break
+ in the middle of such an element.
+ (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
+ distinct borders/margin/padding that contribute to the min/max width.
+*/
+ const RenderBlockFlow& parent;
+ RenderObject* current;
+ bool endOfInline;
+ bool initial;
+
+ InlineMinMaxIterator(const RenderBlockFlow& p)
+ : parent(p)
+ , current(nullptr)
+ , endOfInline(false)
+ , initial(true)
+ { }
+
+ RenderObject* next();
+};
+
+RenderObject* InlineMinMaxIterator::next()
+{
+ RenderObject* result = nullptr;
+ bool oldEndOfInline = endOfInline;
+ endOfInline = false;
+ do {
+ if (!oldEndOfInline && (current && !current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned()))
+ result = current->firstChildSlow();
+ else if (initial) {
+ result = parent.firstChild();
+ initial = false;
+ }
+
+ if (!result) {
+ // We hit the end of our inline. (It was empty, e.g., <span></span>.)
+ if (!oldEndOfInline && current && current->isRenderInline()) {
+ result = current;
+ endOfInline = true;
+ break;
+ }
+
+ while (current && current != &parent) {
+ result = current->nextSibling();
+ if (result)
+ break;
+ current = current->parent();
+ if (current && current != &parent && current->isRenderInline()) {
+ result = current;
+ endOfInline = true;
+ break;
+ }
+ }
+ }
+
+ if (!result)
+ break;
+
+ if (!result->isOutOfFlowPositioned() && (result->isTextOrLineBreak() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
+ break;
+
+ current = result;
+ result = nullptr;
+ } while (current || current == &parent);
+ // Update our position.
+ current = result;
+ return result;
</ins><span class="cx"> }
</span><ins>+
+static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
+{
+ if (cssUnit.type() != Auto)
+ return (cssUnit.isFixed() ? LayoutUnit(cssUnit.value()) : childValue);
+ return 0;
+}
+
+static LayoutUnit getBorderPaddingMargin(const RenderBoxModelObject& child, bool endOfInline)
+{
+ const RenderStyle& childStyle = child.style();
+ if (endOfInline) {
+ return getBPMWidth(child.marginEnd(), childStyle.marginEnd()) +
+ getBPMWidth(child.paddingEnd(), childStyle.paddingEnd()) +
+ child.borderEnd();
+ }
+ return getBPMWidth(child.marginStart(), childStyle.marginStart()) +
+ getBPMWidth(child.paddingStart(), childStyle.paddingStart()) +
+ child.borderStart();
+}
+
+static inline void stripTrailingSpace(float& inlineMax, float& inlineMin, RenderObject* trailingSpaceChild)
+{
+ if (trailingSpaceChild && trailingSpaceChild->isText()) {
+ // Collapse away the trailing space at the end of a block.
+ RenderText* t = toRenderText(trailingSpaceChild);
+ const UChar space = ' ';
+ const Font& font = t->style().font(); // FIXME: This ignores first-line.
+ float spaceWidth = font.width(RenderBlock::constructTextRun(t, font, &space, 1, t->style()));
+ inlineMax -= spaceWidth + font.wordSpacing();
+ if (inlineMin > inlineMax)
+ inlineMin = inlineMax;
+ }
+}
+
+static inline LayoutUnit preferredWidth(LayoutUnit preferredWidth, float result)
+{
+ return std::max(preferredWidth, LayoutUnit::fromFloatCeil(result));
+}
+
+void RenderBlockFlow::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+ float inlineMax = 0;
+ float inlineMin = 0;
+
+ const RenderStyle& styleToUse = style();
+ RenderBlock* containingBlock = this->containingBlock();
+ LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
+
+ // If we are at the start of a line, we want to ignore all white-space.
+ // Also strip spaces if we previously had text that ended in a trailing space.
+ bool stripFrontSpaces = true;
+ RenderObject* trailingSpaceChild = 0;
+
+ // Firefox and Opera will allow a table cell to grow to fit an image inside it under
+ // very specific cirucumstances (in order to match common WinIE renderings).
+ // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
+ bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || !styleToUse.logicalWidth().isIntrinsicOrAuto();
+
+ bool autoWrap, oldAutoWrap;
+ autoWrap = oldAutoWrap = styleToUse.autoWrap();
+
+ InlineMinMaxIterator childIterator(*this);
+
+ // Only gets added to the max preffered width once.
+ bool addedTextIndent = false;
+ // Signals the text indent was more negative than the min preferred width
+ bool hasRemainingNegativeTextIndent = false;
+
+ LayoutUnit textIndent = minimumValueForLength(styleToUse.textIndent(), cw);
+ RenderObject* prevFloat = 0;
+ bool isPrevChildInlineFlow = false;
+ bool shouldBreakLineAfterText = false;
+ while (RenderObject* child = childIterator.next()) {
+ autoWrap = child->isReplaced() ? child->parent()->style().autoWrap() :
+ child->style().autoWrap();
+
+ if (!child->isBR()) {
+ // Step One: determine whether or not we need to go ahead and
+ // terminate our current line. Each discrete chunk can become
+ // the new min-width, if it is the widest chunk seen so far, and
+ // it can also become the max-width.
+
+ // Children fall into three categories:
+ // (1) An inline flow object. These objects always have a min/max of 0,
+ // and are included in the iteration solely so that their margins can
+ // be added in.
+ //
+ // (2) An inline non-text non-flow object, e.g., an inline replaced element.
+ // These objects can always be on a line by themselves, so in this situation
+ // we need to go ahead and break the current line, and then add in our own
+ // margins and min/max width on its own line, and then terminate the line.
+ //
+ // (3) A text object. Text runs can have breakable characters at the start,
+ // the middle or the end. They may also lose whitespace off the front if
+ // we're already ignoring whitespace. In order to compute accurate min-width
+ // information, we need three pieces of information.
+ // (a) the min-width of the first non-breakable run. Should be 0 if the text string
+ // starts with whitespace.
+ // (b) the min-width of the last non-breakable run. Should be 0 if the text string
+ // ends with whitespace.
+ // (c) the min/max width of the string (trimmed for whitespace).
+ //
+ // If the text string starts with whitespace, then we need to go ahead and
+ // terminate our current line (unless we're already in a whitespace stripping
+ // mode.
+ //
+ // If the text string has a breakable character in the middle, but didn't start
+ // with whitespace, then we add the width of the first non-breakable run and
+ // then end the current line. We then need to use the intermediate min/max width
+ // values (if any of them are larger than our current min/max). We then look at
+ // the width of the last non-breakable run and use that to start a new line
+ // (unless we end in whitespace).
+ const RenderStyle& childStyle = child->style();
+ float childMin = 0;
+ float childMax = 0;
+
+ if (!child->isText()) {
+ if (child->isLineBreakOpportunity()) {
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ continue;
+ }
+ // Case (1) and (2). Inline replaced and inline flow elements.
+ if (child->isRenderInline()) {
+ // Add in padding/border/margin from the appropriate side of
+ // the element.
+ float bpm = getBorderPaddingMargin(*toRenderInline(child), childIterator.endOfInline);
+ childMin += bpm;
+ childMax += bpm;
+
+ inlineMin += childMin;
+ inlineMax += childMax;
+
+ child->setPreferredLogicalWidthsDirty(false);
+ } else {
+ // Inline replaced elts add in their margins to their min/max values.
+ LayoutUnit margins = 0;
+ Length startMargin = childStyle.marginStart();
+ Length endMargin = childStyle.marginEnd();
+ if (startMargin.isFixed())
+ margins += LayoutUnit::fromFloatCeil(startMargin.value());
+ if (endMargin.isFixed())
+ margins += LayoutUnit::fromFloatCeil(endMargin.value());
+ childMin += margins.ceilToFloat();
+ childMax += margins.ceilToFloat();
+ }
+ }
+
+ if (!child->isRenderInline() && !child->isText()) {
+ // Case (2). Inline replaced elements and floats.
+ // Go ahead and terminate the current line as far as
+ // minwidth is concerned.
+ childMin += child->minPreferredLogicalWidth().ceilToFloat();
+ childMax += child->maxPreferredLogicalWidth().ceilToFloat();
+
+ bool clearPreviousFloat;
+ if (child->isFloating()) {
+ clearPreviousFloat = (prevFloat
+ && ((prevFloat->style().floating() == LeftFloat && (childStyle.clear() & CLEFT))
+ || (prevFloat->style().floating() == RightFloat && (childStyle.clear() & CRIGHT))));
+ prevFloat = child;
+ } else
+ clearPreviousFloat = false;
+
+ bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
+ if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ }
+
+ // If we're supposed to clear the previous float, then terminate maxwidth as well.
+ if (clearPreviousFloat) {
+ maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
+ inlineMax = 0;
+ }
+
+ // Add in text-indent. This is added in only once.
+ if (!addedTextIndent && !child->isFloating()) {
+ LayoutUnit ceiledIndent = textIndent.ceilToFloat();
+ childMin += ceiledIndent;
+ childMax += ceiledIndent;
+
+ if (childMin < 0)
+ textIndent = LayoutUnit::fromFloatCeil(childMin);
+ else
+ addedTextIndent = true;
+ }
+
+ // Add our width to the max.
+ inlineMax += std::max<float>(0, childMax);
+
+ if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
+ if (child->isFloating())
+ minLogicalWidth = preferredWidth(minLogicalWidth, childMin);
+ else
+ inlineMin += childMin;
+ } else {
+ // Now check our line.
+ minLogicalWidth = preferredWidth(minLogicalWidth, childMin);
+
+ // Now start a new line.
+ inlineMin = 0;
+ }
+
+ if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ }
+
+ // We are no longer stripping whitespace at the start of a line.
+ if (!child->isFloating()) {
+ stripFrontSpaces = false;
+ trailingSpaceChild = 0;
+ }
+ } else if (child->isText()) {
+ // Case (3). Text.
+ RenderText* t = toRenderText(child);
+
+ if (t->style().hasTextCombine() && t->isCombineText())
+ toRenderCombineText(*t).combineText();
+
+ // Determine if we have a breakable character. Pass in
+ // whether or not we should ignore any spaces at the front
+ // of the string. If those are going to be stripped out,
+ // then they shouldn't be considered in the breakable char
+ // check.
+ bool hasBreakableChar, hasBreak;
+ float beginMin, endMin;
+ bool beginWS, endWS;
+ float beginMax, endMax;
+ t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
+ hasBreakableChar, hasBreak, beginMax, endMax,
+ childMin, childMax, stripFrontSpaces);
+
+ // This text object will not be rendered, but it may still provide a breaking opportunity.
+ if (!hasBreak && !childMax) {
+ if (autoWrap && (beginWS || endWS)) {
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ }
+ continue;
+ }
+
+ if (stripFrontSpaces)
+ trailingSpaceChild = child;
+ else
+ trailingSpaceChild = 0;
+
+ // Add in text-indent. This is added in only once.
+ float ti = 0;
+ if (!addedTextIndent || hasRemainingNegativeTextIndent) {
+ ti = textIndent.ceilToFloat();
+ childMin += ti;
+ beginMin += ti;
+
+ // It the text indent negative and larger than the child minimum, we re-use the remainder
+ // in future minimum calculations, but using the negative value again on the maximum
+ // will lead to under-counting the max pref width.
+ if (!addedTextIndent) {
+ childMax += ti;
+ beginMax += ti;
+ addedTextIndent = true;
+ }
+
+ if (childMin < 0) {
+ textIndent = childMin;
+ hasRemainingNegativeTextIndent = true;
+ }
+ }
+
+ // If we have no breakable characters at all,
+ // then this is the easy case. We add ourselves to the current
+ // min and max and continue.
+ if (!hasBreakableChar)
+ inlineMin += childMin;
+ else {
+ // We have a breakable character. Now we need to know if
+ // we start and end with whitespace.
+ if (beginWS) {
+ // Go ahead and end the current line.
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ } else {
+ inlineMin += beginMin;
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ childMin -= ti;
+ }
+
+ inlineMin = childMin;
+
+ if (endWS) {
+ // We end in whitespace, which means we can go ahead
+ // and end our current line.
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ shouldBreakLineAfterText = false;
+ } else {
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = endMin;
+ shouldBreakLineAfterText = true;
+ }
+ }
+
+ if (hasBreak) {
+ inlineMax += beginMax;
+ maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
+ maxLogicalWidth = preferredWidth(maxLogicalWidth, childMax);
+ inlineMax = endMax;
+ addedTextIndent = true;
+ } else
+ inlineMax += std::max<float>(0, childMax);
+ }
+
+ // Ignore spaces after a list marker.
+ if (child->isListMarker())
+ stripFrontSpaces = true;
+ } else {
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
+ inlineMin = inlineMax = 0;
+ stripFrontSpaces = true;
+ trailingSpaceChild = 0;
+ addedTextIndent = true;
+ }
+
+ if (!child->isText() && child->isRenderInline())
+ isPrevChildInlineFlow = true;
+ else
+ isPrevChildInlineFlow = false;
+
+ oldAutoWrap = autoWrap;
+ }
+
+ if (styleToUse.collapseWhiteSpace())
+ stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
+
+ minLogicalWidth = preferredWidth(minLogicalWidth, inlineMin);
+ maxLogicalWidth = preferredWidth(maxLogicalWidth, inlineMax);
+}
+
+}
</ins><span class="cx"> // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockFlowh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.h (173310 => 173311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlockFlow.h        2014-09-05 10:25:15 UTC (rev 173310)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.h        2014-09-05 14:18:06 UTC (rev 173311)
</span><span class="lines">@@ -580,6 +580,8 @@
</span><span class="cx"> bool namedFlowFragmentNeedsUpdate() const;
</span><span class="cx"> virtual bool canHaveChildren() const override;
</span><span class="cx">
</span><ins>+ void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
+
</ins><span class="cx"> #if ENABLE(IOS_TEXT_AUTOSIZING)
</span><span class="cx"> int m_widthForTextAutosizing;
</span><span class="cx"> unsigned m_lineCountForTextAutosizing : 2;
</span></span></pre>
</div>
</div>
</body>
</html>