OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "core/frame/FrameView.h" | 35 #include "core/frame/FrameView.h" |
36 #include "core/frame/LocalFrame.h" | 36 #include "core/frame/LocalFrame.h" |
37 #include "core/frame/Settings.h" | 37 #include "core/frame/Settings.h" |
38 #include "core/page/Page.h" | 38 #include "core/page/Page.h" |
39 #include "core/rendering/InlineIterator.h" | 39 #include "core/rendering/InlineIterator.h" |
40 #include "core/rendering/RenderBlock.h" | 40 #include "core/rendering/RenderBlock.h" |
41 #include "core/rendering/RenderListItem.h" | 41 #include "core/rendering/RenderListItem.h" |
42 #include "core/rendering/RenderListMarker.h" | 42 #include "core/rendering/RenderListMarker.h" |
43 #include "core/rendering/RenderTableCell.h" | 43 #include "core/rendering/RenderTableCell.h" |
44 #include "core/rendering/RenderView.h" | 44 #include "core/rendering/RenderView.h" |
45 #include "core/rendering/TextAutosizer.h" | |
46 | 45 |
47 using namespace std; | 46 using namespace std; |
48 | 47 |
49 namespace WebCore { | 48 namespace WebCore { |
50 | 49 |
51 static const RenderObject* parentElementRenderer(const RenderObject* renderer) | 50 static const RenderObject* parentElementRenderer(const RenderObject* renderer) |
52 { | 51 { |
53 // At style recalc, the renderer's parent may not be attached, | 52 // At style recalc, the renderer's parent may not be attached, |
54 // so we need to obtain this from the DOM tree. | 53 // so we need to obtain this from the DOM tree. |
55 | 54 |
56 const Node* node = renderer->node(); | 55 const Node* node = renderer->node(); |
57 if (!node) | 56 if (!node) |
58 return 0; | 57 return 0; |
59 | 58 |
60 while ((node = node->parentNode())) { | 59 while ((node = node->parentNode())) { |
61 if (node->isElementNode()) | 60 if (node->isElementNode()) |
62 return node->renderer(); | 61 return node->renderer(); |
63 } | 62 } |
64 return 0; | 63 return 0; |
65 } | 64 } |
66 | 65 |
| 66 static const Vector<QualifiedName>& formInputTags() |
| 67 { |
| 68 // Returns the tags for the form input elements. |
| 69 DEFINE_STATIC_LOCAL(Vector<QualifiedName>, formInputTags, ()); |
| 70 if (formInputTags.isEmpty()) { |
| 71 formInputTags.append(HTMLNames::inputTag); |
| 72 formInputTags.append(HTMLNames::buttonTag); |
| 73 formInputTags.append(HTMLNames::selectTag); |
| 74 } |
| 75 return formInputTags; |
| 76 } |
| 77 |
| 78 static bool isAutosizingContainer(const RenderObject* renderer) |
| 79 { |
| 80 // "Autosizing containers" are the smallest unit for which we can |
| 81 // enable/disable Text Autosizing. |
| 82 // - Must not be inline, as different multipliers on one line looks terrible
. |
| 83 // Exceptions are inline-block and alike elements (inline-table, -webkit-i
nline-*), |
| 84 // as they often contain entire multi-line columns of text. |
| 85 // - Must not be list items, as items in the same list should look consisten
t (*). |
| 86 // - Must not be normal list items, as items in the same list should look |
| 87 // consistent, unless they are floating or position:absolute/fixed. |
| 88 Node* node = renderer->generatingNode(); |
| 89 if ((node && !node->hasChildren()) |
| 90 || !renderer->isRenderBlock() |
| 91 || (renderer->isInline() && !renderer->style()->isDisplayReplacedType())
) |
| 92 return false; |
| 93 if (renderer->isListItem()) |
| 94 return renderer->isFloating() || renderer->isOutOfFlowPositioned(); |
| 95 // Avoid creating containers for text within text controls, buttons, or <sel
ect> buttons. |
| 96 Node* parentNode = renderer->parent() ? renderer->parent()->generatingNode()
: 0; |
| 97 if (parentNode && parentNode->isElementNode() && formInputTags().contains(to
Element(parentNode)->tagQName())) |
| 98 return false; |
| 99 |
| 100 return true; |
| 101 } |
| 102 |
| 103 static RenderObject* nextInPreOrderSkippingDescendantsOfContainers(const RenderO
bject* current, const RenderObject* stayWithin) |
| 104 { |
| 105 if (current == stayWithin || !isAutosizingContainer(current)) |
| 106 return current->nextInPreOrder(stayWithin); |
| 107 return current->nextInPreOrderAfterChildren(stayWithin); |
| 108 } |
| 109 |
| 110 static bool isIndependentDescendant(const RenderBlock* renderer) |
| 111 { |
| 112 ASSERT(isAutosizingContainer(renderer)); |
| 113 |
| 114 // "Autosizing clusters" are special autosizing containers within which we |
| 115 // want to enforce a uniform text size multiplier, in the hopes of making |
| 116 // the major sections of the page look internally consistent. |
| 117 // All their descendants (including other autosizing containers) must share |
| 118 // the same multiplier, except for subtrees which are themselves clusters, |
| 119 // and some of their descendant containers might not be autosized at all |
| 120 // (for example if their height is constrained). |
| 121 // Additionally, clusterShouldBeAutosized requires each cluster to contain a |
| 122 // minimum amount of text, without which it won't be autosized. |
| 123 // |
| 124 // Clusters are chosen using very similar criteria to CSS flow roots, aka |
| 125 // block formatting contexts (http://w3.org/TR/css3-box/#flow-root), since |
| 126 // flow roots correspond to box containers that behave somewhat |
| 127 // independently from their parent (for example they don't overlap floats). |
| 128 // The definition of a flow root also conveniently includes most of the |
| 129 // ways that a box and its children can have significantly different width |
| 130 // from the box's parent (we want to avoid having significantly different |
| 131 // width blocks within a cluster, since the narrower blocks would end up |
| 132 // larger than would otherwise be necessary). |
| 133 RenderBlock* containingBlock = renderer->containingBlock(); |
| 134 return renderer->isRenderView() |
| 135 || renderer->isFloating() |
| 136 || renderer->isOutOfFlowPositioned() |
| 137 || renderer->isTableCell() |
| 138 || renderer->isTableCaption() |
| 139 || renderer->isFlexibleBoxIncludingDeprecated() |
| 140 || renderer->hasColumns() |
| 141 || (containingBlock && containingBlock->isHorizontalWritingMode() != ren
derer->isHorizontalWritingMode()) |
| 142 || renderer->style()->isDisplayReplacedType() |
| 143 || renderer->isTextArea() |
| 144 || renderer->style()->userModify() != READ_ONLY; |
| 145 // FIXME: Tables need special handling to multiply all their columns by |
| 146 // the same amount even if they're different widths; so do hasColumns() |
| 147 // containers, and probably flexboxes... |
| 148 } |
| 149 |
| 150 static bool containerIsRowOfLinks(const RenderObject* container) |
| 151 { |
| 152 // A "row of links" is a container for which holds: |
| 153 // 1. it should not contain non-link text elements longer than 3 characters |
| 154 // 2. it should contain min. 3 inline links and all links should |
| 155 // have the same specified font size |
| 156 // 3. it should not contain <br> elements |
| 157 // 4. it should contain only inline elements unless they are containers, |
| 158 // children of link elements or children of sub-containers. |
| 159 int linkCount = 0; |
| 160 RenderObject* renderer = container->nextInPreOrder(container); |
| 161 float matchingFontSize = -1; |
| 162 |
| 163 while (renderer) { |
| 164 if (!isAutosizingContainer(renderer)) { |
| 165 if (renderer->isText() && toRenderText(renderer)->text().impl()->str
ipWhiteSpace()->length() > 3) |
| 166 return false; |
| 167 if (!renderer->isInline()) |
| 168 return false; |
| 169 if (renderer->isBR()) |
| 170 return false; |
| 171 } |
| 172 if (renderer->style()->isLink()) { |
| 173 if (matchingFontSize < 0) { |
| 174 matchingFontSize = renderer->style()->specifiedFontSize(); |
| 175 } else { |
| 176 if (matchingFontSize != renderer->style()->specifiedFontSize()) |
| 177 return false; |
| 178 } |
| 179 |
| 180 linkCount++; |
| 181 // Skip traversing descendants of the link. |
| 182 renderer = renderer->nextInPreOrderAfterChildren(container); |
| 183 } else { |
| 184 renderer = nextInPreOrderSkippingDescendantsOfContainers(renderer, c
ontainer); |
| 185 } |
| 186 } |
| 187 |
| 188 return (linkCount >= 3); |
| 189 } |
| 190 |
| 191 static bool contentHeightIsConstrained(const RenderBlock* container) |
| 192 { |
| 193 // FIXME: Propagate constrainedness down the tree, to avoid inefficiently wa
lking back up from each box. |
| 194 // FIXME: This code needs to take into account vertical writing modes. |
| 195 // FIXME: Consider additional heuristics, such as ignoring fixed heights if
the content is already overflowing before autosizing kicks in. |
| 196 for (; container; container = container->containingBlock()) { |
| 197 RenderStyle* style = container->style(); |
| 198 if (style->overflowY() >= OSCROLL) |
| 199 return false; |
| 200 if (style->height().isSpecified() || style->maxHeight().isSpecified() ||
container->isOutOfFlowPositioned()) { |
| 201 // Some sites (e.g. wikipedia) set their html and/or body elements t
o height:100%, |
| 202 // without intending to constrain the height of the content within t
hem. |
| 203 return !container->isRoot() && !container->isBody(); |
| 204 } |
| 205 if (container->isFloating()) |
| 206 return false; |
| 207 } |
| 208 return false; |
| 209 } |
| 210 |
| 211 static bool containerContainsOneOfTags(const RenderBlock* container, const Vecto
r<QualifiedName>& tags) |
| 212 { |
| 213 const RenderObject* renderer = container; |
| 214 while (renderer) { |
| 215 const Node* rendererNode = renderer->node(); |
| 216 if (rendererNode && rendererNode->isElementNode()) { |
| 217 if (tags.contains(toElement(rendererNode)->tagQName())) |
| 218 return true; |
| 219 } |
| 220 renderer = nextInPreOrderSkippingDescendantsOfContainers(renderer, conta
iner); |
| 221 } |
| 222 |
| 223 return false; |
| 224 } |
| 225 |
| 226 static bool containerShouldBeAutosized(const RenderBlock* container) |
| 227 { |
| 228 if (containerContainsOneOfTags(container, formInputTags())) |
| 229 return false; |
| 230 |
| 231 if (containerIsRowOfLinks(container)) |
| 232 return false; |
| 233 |
| 234 // Don't autosize block-level text that can't wrap (as it's likely to |
| 235 // expand sideways and break the page's layout). |
| 236 if (!container->style()->autoWrap()) |
| 237 return false; |
| 238 |
| 239 return !contentHeightIsConstrained(container); |
| 240 } |
| 241 |
67 FastTextAutosizer::FastTextAutosizer(const Document* document) | 242 FastTextAutosizer::FastTextAutosizer(const Document* document) |
68 : m_document(document) | 243 : m_document(document) |
69 , m_frameWidth(0) | 244 , m_frameWidth(0) |
70 , m_layoutWidth(0) | 245 , m_layoutWidth(0) |
71 , m_baseMultiplier(0) | 246 , m_baseMultiplier(0) |
72 , m_pageAutosizingStatus(PageAutosizingStatusUnknown) | 247 , m_pageAutosizingStatus(PageAutosizingStatusUnknown) |
73 , m_firstBlock(0) | 248 , m_firstBlock(0) |
74 #ifndef NDEBUG | 249 #ifndef NDEBUG |
75 , m_renderViewInfoPrepared(false) | 250 , m_renderViewInfoPrepared(false) |
76 , m_blocksThatHaveBegunLayout() | 251 , m_blocksThatHaveBegunLayout() |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 continue; | 357 continue; |
183 for (RenderObject* row = section->firstChild(); row; row = row->nextSibl
ing()) { | 358 for (RenderObject* row = section->firstChild(); row; row = row->nextSibl
ing()) { |
184 if (!row->isTableRow()) | 359 if (!row->isTableRow()) |
185 continue; | 360 continue; |
186 for (RenderObject* cell = row->firstChild(); cell; cell = cell->next
Sibling()) { | 361 for (RenderObject* cell = row->firstChild(); cell; cell = cell->next
Sibling()) { |
187 if (!cell->isTableCell()) | 362 if (!cell->isTableCell()) |
188 continue; | 363 continue; |
189 RenderTableCell* renderTableCell = toRenderTableCell(cell); | 364 RenderTableCell* renderTableCell = toRenderTableCell(cell); |
190 | 365 |
191 bool shouldAutosize; | 366 bool shouldAutosize; |
192 if (!TextAutosizer::containerShouldBeAutosized(renderTableCell)) | 367 if (!containerShouldBeAutosized(renderTableCell)) |
193 shouldAutosize = false; | 368 shouldAutosize = false; |
194 else if (Supercluster* supercluster = getSupercluster(renderTabl
eCell)) | 369 else if (Supercluster* supercluster = getSupercluster(renderTabl
eCell)) |
195 shouldAutosize = anyClusterHasEnoughTextToAutosize(superclus
ter->m_roots, table); | 370 shouldAutosize = anyClusterHasEnoughTextToAutosize(superclus
ter->m_roots, table); |
196 else | 371 else |
197 shouldAutosize = clusterWouldHaveEnoughTextToAutosize(render
TableCell, table); | 372 shouldAutosize = clusterWouldHaveEnoughTextToAutosize(render
TableCell, table); |
198 | 373 |
199 if (shouldAutosize) { | 374 if (shouldAutosize) { |
200 for (RenderObject* child = cell; child; child = child->nextI
nPreOrder(cell)) { | 375 for (RenderObject* child = cell; child; child = child->nextI
nPreOrder(cell)) { |
201 if (child->isText()) { | 376 if (child->isText()) { |
202 applyMultiplier(child, multiplier); | 377 applyMultiplier(child, multiplier); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 | 453 |
279 #ifndef NDEBUG | 454 #ifndef NDEBUG |
280 m_renderViewInfoPrepared = true; | 455 m_renderViewInfoPrepared = true; |
281 #endif | 456 #endif |
282 } | 457 } |
283 | 458 |
284 bool FastTextAutosizer::isFingerprintingCandidate(const RenderBlock* block) | 459 bool FastTextAutosizer::isFingerprintingCandidate(const RenderBlock* block) |
285 { | 460 { |
286 // FIXME: move the logic out of TextAutosizer.cpp into this class. | 461 // FIXME: move the logic out of TextAutosizer.cpp into this class. |
287 return block->isRenderView() | 462 return block->isRenderView() |
288 || (TextAutosizer::isAutosizingContainer(block) | 463 || (isAutosizingContainer(block) |
289 && (TextAutosizer::isIndependentDescendant(block) | 464 && (isIndependentDescendant(block) |
290 || mightBeWiderOrNarrowerDescendant(block))); | 465 || mightBeWiderOrNarrowerDescendant(block))); |
291 } | 466 } |
292 | 467 |
293 bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock*
root, const RenderBlock* widthProvider) | 468 bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock*
root, const RenderBlock* widthProvider) |
294 { | 469 { |
295 Cluster hypotheticalCluster(root, true, 0); | 470 Cluster hypotheticalCluster(root, true, 0); |
296 return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider); | 471 return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider); |
297 } | 472 } |
298 | 473 |
299 bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const R
enderBlock* widthProvider) | 474 bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const R
enderBlock* widthProvider) |
300 { | 475 { |
301 if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText) | 476 if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText) |
302 return cluster->m_hasEnoughTextToAutosize == HasEnoughText; | 477 return cluster->m_hasEnoughTextToAutosize == HasEnoughText; |
303 | 478 |
304 const RenderBlock* root = cluster->m_root; | 479 const RenderBlock* root = cluster->m_root; |
305 if (!widthProvider) | 480 if (!widthProvider) |
306 widthProvider = clusterWidthProvider(root); | 481 widthProvider = clusterWidthProvider(root); |
307 | 482 |
308 // TextAreas and user-modifiable areas get a free pass to autosize regardles
s of text content. | 483 // TextAreas and user-modifiable areas get a free pass to autosize regardles
s of text content. |
309 if (root->isTextArea() || (root->style() && root->style()->userModify() != R
EAD_ONLY)) { | 484 if (root->isTextArea() || (root->style() && root->style()->userModify() != R
EAD_ONLY)) { |
310 cluster->m_hasEnoughTextToAutosize = HasEnoughText; | 485 cluster->m_hasEnoughTextToAutosize = HasEnoughText; |
311 return true; | 486 return true; |
312 } | 487 } |
313 | 488 |
314 if (!TextAutosizer::containerShouldBeAutosized(root)) { | 489 if (!containerShouldBeAutosized(root)) { |
315 cluster->m_hasEnoughTextToAutosize = NotEnoughText; | 490 cluster->m_hasEnoughTextToAutosize = NotEnoughText; |
316 return false; | 491 return false; |
317 } | 492 } |
318 | 493 |
319 // 4 lines of text is considered enough to autosize. | 494 // 4 lines of text is considered enough to autosize. |
320 float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4; | 495 float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4; |
321 | 496 |
322 float length = 0; | 497 float length = 0; |
323 RenderObject* descendant = root->nextInPreOrder(root); | 498 RenderObject* descendant = root->nextInPreOrder(root); |
324 while (descendant) { | 499 while (descendant) { |
325 if (descendant->isRenderBlock()) { | 500 if (descendant->isRenderBlock()) { |
326 RenderBlock* block = toRenderBlock(descendant); | 501 RenderBlock* block = toRenderBlock(descendant); |
327 if (TextAutosizer::isAutosizingContainer(block)) { | 502 if (isAutosizingContainer(block)) { |
328 // Note: Ideally we would check isWiderOrNarrowerDescendant here
but we only know that | 503 // Note: Ideally we would check isWiderOrNarrowerDescendant here
but we only know that |
329 // after the block has entered layout, which may not be th
e case. | 504 // after the block has entered layout, which may not be th
e case. |
330 bool isAutosizingClusterRoot = TextAutosizer::isIndependentDesce
ndant(block) || block->isTable(); | 505 bool isAutosizingClusterRoot = isIndependentDescendant(block) ||
block->isTable(); |
331 if ((isAutosizingClusterRoot && !block->isTableCell()) | 506 if ((isAutosizingClusterRoot && !block->isTableCell()) |
332 || !TextAutosizer::containerShouldBeAutosized(block)) { | 507 || !containerShouldBeAutosized(block)) { |
333 descendant = descendant->nextInPreOrderAfterChildren(root); | 508 descendant = descendant->nextInPreOrderAfterChildren(root); |
334 continue; | 509 continue; |
335 } | 510 } |
336 } | 511 } |
337 } else if (descendant->isText()) { | 512 } else if (descendant->isText()) { |
338 // Note: Using text().stripWhiteSpace().length() instead of rendered
TextLength() because | 513 // Note: Using text().stripWhiteSpace().length() instead of rendered
TextLength() because |
339 // the lineboxes will not be built until layout. These values can be
different. | 514 // the lineboxes will not be built until layout. These values can be
different. |
340 // Note: This is an approximation assuming each character is 1em wid
e. | 515 // Note: This is an approximation assuming each character is 1em wid
e. |
341 length += toRenderText(descendant)->text().stripWhiteSpace().length(
) * descendant->style()->specifiedFontSize(); | 516 length += toRenderText(descendant)->text().stripWhiteSpace().length(
) * descendant->style()->specifiedFontSize(); |
342 | 517 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 if (renderer->isTableCell()) | 573 if (renderer->isTableCell()) |
399 data.m_column = renderer->node()->nodeIndex(); | 574 data.m_column = renderer->node()->nodeIndex(); |
400 | 575 |
401 return StringHasher::computeHash<UChar>( | 576 return StringHasher::computeHash<UChar>( |
402 static_cast<const UChar*>(static_cast<const void*>(&data)), | 577 static_cast<const UChar*>(static_cast<const void*>(&data)), |
403 sizeof data / sizeof(UChar)); | 578 sizeof data / sizeof(UChar)); |
404 } | 579 } |
405 | 580 |
406 FastTextAutosizer::Cluster* FastTextAutosizer::maybeCreateCluster(const RenderBl
ock* block) | 581 FastTextAutosizer::Cluster* FastTextAutosizer::maybeCreateCluster(const RenderBl
ock* block) |
407 { | 582 { |
408 if (!TextAutosizer::isAutosizingContainer(block)) | 583 if (!isAutosizingContainer(block)) |
409 return 0; | 584 return 0; |
410 | 585 |
411 Cluster* parentCluster = m_clusterStack.isEmpty() ? 0 : currentCluster(); | 586 Cluster* parentCluster = m_clusterStack.isEmpty() ? 0 : currentCluster(); |
412 ASSERT(parentCluster || block->isRenderView()); | 587 ASSERT(parentCluster || block->isRenderView()); |
413 | 588 |
414 // Create clusters to suppress / unsuppress autosizing based on containerSho
uldBeAutosized. | 589 // Create clusters to suppress / unsuppress autosizing based on containerSho
uldBeAutosized. |
415 bool containerCanAutosize = TextAutosizer::containerShouldBeAutosized(block)
; | 590 bool containerCanAutosize = containerShouldBeAutosized(block); |
416 bool parentClusterCanAutosize = parentCluster && parentCluster->m_autosize; | 591 bool parentClusterCanAutosize = parentCluster && parentCluster->m_autosize; |
417 bool createClusterThatMightAutosize = block->isRenderView() | 592 bool createClusterThatMightAutosize = block->isRenderView() |
418 || mightBeWiderOrNarrowerDescendant(block) | 593 || mightBeWiderOrNarrowerDescendant(block) |
419 || TextAutosizer::isIndependentDescendant(block) | 594 || isIndependentDescendant(block) |
420 || block->isTable(); | 595 || block->isTable(); |
421 | 596 |
422 // If the container would not alter the m_autosize bit, it doesn't need to b
e a cluster. | 597 // If the container would not alter the m_autosize bit, it doesn't need to b
e a cluster. |
423 if (!createClusterThatMightAutosize && containerCanAutosize == parentCluster
CanAutosize) | 598 if (!createClusterThatMightAutosize && containerCanAutosize == parentCluster
CanAutosize) |
424 return 0; | 599 return 0; |
425 | 600 |
426 return new Cluster(block, containerCanAutosize, parentCluster, getSuperclust
er(block)); | 601 return new Cluster(block, containerCanAutosize, parentCluster, getSuperclust
er(block)); |
427 } | 602 } |
428 | 603 |
429 FastTextAutosizer::Supercluster* FastTextAutosizer::getSupercluster(const Render
Block* block) | 604 FastTextAutosizer::Supercluster* FastTextAutosizer::getSupercluster(const Render
Block* block) |
(...skipping 30 matching lines...) Expand all Loading... |
460 } | 635 } |
461 ASSERT_NOT_REACHED(); | 636 ASSERT_NOT_REACHED(); |
462 return 0; | 637 return 0; |
463 } | 638 } |
464 | 639 |
465 float FastTextAutosizer::clusterMultiplier(Cluster* cluster) | 640 float FastTextAutosizer::clusterMultiplier(Cluster* cluster) |
466 { | 641 { |
467 ASSERT(m_renderViewInfoPrepared); | 642 ASSERT(m_renderViewInfoPrepared); |
468 if (!cluster->m_multiplier) { | 643 if (!cluster->m_multiplier) { |
469 if (cluster->m_root->isTable() | 644 if (cluster->m_root->isTable() |
470 || TextAutosizer::isIndependentDescendant(cluster->m_root) | 645 || isIndependentDescendant(cluster->m_root) |
471 || isWiderOrNarrowerDescendant(cluster)) { | 646 || isWiderOrNarrowerDescendant(cluster)) { |
472 | 647 |
473 if (cluster->m_supercluster) { | 648 if (cluster->m_supercluster) { |
474 cluster->m_multiplier = superclusterMultiplier(cluster); | 649 cluster->m_multiplier = superclusterMultiplier(cluster); |
475 } else if (clusterHasEnoughTextToAutosize(cluster)) { | 650 } else if (clusterHasEnoughTextToAutosize(cluster)) { |
476 cluster->m_multiplier = multiplierFromBlock(clusterWidthProvider
(cluster->m_root)); | 651 cluster->m_multiplier = multiplierFromBlock(clusterWidthProvider
(cluster->m_root)); |
477 // Do not inflate table descendants above the table's multiplier
. See inflateTable(...) for details. | 652 // Do not inflate table descendants above the table's multiplier
. See inflateTable(...) for details. |
478 if (cluster->m_hasTableAncestor) | 653 if (cluster->m_hasTableAncestor) |
479 cluster->m_multiplier = min(cluster->m_multiplier, clusterMu
ltiplier(cluster->m_parent)); | 654 cluster->m_multiplier = min(cluster->m_multiplier, clusterMu
ltiplier(cluster->m_parent)); |
480 } else { | 655 } else { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 return parent; | 789 return parent; |
615 | 790 |
616 if (parent->isEmpty()) | 791 if (parent->isEmpty()) |
617 return parent->isText() ? parent : 0; | 792 return parent->isText() ? parent : 0; |
618 | 793 |
619 ++depth; | 794 ++depth; |
620 const RenderObject* child = (firstOrLast == First) ? parent->firstChild() :
parent->lastChild(); | 795 const RenderObject* child = (firstOrLast == First) ? parent->firstChild() :
parent->lastChild(); |
621 while (child) { | 796 while (child) { |
622 // Note: At this point clusters may not have been created for these bloc
ks so we cannot rely | 797 // Note: At this point clusters may not have been created for these bloc
ks so we cannot rely |
623 // on m_clusters. Instead, we use a best-guess about whether the b
lock will become a cluster. | 798 // on m_clusters. Instead, we use a best-guess about whether the b
lock will become a cluster. |
624 if (!TextAutosizer::isAutosizingContainer(child) || !TextAutosizer::isIn
dependentDescendant(toRenderBlock(child))) { | 799 if (!isAutosizingContainer(child) || !isIndependentDescendant(toRenderBl
ock(child))) { |
625 const RenderObject* leaf = findTextLeaf(child, depth, firstOrLast); | 800 const RenderObject* leaf = findTextLeaf(child, depth, firstOrLast); |
626 if (leaf) | 801 if (leaf) |
627 return leaf; | 802 return leaf; |
628 } | 803 } |
629 child = (firstOrLast == First) ? child->nextSibling() : child->previousS
ibling(); | 804 child = (firstOrLast == First) ? child->nextSibling() : child->previousS
ibling(); |
630 } | 805 } |
631 --depth; | 806 --depth; |
632 | 807 |
633 return 0; | 808 return 0; |
634 } | 809 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 m_textAutosizer = 0; | 958 m_textAutosizer = 0; |
784 } | 959 } |
785 | 960 |
786 FastTextAutosizer::LayoutScope::~LayoutScope() | 961 FastTextAutosizer::LayoutScope::~LayoutScope() |
787 { | 962 { |
788 if (m_textAutosizer) | 963 if (m_textAutosizer) |
789 m_textAutosizer->endLayout(m_block); | 964 m_textAutosizer->endLayout(m_block); |
790 } | 965 } |
791 | 966 |
792 } // namespace WebCore | 967 } // namespace WebCore |
OLD | NEW |