| 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 |