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, |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 | 126 |
127 RenderBlock* cluster = container; | 127 RenderBlock* cluster = container; |
128 while (cluster && (!isAutosizingContainer(cluster) || !isIndependentDescenda
nt(cluster))) | 128 while (cluster && (!isAutosizingContainer(cluster) || !isIndependentDescenda
nt(cluster))) |
129 cluster = cluster->containingBlock(); | 129 cluster = cluster->containingBlock(); |
130 | 130 |
131 TextAutosizingClusterInfo clusterInfo(cluster); | 131 TextAutosizingClusterInfo clusterInfo(cluster); |
132 processCluster(clusterInfo, container, layoutRoot, windowInfo); | 132 processCluster(clusterInfo, container, layoutRoot, windowInfo); |
133 return true; | 133 return true; |
134 } | 134 } |
135 | 135 |
136 void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, Rende
rBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& wi
ndowInfo) | 136 void TextAutosizer::processClusterInternal(TextAutosizingClusterInfo& clusterInf
o, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindow
Info& windowInfo, float textWidth, bool shouldBeAutosized) |
137 { | 137 { |
138 // Many pages set a max-width on their content. So especially for the | |
139 // RenderView, instead of just taking the width of |cluster| we find | |
140 // the lowest common ancestor of the first and last descendant text node of | |
141 // the cluster (i.e. the deepest wrapper block that contains all the text), | |
142 // and use its width instead. | |
143 clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clust
erInfo.root); | |
144 float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth(); | |
145 | |
146 float multiplier = 1; | 138 float multiplier = 1; |
147 if (clusterShouldBeAutosized(clusterInfo, textWidth)) { | 139 if (shouldBeAutosized) { |
148 int logicalWindowWidth = clusterInfo.root->isHorizontalWritingMode() ? w
indowInfo.windowSize.width() : windowInfo.windowSize.height(); | 140 int logicalWindowWidth = clusterInfo.root->isHorizontalWritingMode() ? w
indowInfo.windowSize.width() : windowInfo.windowSize.height(); |
149 int logicalLayoutWidth = clusterInfo.root->isHorizontalWritingMode() ? w
indowInfo.minLayoutSize.width() : windowInfo.minLayoutSize.height(); | 141 int logicalLayoutWidth = clusterInfo.root->isHorizontalWritingMode() ? w
indowInfo.minLayoutSize.width() : windowInfo.minLayoutSize.height(); |
150 // Ignore box width in excess of the layout width, to avoid extreme mult
ipliers. | 142 // Ignore box width in excess of the layout width, to avoid extreme mult
ipliers. |
151 float logicalClusterWidth = std::min<float>(textWidth, logicalLayoutWidt
h); | 143 float logicalClusterWidth = std::min<float>(textWidth, logicalLayoutWidt
h); |
152 | 144 |
153 multiplier = logicalClusterWidth / logicalWindowWidth; | 145 multiplier = logicalClusterWidth / logicalWindowWidth; |
154 multiplier *= m_document->settings()->textAutosizingFontScaleFactor(); | 146 multiplier *= m_document->settings()->textAutosizingFontScaleFactor(); |
155 multiplier = std::max(1.0f, multiplier); | 147 multiplier = std::max(1.0f, multiplier); |
156 } | 148 } |
157 | 149 |
158 processContainer(multiplier, container, clusterInfo, subtreeRoot, windowInfo
); | 150 processContainer(multiplier, container, clusterInfo, subtreeRoot, windowInfo
); |
159 | 151 |
160 Vector<TextAutosizingClusterInfo>& narrowDescendants = clusterInfo.narrowDes
cendants; | 152 processCompositeCluster(clusterInfo.narrowDescendants, windowInfo); |
161 for (size_t i = 0; i < narrowDescendants.size(); ++i) { | 153 } |
162 TextAutosizingClusterInfo& descendantClusterInfo = narrowDescendants[i]; | 154 |
163 processCluster(descendantClusterInfo, descendantClusterInfo.root, descen
dantClusterInfo.root, windowInfo); | 155 void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, Rende
rBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& wi
ndowInfo) |
| 156 { |
| 157 // Many pages set a max-width on their content. So especially for the Render
View, instead of |
| 158 // just taking the width of |cluster| we find the lowest common ancestor of
the first and last |
| 159 // descendant text node of the cluster (i.e. the deepest wrapper block that
contains all the |
| 160 // text), and use its width instead. |
| 161 clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clust
erInfo.root); |
| 162 float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth(); |
| 163 processClusterInternal(clusterInfo, container, subtreeRoot, windowInfo, text
Width, clusterShouldBeAutosized(clusterInfo, textWidth)); |
| 164 } |
| 165 |
| 166 void TextAutosizer::processCompositeCluster(Vector<TextAutosizingClusterInfo>& c
lusterInfos, const TextAutosizingWindowInfo& windowInfo) |
| 167 { |
| 168 float maxTextWidth = 0; |
| 169 for (size_t i = 0; i < clusterInfos.size(); ++i) { |
| 170 TextAutosizingClusterInfo& clusterInfo = clusterInfos[i]; |
| 171 clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(c
lusterInfo.root); |
| 172 maxTextWidth = max<float>(maxTextWidth, clusterInfo.blockContainingAllTe
xt->contentLogicalWidth()); |
164 } | 173 } |
| 174 |
| 175 bool shouldBeAutosized = compositeClusterShouldBeAutosized(clusterInfos, max
TextWidth); |
| 176 for (size_t i = 0; i < clusterInfos.size(); ++i) |
| 177 processClusterInternal(clusterInfos[i], clusterInfos[i].root, clusterInf
os[i].root, windowInfo, maxTextWidth, shouldBeAutosized); |
165 } | 178 } |
166 | 179 |
167 void TextAutosizer::processContainer(float multiplier, RenderBlock* container, T
extAutosizingClusterInfo& clusterInfo, RenderObject* subtreeRoot, const TextAuto
sizingWindowInfo& windowInfo) | 180 void TextAutosizer::processContainer(float multiplier, RenderBlock* container, T
extAutosizingClusterInfo& clusterInfo, RenderObject* subtreeRoot, const TextAuto
sizingWindowInfo& windowInfo) |
168 { | 181 { |
169 ASSERT(isAutosizingContainer(container)); | 182 ASSERT(isAutosizingContainer(container)); |
170 | 183 |
171 float localMultiplier = containerShouldBeAutosized(container) ? multiplier:
1; | 184 float localMultiplier = containerShouldBeAutosized(container) ? multiplier:
1; |
172 | 185 |
173 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(sub
treeRoot, subtreeRoot); | 186 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(sub
treeRoot, subtreeRoot); |
174 while (descendant) { | 187 while (descendant) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 return !container->isRoot() && !container->isBody(); | 434 return !container->isRoot() && !container->isBody(); |
422 } | 435 } |
423 if (container->isFloatingOrOutOfFlowPositioned()) | 436 if (container->isFloatingOrOutOfFlowPositioned()) |
424 return false; | 437 return false; |
425 } | 438 } |
426 return false; | 439 return false; |
427 } | 440 } |
428 | 441 |
429 bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterI
nfo, float blockWidth) | 442 bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterI
nfo, float blockWidth) |
430 { | 443 { |
| 444 Vector<TextAutosizingClusterInfo> clusterInfos(1, clusterInfo); |
| 445 return compositeClusterShouldBeAutosized(clusterInfos, blockWidth); |
| 446 } |
| 447 |
| 448 bool TextAutosizer::compositeClusterShouldBeAutosized(Vector<TextAutosizingClust
erInfo>& clusterInfos, float blockWidth) |
| 449 { |
431 // Don't autosize clusters that contain less than 4 lines of text (in | 450 // Don't autosize clusters that contain less than 4 lines of text (in |
432 // practice less lines are required, since measureDescendantTextWidth | 451 // practice less lines are required, since measureDescendantTextWidth |
433 // assumes that characters are 1em wide, but most characters are narrower | 452 // assumes that characters are 1em wide, but most characters are narrower |
434 // than that, so we're overestimating their contribution to the linecount). | 453 // than that, so we're overestimating their contribution to the linecount). |
435 // | 454 // |
436 // This is to reduce the likelihood of autosizing things like headers and | 455 // This is to reduce the likelihood of autosizing things like headers and |
437 // footers, which can be quite visually distracting. The rationale is that | 456 // footers, which can be quite visually distracting. The rationale is that |
438 // if a cluster contains very few lines of text then it's ok to have to zoom | 457 // if a cluster contains very few lines of text then it's ok to have to zoom |
439 // in and pan from side to side to read each line, since if there are very | 458 // in and pan from side to side to read each line, since if there are very |
440 // few lines of text you'll only need to pan across once or twice. | 459 // few lines of text you'll only need to pan across once or twice. |
| 460 float totalTextWidth = 0; |
441 const float minLinesOfText = 4; | 461 const float minLinesOfText = 4; |
442 float minTextWidth = blockWidth * minLinesOfText; | 462 float minTextWidth = blockWidth * minLinesOfText; |
443 float textWidth = 0; | 463 for (size_t i = 0; i < clusterInfos.size(); ++i) { |
444 measureDescendantTextWidth(clusterInfo.blockContainingAllText, clusterInfo,
minTextWidth, textWidth); | 464 measureDescendantTextWidth(clusterInfos[i].blockContainingAllText, clust
erInfos[i], minTextWidth, totalTextWidth); |
445 if (textWidth >= minTextWidth) | 465 if (totalTextWidth >= minTextWidth) |
446 return true; | 466 return true; |
| 467 } |
447 return false; | 468 return false; |
448 } | 469 } |
449 | 470 |
450 void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, Tex
tAutosizingClusterInfo& clusterInfo, float minTextWidth, float& textWidth) | 471 void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, Tex
tAutosizingClusterInfo& clusterInfo, float minTextWidth, float& textWidth) |
451 { | 472 { |
452 bool skipLocalText = !containerShouldBeAutosized(container); | 473 bool skipLocalText = !containerShouldBeAutosized(container); |
453 | 474 |
454 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(con
tainer, container); | 475 RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(con
tainer, container); |
455 while (descendant) { | 476 while (descendant) { |
456 if (!skipLocalText && descendant->isText()) { | 477 if (!skipLocalText && descendant->isText()) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 child = (direction == FirstToLast) ? child->nextSibling() : child->previ
ousSibling(); | 552 child = (direction == FirstToLast) ? child->nextSibling() : child->previ
ousSibling(); |
532 } | 553 } |
533 --depth; | 554 --depth; |
534 | 555 |
535 return 0; | 556 return 0; |
536 } | 557 } |
537 | 558 |
538 } // namespace WebCore | 559 } // namespace WebCore |
539 | 560 |
540 #endif // ENABLE(TEXT_AUTOSIZING) | 561 #endif // ENABLE(TEXT_AUTOSIZING) |
OLD | NEW |