OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * Copyright (C) 2012 Apple Inc. All rights reserved. | 3 * Copyright (C) 2012 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 * Library General Public License for more details. | 13 * Library General Public License for more details. |
14 * | 14 * |
15 * You should have received a copy of the GNU Library General Public License | 15 * You should have received a copy of the GNU Library General Public License |
16 * along with this library; see the file COPYING.LIB. If not, write to | 16 * along with this library; see the file COPYING.LIB. If not, write to |
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 * Boston, MA 02110-1301, USA. | 18 * Boston, MA 02110-1301, USA. |
19 */ | 19 */ |
20 | 20 |
21 #include "config.h" | 21 #include "config.h" |
22 | 22 |
23 #if ENABLE(TEXT_AUTOSIZING) | 23 #if ENABLE(TEXT_AUTOSIZING) |
24 | 24 |
25 #include "TextAutosizer.h" | 25 #include "TextAutosizer.h" |
26 | 26 |
27 #include "Document.h" | 27 #include "Document.h" |
28 #include "InspectorInstrumentation.h" | 28 #include "InspectorInstrumentation.h" |
| 29 #include "IntSize.h" |
29 #include "RenderObject.h" | 30 #include "RenderObject.h" |
30 #include "RenderStyle.h" | 31 #include "RenderStyle.h" |
31 #include "RenderText.h" | 32 #include "RenderText.h" |
32 #include "RenderView.h" | 33 #include "RenderView.h" |
33 #include "Settings.h" | 34 #include "Settings.h" |
34 #include "StyleInheritedData.h" | 35 #include "StyleInheritedData.h" |
35 | 36 |
36 #include <algorithm> | 37 #include <algorithm> |
37 | 38 |
38 namespace WebCore { | 39 namespace WebCore { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 if (!frame->view()->isInChildFrameWithFrameFlattening()) | 79 if (!frame->view()->isInChildFrameWithFrameFlattening()) |
79 windowInfo.minLayoutSize = windowInfo.minLayoutSize.shrunkTo(frame->
view()->layoutSize()); | 80 windowInfo.minLayoutSize = windowInfo.minLayoutSize.shrunkTo(frame->
view()->layoutSize()); |
80 } | 81 } |
81 | 82 |
82 // The layoutRoot could be neither a container nor a cluster, so walk up the
tree till we find each of these. | 83 // The layoutRoot could be neither a container nor a cluster, so walk up the
tree till we find each of these. |
83 RenderBlock* container = layoutRoot->isRenderBlock() ? toRenderBlock(layoutR
oot) : layoutRoot->containingBlock(); | 84 RenderBlock* container = layoutRoot->isRenderBlock() ? toRenderBlock(layoutR
oot) : layoutRoot->containingBlock(); |
84 while (container && !isAutosizingContainer(container)) | 85 while (container && !isAutosizingContainer(container)) |
85 container = container->containingBlock(); | 86 container = container->containingBlock(); |
86 | 87 |
87 RenderBlock* cluster = container; | 88 RenderBlock* cluster = container; |
88 while (cluster && (!isAutosizingContainer(cluster) || !isAutosizingCluster(c
luster))) | 89 while (cluster && !isAutosizingCluster(cluster)) |
89 cluster = cluster->containingBlock(); | 90 cluster = cluster->containingBlock(); |
90 | 91 |
91 processCluster(cluster, container, layoutRoot, windowInfo); | 92 processCluster(cluster, container, layoutRoot, windowInfo); |
92 return true; | 93 return true; |
93 } | 94 } |
94 | 95 |
95 void TextAutosizer::processCluster(RenderBlock* cluster, RenderBlock* container,
RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo) | 96 void TextAutosizer::processCluster(RenderBlock* cluster, RenderBlock* container,
RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo) |
96 { | 97 { |
97 ASSERT(isAutosizingCluster(cluster)); | |
98 | |
99 // Many pages set a max-width on their content. So especially for the | 98 // Many pages set a max-width on their content. So especially for the |
100 // RenderView, instead of just taking the width of |cluster| we find | 99 // RenderView, instead of just taking the width of |cluster| we find |
101 // the lowest common ancestor of the first and last descendant text node of | 100 // the lowest common ancestor of the first and last descendant text node of |
102 // the cluster (i.e. the deepest wrapper block that contains all the text), | 101 // the cluster (i.e. the deepest wrapper block that contains all the text), |
103 // and use its width instead. | 102 // and use its width instead. |
104 const RenderBlock* lowestCommonAncestor = findDeepestBlockContainingAllText(
cluster); | 103 const RenderBlock* blockContainingAllText = findDeepestBlockContainingAllTex
t(cluster); |
105 float commonAncestorWidth = lowestCommonAncestor->contentLogicalWidth(); | 104 float textWidth = blockContainingAllText->contentLogicalWidth(); |
106 | 105 |
107 float multiplier = 1; | 106 float multiplier = 1; |
108 if (clusterShouldBeAutosized(lowestCommonAncestor, commonAncestorWidth)) { | 107 if (clusterShouldBeAutosized(blockContainingAllText, textWidth)) { |
109 int logicalWindowWidth = cluster->isHorizontalWritingMode() ? windowInfo
.windowSize.width() : windowInfo.windowSize.height(); | 108 int logicalWindowWidth = cluster->isHorizontalWritingMode() ? windowInfo
.windowSize.width() : windowInfo.windowSize.height(); |
110 int logicalLayoutWidth = cluster->isHorizontalWritingMode() ? windowInfo
.minLayoutSize.width() : windowInfo.minLayoutSize.height(); | 109 int logicalLayoutWidth = cluster->isHorizontalWritingMode() ? windowInfo
.minLayoutSize.width() : windowInfo.minLayoutSize.height(); |
111 // Ignore box width in excess of the layout width, to avoid extreme mult
ipliers. | 110 // Ignore box width in excess of the layout width, to avoid extreme mult
ipliers. |
112 float logicalClusterWidth = std::min<float>(commonAncestorWidth, logical
LayoutWidth); | 111 float logicalClusterWidth = std::min<float>(textWidth, logicalLayoutWidt
h); |
113 | 112 |
114 multiplier = logicalClusterWidth / logicalWindowWidth; | 113 multiplier = logicalClusterWidth / logicalWindowWidth; |
115 multiplier *= m_document->settings()->textAutosizingFontScaleFactor(); | 114 multiplier *= m_document->settings()->textAutosizingFontScaleFactor(); |
116 multiplier = std::max(1.0f, multiplier); | 115 multiplier = std::max(1.0f, multiplier); |
117 } | 116 } |
118 | 117 |
119 processContainer(multiplier, container, subtreeRoot, windowInfo); | 118 processContainer(multiplier, container, blockContainingAllText, subtreeRoot,
windowInfo); |
120 } | 119 } |
121 | 120 |
122 void TextAutosizer::processContainer(float multiplier, RenderBlock* container, R
enderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo) | 121 void TextAutosizer::processContainer(float multiplier, RenderBlock* container, c
onst RenderBlock* blockContainingAllText, RenderObject* subtreeRoot, const TextA
utosizingWindowInfo& windowInfo) |
123 { | 122 { |
124 ASSERT(isAutosizingContainer(container)); | 123 ASSERT(isAutosizingContainer(container)); |
125 | 124 |
126 float localMultiplier = containerShouldbeAutosized(container) ? multiplier:
1; | 125 float localMultiplier = containerShouldBeAutosized(container) ? multiplier:
1; |
127 | 126 |
128 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(sub
treeRoot, subtreeRoot); | 127 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(sub
treeRoot, subtreeRoot); |
129 while (descendant) { | 128 while (descendant) { |
130 if (descendant->isText()) { | 129 if (descendant->isText()) { |
131 if (localMultiplier != descendant->style()->textAutosizingMultiplier
()) { | 130 if (localMultiplier != descendant->style()->textAutosizingMultiplier
()) { |
132 setMultiplier(descendant, localMultiplier); | 131 setMultiplier(descendant, localMultiplier); |
133 setMultiplier(descendant->parent(), localMultiplier); // Parent
does line spacing. | 132 setMultiplier(descendant->parent(), localMultiplier); // Parent
does line spacing. |
134 } | 133 } |
135 // FIXME: Increase list marker size proportionately. | 134 // FIXME: Increase list marker size proportionately. |
136 } else if (isAutosizingContainer(descendant)) { | 135 } else if (isAutosizingContainer(descendant)) { |
137 RenderBlock* descendantBlock = toRenderBlock(descendant); | 136 RenderBlock* descendantBlock = toRenderBlock(descendant); |
138 if (isAutosizingCluster(descendantBlock)) | 137 if (isAutosizingCluster(descendantBlock, blockContainingAllText)) |
139 processCluster(descendantBlock, descendantBlock, descendantBlock
, windowInfo); | 138 processCluster(descendantBlock, descendantBlock, descendantBlock
, windowInfo); |
140 else | 139 else |
141 processContainer(multiplier, descendantBlock, descendantBlock, w
indowInfo); | 140 processContainer(multiplier, descendantBlock, blockContainingAll
Text, descendantBlock, windowInfo); |
142 } | 141 } |
143 descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, s
ubtreeRoot); | 142 descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, s
ubtreeRoot); |
144 } | 143 } |
145 } | 144 } |
146 | 145 |
147 void TextAutosizer::setMultiplier(RenderObject* renderer, float multiplier) | 146 void TextAutosizer::setMultiplier(RenderObject* renderer, float multiplier) |
148 { | 147 { |
149 RefPtr<RenderStyle> newStyle = RenderStyle::clone(renderer->style()); | 148 RefPtr<RenderStyle> newStyle = RenderStyle::clone(renderer->style()); |
150 newStyle->setTextAutosizingMultiplier(multiplier); | 149 newStyle->setTextAutosizingMultiplier(multiplier); |
151 renderer->setStyle(newStyle.release()); | 150 renderer->setStyle(newStyle.release()); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 // - Must not be list items, as items in the same list should look consisten
t (*). | 188 // - Must not be list items, as items in the same list should look consisten
t (*). |
190 // - Must not be normal list items, as items in the same list should look | 189 // - Must not be normal list items, as items in the same list should look |
191 // consistent, unless they are floating or position:absolute/fixed. | 190 // consistent, unless they are floating or position:absolute/fixed. |
192 if (!renderer->isRenderBlock() || (renderer->isInline() && !renderer->style(
)->isDisplayReplacedType())) | 191 if (!renderer->isRenderBlock() || (renderer->isInline() && !renderer->style(
)->isDisplayReplacedType())) |
193 return false; | 192 return false; |
194 if (renderer->isListItem()) | 193 if (renderer->isListItem()) |
195 return renderer->isFloating() || renderer->isOutOfFlowPositioned(); | 194 return renderer->isFloating() || renderer->isOutOfFlowPositioned(); |
196 return true; | 195 return true; |
197 } | 196 } |
198 | 197 |
199 bool TextAutosizer::isAutosizingCluster(const RenderBlock* renderer) | 198 bool TextAutosizer::isAutosizingCluster(const RenderBlock* renderer, const Rende
rBlock* parentBlockContainingAllText) |
200 { | 199 { |
201 // "Autosizing clusters" are special autosizing containers within which we | 200 // "Autosizing clusters" are special autosizing containers within which we |
202 // want to enforce a uniform text size multiplier, in the hopes of making | 201 // want to enforce a uniform text size multiplier, in the hopes of making |
203 // the major sections of the page look internally consistent. | 202 // the major sections of the page look internally consistent. |
204 // All their descendents (including other autosizing containers) must share | 203 // All their descendants (including other autosizing containers) must share |
205 // the same multiplier, except for subtrees which are themselves clusters, | 204 // the same multiplier, except for subtrees which are themselves clusters, |
206 // and some of their descendent containers might not be autosized at all | 205 // and some of their descendant containers might not be autosized at all |
207 // (for example if their height is constrained). | 206 // (for example if their height is constrained). |
208 // Additionally, clusterShouldBeAutosized requires each cluster to contain a | 207 // Additionally, clusterShouldBeAutosized requires each cluster to contain a |
209 // minimum amount of text, without which it won't be autosized. | 208 // minimum amount of text, without which it won't be autosized. |
210 // | 209 // |
211 // Clusters are chosen using very similar criteria to CSS flow roots, aka | 210 // Clusters are chosen using very similar criteria to CSS flow roots, aka |
212 // block formatting contexts (http://w3.org/TR/css3-box/#flow-root), since | 211 // block formatting contexts (http://w3.org/TR/css3-box/#flow-root), since |
213 // flow roots correspond to box containers that behave somewhat | 212 // flow roots correspond to box containers that behave somewhat |
214 // independently from their parent (for example they don't overlap floats). | 213 // independently from their parent (for example they don't overlap floats). |
215 // The definition of a flow flow root also conveniently includes most of the | 214 // The definition of a flow root also conveniently includes most of the |
216 // ways that a box and its children can have significantly different width | 215 // ways that a box and its children can have significantly different width |
217 // from the box's parent (we want to avoid having significantly different | 216 // from the box's parent (we want to avoid having significantly different |
218 // width blocks within a cluster, since the narrower blocks would end up | 217 // width blocks within a cluster, since the narrower blocks would end up |
219 // larger than would otherwise be necessary). | 218 // larger than would otherwise be necessary). |
| 219 // Additionally, any containers that are wider than the |blockContainingAllT
ext| |
| 220 // of their enclosing cluster also become clusters, since they need special |
| 221 // treatment due to their width. |
220 ASSERT(isAutosizingContainer(renderer)); | 222 ASSERT(isAutosizingContainer(renderer)); |
221 | 223 |
222 return renderer->isRenderView() | 224 return renderer->isRenderView() |
223 || renderer->isFloating() | 225 || renderer->isFloating() |
224 || renderer->isOutOfFlowPositioned() | 226 || renderer->isOutOfFlowPositioned() |
225 || renderer->isTableCell() | 227 || renderer->isTableCell() |
226 || renderer->isTableCaption() | 228 || renderer->isTableCaption() |
227 || renderer->isFlexibleBoxIncludingDeprecated() | 229 || renderer->isFlexibleBoxIncludingDeprecated() |
228 || renderer->hasColumns() | 230 || renderer->hasColumns() |
229 || renderer->containingBlock()->isHorizontalWritingMode() != renderer->i
sHorizontalWritingMode() | 231 || renderer->containingBlock()->isHorizontalWritingMode() != renderer->i
sHorizontalWritingMode() |
230 || renderer->style()->isDisplayReplacedType(); | 232 || renderer->style()->isDisplayReplacedType() |
| 233 || (parentBlockContainingAllText |
| 234 && renderer->contentLogicalWidth() > parentBlockContainingAllText->c
ontentLogicalWidth()); |
231 // FIXME: Tables need special handling to multiply all their columns by | 235 // FIXME: Tables need special handling to multiply all their columns by |
232 // the same amount even if they're different widths; so do hasColumns() | 236 // the same amount even if they're different widths; so do hasColumns() |
233 // containers, and probably flexboxes... | 237 // containers, and probably flexboxes... |
234 } | 238 } |
235 | 239 |
| 240 bool TextAutosizer::isAutosizingCluster(const RenderObject* object) |
| 241 { |
| 242 return isAutosizingContainer(object) && isAutosizingCluster(toRenderBlock(ob
ject), 0); |
| 243 } |
| 244 |
236 static bool contentHeightIsConstrained(const RenderBlock* container) | 245 static bool contentHeightIsConstrained(const RenderBlock* container) |
237 { | 246 { |
238 // FIXME: Propagate constrainedness down the tree, to avoid inefficiently wa
lking back up from each box. | 247 // FIXME: Propagate constrainedness down the tree, to avoid inefficiently wa
lking back up from each box. |
239 // FIXME: This code needs to take into account vertical writing modes. | 248 // FIXME: This code needs to take into account vertical writing modes. |
240 // FIXME: Consider additional heuristics, such as ignoring fixed heights if
the content is already overflowing before autosizing kicks in. | 249 // FIXME: Consider additional heuristics, such as ignoring fixed heights if
the content is already overflowing before autosizing kicks in. |
241 for (; container; container = container->containingBlock()) { | 250 for (; container; container = container->containingBlock()) { |
242 RenderStyle* style = container->style(); | 251 RenderStyle* style = container->style(); |
243 if (style->overflowY() >= OSCROLL) | 252 if (style->overflowY() >= OSCROLL) |
244 return false; | 253 return false; |
245 if (style->height().isSpecified() || style->maxHeight().isSpecified()) { | 254 if (style->height().isSpecified() || style->maxHeight().isSpecified()) { |
246 // Some sites (e.g. wikipedia) set their html and/or body elements t
o height:100%, | 255 // Some sites (e.g. wikipedia) set their html and/or body elements t
o height:100%, |
247 // without intending to constrain the height of the content within t
hem. | 256 // without intending to constrain the height of the content within t
hem. |
248 return !container->isRoot() && !container->isBody(); | 257 return !container->isRoot() && !container->isBody(); |
249 } | 258 } |
250 if (container->isFloatingOrOutOfFlowPositioned()) | 259 if (container->isFloatingOrOutOfFlowPositioned()) |
251 return false; | 260 return false; |
252 } | 261 } |
253 return false; | 262 return false; |
254 } | 263 } |
255 | 264 |
256 bool TextAutosizer::containerShouldbeAutosized(const RenderBlock* container) | 265 bool TextAutosizer::containerShouldBeAutosized(const RenderBlock* container) |
257 { | 266 { |
258 // Don't autosize block-level text that can't wrap (as it's likely to | 267 // Don't autosize block-level text that can't wrap (as it's likely to |
259 // expand sideways and break the page's layout). | 268 // expand sideways and break the page's layout). |
260 if (!container->style()->autoWrap()) | 269 if (!container->style()->autoWrap()) |
261 return false; | 270 return false; |
262 | 271 |
263 return !contentHeightIsConstrained(container); | 272 return !contentHeightIsConstrained(container); |
264 } | 273 } |
265 | 274 |
266 bool TextAutosizer::clusterShouldBeAutosized(const RenderBlock* lowestCommonAnce
stor, float commonAncestorWidth) | 275 bool TextAutosizer::clusterShouldBeAutosized(const RenderBlock* blockContainingA
llText, float blockWidth) |
267 { | 276 { |
268 // Don't autosize clusters that contain less than 4 lines of text (in | 277 // Don't autosize clusters that contain less than 4 lines of text (in |
269 // practice less lines are required, since measureDescendantTextWidth | 278 // practice less lines are required, since measureDescendantTextWidth |
270 // assumes that characters are 1em wide, but most characters are narrower | 279 // assumes that characters are 1em wide, but most characters are narrower |
271 // than that, so we're overestimating their contribution to the linecount). | 280 // than that, so we're overestimating their contribution to the linecount). |
272 // | 281 // |
273 // This is to reduce the likelihood of autosizing things like headers and | 282 // This is to reduce the likelihood of autosizing things like headers and |
274 // footers, which can be quite visually distracting. The rationale is that | 283 // footers, which can be quite visually distracting. The rationale is that |
275 // if a cluster contains very few lines of text then it's ok to have to zoom | 284 // if a cluster contains very few lines of text then it's ok to have to zoom |
276 // in and pan from side to side to read each line, since if there are very | 285 // in and pan from side to side to read each line, since if there are very |
277 // few lines of text you'll only need to pan across once or twice. | 286 // few lines of text you'll only need to pan across once or twice. |
278 const float minLinesOfText = 4; | 287 const float minLinesOfText = 4; |
279 float minTextWidth = commonAncestorWidth * minLinesOfText; | 288 float minTextWidth = blockWidth * minLinesOfText; |
280 float textWidth = 0; | 289 float textWidth = 0; |
281 measureDescendantTextWidth(lowestCommonAncestor, minTextWidth, textWidth); | 290 measureDescendantTextWidth(blockContainingAllText, blockContainingAllText, m
inTextWidth, textWidth); |
282 if (textWidth >= minTextWidth) | 291 if (textWidth >= minTextWidth) |
283 return true; | 292 return true; |
284 return false; | 293 return false; |
285 } | 294 } |
286 | 295 |
287 void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, flo
at minTextWidth, float& textWidth) | 296 void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, con
st RenderBlock* blockContainingAllText, float minTextWidth, float& textWidth) |
288 { | 297 { |
289 bool skipLocalText = !containerShouldbeAutosized(container); | 298 bool skipLocalText = !containerShouldBeAutosized(container); |
290 | 299 |
291 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(con
tainer, container); | 300 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(con
tainer, container); |
292 while (descendant) { | 301 while (descendant) { |
293 if (!skipLocalText && descendant->isText()) { | 302 if (!skipLocalText && descendant->isText()) { |
294 textWidth += toRenderText(descendant)->renderedTextLength() * descen
dant->style()->specifiedFontSize(); | 303 textWidth += toRenderText(descendant)->renderedTextLength() * descen
dant->style()->specifiedFontSize(); |
295 } else if (isAutosizingContainer(descendant)) { | 304 } else if (isAutosizingContainer(descendant)) { |
296 RenderBlock* descendantBlock = toRenderBlock(descendant); | 305 RenderBlock* descendantBlock = toRenderBlock(descendant); |
297 if (!isAutosizingCluster(descendantBlock)) | 306 if (!isAutosizingCluster(descendantBlock, blockContainingAllText)) |
298 measureDescendantTextWidth(descendantBlock, minTextWidth, textWi
dth); | 307 measureDescendantTextWidth(descendantBlock, blockContainingAllTe
xt, minTextWidth, textWidth); |
299 } | 308 } |
300 if (textWidth >= minTextWidth) | 309 if (textWidth >= minTextWidth) |
301 return; | 310 return; |
302 descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, c
ontainer); | 311 descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, c
ontainer); |
303 } | 312 } |
304 } | 313 } |
305 | 314 |
306 RenderObject* TextAutosizer::nextInPreOrderSkippingDescendantsOfContainers(const
RenderObject* current, const RenderObject* stayWithin) | 315 RenderObject* TextAutosizer::nextInPreOrderSkippingDescendantsOfContainers(const
RenderObject* current, const RenderObject* stayWithin) |
307 { | 316 { |
308 if (current == stayWithin || !isAutosizingContainer(current)) | 317 if (current == stayWithin || !isAutosizingContainer(current)) |
309 for (RenderObject* child = current->firstChild(); child; child = child->
nextSibling()) | 318 for (RenderObject* child = current->firstChild(); child; child = child->
nextSibling()) |
310 return child; | 319 return child; |
311 | 320 |
312 for (const RenderObject* ancestor = current; ancestor; ancestor = ancestor->
parent()) { | 321 for (const RenderObject* ancestor = current; ancestor; ancestor = ancestor->
parent()) { |
313 if (ancestor == stayWithin) | 322 if (ancestor == stayWithin) |
314 return 0; | 323 return 0; |
315 for (RenderObject* sibling = ancestor->nextSibling(); sibling; sibling =
sibling->nextSibling()) | 324 for (RenderObject* sibling = ancestor->nextSibling(); sibling; sibling =
sibling->nextSibling()) |
316 return sibling; | 325 return sibling; |
317 } | 326 } |
318 | 327 |
319 return 0; | 328 return 0; |
320 } | 329 } |
321 | 330 |
322 const RenderBlock* TextAutosizer::findDeepestBlockContainingAllText(const Render
Block* cluster) | 331 const RenderBlock* TextAutosizer::findDeepestBlockContainingAllText(const Render
Block* cluster) |
323 { | 332 { |
324 ASSERT(isAutosizingCluster(cluster)); | |
325 | |
326 size_t firstDepth = 0; | 333 size_t firstDepth = 0; |
327 const RenderObject* firstTextLeaf = findFirstTextLeafNotInCluster(cluster, f
irstDepth, FirstToLast); | 334 const RenderObject* firstTextLeaf = findFirstTextLeafNotInCluster(cluster, f
irstDepth, FirstToLast); |
328 if (!firstTextLeaf) | 335 if (!firstTextLeaf) |
329 return cluster; | 336 return cluster; |
330 | 337 |
331 size_t lastDepth = 0; | 338 size_t lastDepth = 0; |
332 const RenderObject* lastTextLeaf = findFirstTextLeafNotInCluster(cluster, la
stDepth, LastToFirst); | 339 const RenderObject* lastTextLeaf = findFirstTextLeafNotInCluster(cluster, la
stDepth, LastToFirst); |
333 ASSERT(lastTextLeaf); | 340 ASSERT(lastTextLeaf); |
334 | 341 |
335 // Equalize the depths if necessary. Only one of the while loops below will
get executed. | 342 // Equalize the depths if necessary. Only one of the while loops below will
get executed. |
(...skipping 28 matching lines...) Expand all Loading... |
364 } | 371 } |
365 | 372 |
366 const RenderObject* TextAutosizer::findFirstTextLeafNotInCluster(const RenderObj
ect* parent, size_t& depth, TraversalDirection direction) | 373 const RenderObject* TextAutosizer::findFirstTextLeafNotInCluster(const RenderObj
ect* parent, size_t& depth, TraversalDirection direction) |
367 { | 374 { |
368 if (parent->isEmpty()) | 375 if (parent->isEmpty()) |
369 return parent->isText() ? parent : 0; | 376 return parent->isText() ? parent : 0; |
370 | 377 |
371 ++depth; | 378 ++depth; |
372 const RenderObject* child = (direction == FirstToLast) ? parent->firstChild(
) : parent->lastChild(); | 379 const RenderObject* child = (direction == FirstToLast) ? parent->firstChild(
) : parent->lastChild(); |
373 while (child) { | 380 while (child) { |
374 if (!isAutosizingContainer(child) || !isAutosizingCluster(toRenderBlock(
child))) { | 381 if (!isAutosizingCluster(child)) { |
375 const RenderObject* leaf = findFirstTextLeafNotInCluster(child, dept
h, direction); | 382 const RenderObject* leaf = findFirstTextLeafNotInCluster(child, dept
h, direction); |
376 if (leaf) | 383 if (leaf) |
377 return leaf; | 384 return leaf; |
378 } | 385 } |
379 child = (direction == FirstToLast) ? child->nextSibling() : child->previ
ousSibling(); | 386 child = (direction == FirstToLast) ? child->nextSibling() : child->previ
ousSibling(); |
380 } | 387 } |
381 --depth; | 388 --depth; |
382 | 389 |
383 return 0; | 390 return 0; |
384 } | 391 } |
385 | 392 |
386 } // namespace WebCore | 393 } // namespace WebCore |
387 | 394 |
388 #endif // ENABLE(TEXT_AUTOSIZING) | 395 #endif // ENABLE(TEXT_AUTOSIZING) |
OLD | NEW |