Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: third_party/WebKit/Source/core/layout/TextAutosizer.cpp

Issue 2403553002: reflow comments in core/layout/[M-Z]*.{cpp,h} (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 } 147 }
148 148
149 static bool isPotentialClusterRoot(const LayoutObject* layoutObject) { 149 static bool isPotentialClusterRoot(const LayoutObject* layoutObject) {
150 // "Potential cluster roots" are the smallest unit for which we can 150 // "Potential cluster roots" are the smallest unit for which we can
151 // enable/disable text autosizing. 151 // enable/disable text autosizing.
152 // - Must have children. 152 // - Must have children.
153 // An exception is made for LayoutView which should create a root to 153 // An exception is made for LayoutView which should create a root to
154 // maintain consistency with documents that have no child nodes but may 154 // maintain consistency with documents that have no child nodes but may
155 // still have LayoutObject children. 155 // still have LayoutObject children.
156 // - Must not be inline, as different multipliers on one line looks terrible. 156 // - Must not be inline, as different multipliers on one line looks terrible.
157 // Exceptions are inline-block and alike elements (inline-table, -webkit-inl ine-*), 157 // Exceptions are inline-block and alike elements (inline-table,
158 // as they often contain entire multi-line columns of text. 158 // -webkit-inline-*), as they often contain entire multi-line columns of
159 // text.
159 // - Must not be normal list items, as items in the same list should look 160 // - Must not be normal list items, as items in the same list should look
160 // consistent, unless they are floating or position:absolute/fixed. 161 // consistent, unless they are floating or position:absolute/fixed.
161 Node* node = layoutObject->generatingNode(); 162 Node* node = layoutObject->generatingNode();
162 if (node && !node->hasChildren() && !layoutObject->isLayoutView()) 163 if (node && !node->hasChildren() && !layoutObject->isLayoutView())
163 return false; 164 return false;
164 if (!layoutObject->isLayoutBlock()) 165 if (!layoutObject->isLayoutBlock())
165 return false; 166 return false;
166 if (layoutObject->isInline() && 167 if (layoutObject->isInline() &&
167 !layoutObject->style()->isDisplayReplacedType()) 168 !layoutObject->style()->isDisplayReplacedType())
168 return false; 169 return false;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 layoutObject = layoutObject->nextInPreOrderAfterChildren(block); 221 layoutObject = layoutObject->nextInPreOrderAfterChildren(block);
221 continue; 222 continue;
222 } 223 }
223 layoutObject = layoutObject->nextInPreOrder(block); 224 layoutObject = layoutObject->nextInPreOrder(block);
224 } 225 }
225 226
226 return (linkCount >= 3); 227 return (linkCount >= 3);
227 } 228 }
228 229
229 static bool blockHeightConstrained(const LayoutBlock* block) { 230 static bool blockHeightConstrained(const LayoutBlock* block) {
230 // FIXME: Propagate constrainedness down the tree, to avoid inefficiently walk ing back up from each box. 231 // FIXME: Propagate constrainedness down the tree, to avoid inefficiently
232 // walking back up from each box.
231 // FIXME: This code needs to take into account vertical writing modes. 233 // FIXME: This code needs to take into account vertical writing modes.
232 // FIXME: Consider additional heuristics, such as ignoring fixed heights if th e content is already overflowing before autosizing kicks in. 234 // FIXME: Consider additional heuristics, such as ignoring fixed heights if
235 // the content is already overflowing before autosizing kicks in.
233 for (; block; block = block->containingBlock()) { 236 for (; block; block = block->containingBlock()) {
234 const ComputedStyle& style = block->styleRef(); 237 const ComputedStyle& style = block->styleRef();
235 if (style.overflowY() >= OverflowScroll) 238 if (style.overflowY() >= OverflowScroll)
236 return false; 239 return false;
237 if (style.height().isSpecified() || style.maxHeight().isSpecified() || 240 if (style.height().isSpecified() || style.maxHeight().isSpecified() ||
238 block->isOutOfFlowPositioned()) { 241 block->isOutOfFlowPositioned()) {
239 // Some sites (e.g. wikipedia) set their html and/or body elements to heig ht:100%, 242 // Some sites (e.g. wikipedia) set their html and/or body elements to
240 // without intending to constrain the height of the content within them. 243 // height:100%, without intending to constrain the height of the content
244 // within them.
241 return !block->isDocumentElement() && !block->isBody() && 245 return !block->isDocumentElement() && !block->isBody() &&
242 !block->isLayoutView(); 246 !block->isLayoutView();
243 } 247 }
244 if (block->isFloating()) 248 if (block->isFloating())
245 return false; 249 return false;
246 } 250 }
247 return false; 251 return false;
248 } 252 }
249 253
250 static bool blockOrImmediateChildrenAreFormControls(const LayoutBlock* block) { 254 static bool blockOrImmediateChildrenAreFormControls(const LayoutBlock* block) {
(...skipping 22 matching lines...) Expand all
273 if (!block->style()->autoWrap()) 277 if (!block->style()->autoWrap())
274 return true; 278 return true;
275 279
276 if (blockHeightConstrained(block)) 280 if (blockHeightConstrained(block))
277 return true; 281 return true;
278 282
279 return false; 283 return false;
280 } 284 }
281 285
282 static bool hasExplicitWidth(const LayoutBlock* block) { 286 static bool hasExplicitWidth(const LayoutBlock* block) {
283 // FIXME: This heuristic may need to be expanded to other ways a block can be wider or narrower 287 // FIXME: This heuristic may need to be expanded to other ways a block can be
284 // than its parent containing block. 288 // wider or narrower than its parent containing block.
285 return block->style() && block->style()->width().isSpecified(); 289 return block->style() && block->style()->width().isSpecified();
286 } 290 }
287 291
288 TextAutosizer::TextAutosizer(const Document* document) 292 TextAutosizer::TextAutosizer(const Document* document)
289 : m_document(document), 293 : m_document(document),
290 m_firstBlockToBeginLayout(nullptr), 294 m_firstBlockToBeginLayout(nullptr),
291 #if ENABLE(ASSERT) 295 #if ENABLE(ASSERT)
292 m_blocksThatHaveBegunLayout(), 296 m_blocksThatHaveBegunLayout(),
293 #endif 297 #endif
294 m_superclusters(), 298 m_superclusters(),
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 390
387 void TextAutosizer::inflateAutoTable(LayoutTable* table) { 391 void TextAutosizer::inflateAutoTable(LayoutTable* table) {
388 ASSERT(table); 392 ASSERT(table);
389 ASSERT(!table->style()->isFixedTableLayout()); 393 ASSERT(!table->style()->isFixedTableLayout());
390 ASSERT(table->containingBlock()); 394 ASSERT(table->containingBlock());
391 395
392 Cluster* cluster = currentCluster(); 396 Cluster* cluster = currentCluster();
393 if (cluster->m_root != table) 397 if (cluster->m_root != table)
394 return; 398 return;
395 399
396 // Pre-inflate cells that have enough text so that their inflated preferred wi dths will be used 400 // Pre-inflate cells that have enough text so that their inflated preferred
397 // for column sizing. 401 // widths will be used for column sizing.
398 for (LayoutObject* section = table->firstChild(); section; 402 for (LayoutObject* section = table->firstChild(); section;
399 section = section->nextSibling()) { 403 section = section->nextSibling()) {
400 if (!section->isTableSection()) 404 if (!section->isTableSection())
401 continue; 405 continue;
402 for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row; 406 for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row;
403 row = row->nextRow()) { 407 row = row->nextRow()) {
404 for (LayoutTableCell* cell = row->firstCell(); cell; 408 for (LayoutTableCell* cell = row->firstCell(); cell;
405 cell = cell->nextCell()) { 409 cell = cell->nextCell()) {
406 if (!cell->needsLayout()) 410 if (!cell->needsLayout())
407 continue; 411 continue;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 LayoutObject* child = nullptr; 446 LayoutObject* child = nullptr;
443 if (parent->isLayoutBlock() && 447 if (parent->isLayoutBlock() &&
444 (parent->childrenInline() || behavior == DescendToInnerBlocks)) 448 (parent->childrenInline() || behavior == DescendToInnerBlocks))
445 child = toLayoutBlock(parent)->firstChild(); 449 child = toLayoutBlock(parent)->firstChild();
446 else if (parent->isLayoutInline()) 450 else if (parent->isLayoutInline())
447 child = toLayoutInline(parent)->firstChild(); 451 child = toLayoutInline(parent)->firstChild();
448 452
449 while (child) { 453 while (child) {
450 if (child->isText()) { 454 if (child->isText()) {
451 hasTextChild = true; 455 hasTextChild = true;
452 // We only calculate this multiplier on-demand to ensure the parent block of this text 456 // We only calculate this multiplier on-demand to ensure the parent block
453 // has entered layout. 457 // of this text has entered layout.
454 if (!multiplier) 458 if (!multiplier)
455 multiplier = 459 multiplier =
456 cluster->m_flags & SUPPRESSING ? 1.0f : clusterMultiplier(cluster); 460 cluster->m_flags & SUPPRESSING ? 1.0f : clusterMultiplier(cluster);
457 applyMultiplier(child, multiplier, layouter); 461 applyMultiplier(child, multiplier, layouter);
458 462
459 // FIXME: Investigate why MarkOnlyThis is sufficient. 463 // FIXME: Investigate why MarkOnlyThis is sufficient.
460 if (parent->isLayoutInline()) 464 if (parent->isLayoutInline())
461 child->setPreferredLogicalWidthsDirty(MarkOnlyThis); 465 child->setPreferredLogicalWidthsDirty(MarkOnlyThis);
462 } else if (child->isLayoutInline()) { 466 } else if (child->isLayoutInline()) {
463 multiplier = inflate(child, layouter, behavior, multiplier); 467 multiplier = inflate(child, layouter, behavior, multiplier);
464 } else if (child->isLayoutBlock() && behavior == DescendToInnerBlocks && 468 } else if (child->isLayoutBlock() && behavior == DescendToInnerBlocks &&
465 !classifyBlock(child, 469 !classifyBlock(child,
466 INDEPENDENT | EXPLICIT_WIDTH | SUPPRESSING)) { 470 INDEPENDENT | EXPLICIT_WIDTH | SUPPRESSING)) {
467 multiplier = inflate(child, layouter, behavior, multiplier); 471 multiplier = inflate(child, layouter, behavior, multiplier);
468 } 472 }
469 child = child->nextSibling(); 473 child = child->nextSibling();
470 } 474 }
471 475
472 if (hasTextChild) { 476 if (hasTextChild) {
473 applyMultiplier(parent, multiplier, 477 applyMultiplier(parent, multiplier,
474 layouter); // Parent handles line spacing. 478 layouter); // Parent handles line spacing.
475 } else if (!parent->isListItem()) { 479 } else if (!parent->isListItem()) {
476 // For consistency, a block with no immediate text child should always have a 480 // For consistency, a block with no immediate text child should always have
477 // multiplier of 1. 481 // a multiplier of 1.
478 applyMultiplier(parent, 1, layouter); 482 applyMultiplier(parent, 1, layouter);
479 } 483 }
480 484
481 if (parent->isListItem()) { 485 if (parent->isListItem()) {
482 float multiplier = clusterMultiplier(cluster); 486 float multiplier = clusterMultiplier(cluster);
483 applyMultiplier(parent, multiplier, layouter); 487 applyMultiplier(parent, multiplier, layouter);
484 488
485 // The list item has to be treated special because we can have a tree such t hat you have 489 // The list item has to be treated special because we can have a tree such
486 // a list item for a form inside it. The list marker then ends up inside the form and when 490 // that you have a list item for a form inside it. The list marker then ends
487 // we try to get the clusterMultiplier we have the wrong cluster root to wor k from and get 491 // up inside the form and when we try to get the clusterMultiplier we have
488 // the wrong value. 492 // the wrong cluster root to work from and get the wrong value.
489 LayoutListItem* item = toLayoutListItem(parent); 493 LayoutListItem* item = toLayoutListItem(parent);
490 if (LayoutListMarker* marker = item->marker()) { 494 if (LayoutListMarker* marker = item->marker()) {
491 applyMultiplier(marker, multiplier, layouter); 495 applyMultiplier(marker, multiplier, layouter);
492 marker->setPreferredLogicalWidthsDirty(MarkOnlyThis); 496 marker->setPreferredLogicalWidthsDirty(MarkOnlyThis);
493 } 497 }
494 } 498 }
495 499
496 if (m_pageInfo.m_hasAutosized) 500 if (m_pageInfo.m_hasAutosized)
497 UseCounter::count(*m_document, UseCounter::TextAutosizing); 501 UseCounter::count(*m_document, UseCounter::TextAutosizing);
498 502
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 if (frameSize.isEmpty()) 556 if (frameSize.isEmpty())
553 frameSize = windowSize(); 557 frameSize = windowSize();
554 558
555 m_pageInfo.m_frameWidth = 559 m_pageInfo.m_frameWidth =
556 horizontalWritingMode ? frameSize.width() : frameSize.height(); 560 horizontalWritingMode ? frameSize.width() : frameSize.height();
557 561
558 IntSize layoutSize = mainFrame->view()->layoutSize(); 562 IntSize layoutSize = mainFrame->view()->layoutSize();
559 m_pageInfo.m_layoutWidth = 563 m_pageInfo.m_layoutWidth =
560 horizontalWritingMode ? layoutSize.width() : layoutSize.height(); 564 horizontalWritingMode ? layoutSize.width() : layoutSize.height();
561 565
562 // TODO(pdr): Accessibility should be moved out of the text autosizer. See: crbug.com/645717. 566 // TODO(pdr): Accessibility should be moved out of the text autosizer. See:
567 // crbug.com/645717.
563 m_pageInfo.m_accessibilityFontScaleFactor = 568 m_pageInfo.m_accessibilityFontScaleFactor =
564 m_document->settings()->accessibilityFontScaleFactor(); 569 m_document->settings()->accessibilityFontScaleFactor();
565 570
566 // If the page has a meta viewport or @viewport, don't apply the device scal e adjustment. 571 // If the page has a meta viewport or @viewport, don't apply the device
572 // scale adjustment.
567 if (!mainFrame->document()->viewportDescription().isSpecifiedByAuthor()) 573 if (!mainFrame->document()->viewportDescription().isSpecifiedByAuthor())
568 m_pageInfo.m_deviceScaleAdjustment = 574 m_pageInfo.m_deviceScaleAdjustment =
569 m_document->settings()->deviceScaleAdjustment(); 575 m_document->settings()->deviceScaleAdjustment();
570 else 576 else
571 m_pageInfo.m_deviceScaleAdjustment = 1.0f; 577 m_pageInfo.m_deviceScaleAdjustment = 1.0f;
572 578
573 // TODO(pdr): pageNeedsAutosizing should take into account whether text-size -adjust is used 579 // TODO(pdr): pageNeedsAutosizing should take into account whether
574 // anywhere on the page because that also needs to trigger autosizing. See: crbug.com/646237. 580 // text-size-adjust is used anywhere on the page because that also needs to
581 // trigger autosizing. See: crbug.com/646237.
575 m_pageInfo.m_pageNeedsAutosizing = 582 m_pageInfo.m_pageNeedsAutosizing =
576 !!m_pageInfo.m_frameWidth && 583 !!m_pageInfo.m_frameWidth &&
577 (m_pageInfo.m_accessibilityFontScaleFactor * 584 (m_pageInfo.m_accessibilityFontScaleFactor *
578 m_pageInfo.m_deviceScaleAdjustment * 585 m_pageInfo.m_deviceScaleAdjustment *
579 (static_cast<float>(m_pageInfo.m_layoutWidth) / 586 (static_cast<float>(m_pageInfo.m_layoutWidth) /
580 m_pageInfo.m_frameWidth) > 587 m_pageInfo.m_frameWidth) >
581 1.0f); 588 1.0f);
582 } 589 }
583 590
584 if (m_pageInfo.m_pageNeedsAutosizing) { 591 if (m_pageInfo.m_pageNeedsAutosizing) {
585 // If page info has changed, multipliers may have changed. Force a layout to recompute them. 592 // If page info has changed, multipliers may have changed. Force a layout to
593 // recompute them.
586 if (m_pageInfo.m_frameWidth != previousPageInfo.m_frameWidth || 594 if (m_pageInfo.m_frameWidth != previousPageInfo.m_frameWidth ||
587 m_pageInfo.m_layoutWidth != previousPageInfo.m_layoutWidth || 595 m_pageInfo.m_layoutWidth != previousPageInfo.m_layoutWidth ||
588 m_pageInfo.m_accessibilityFontScaleFactor != 596 m_pageInfo.m_accessibilityFontScaleFactor !=
589 previousPageInfo.m_accessibilityFontScaleFactor || 597 previousPageInfo.m_accessibilityFontScaleFactor ||
590 m_pageInfo.m_deviceScaleAdjustment != 598 m_pageInfo.m_deviceScaleAdjustment !=
591 previousPageInfo.m_deviceScaleAdjustment || 599 previousPageInfo.m_deviceScaleAdjustment ||
592 m_pageInfo.m_settingEnabled != previousPageInfo.m_settingEnabled) 600 m_pageInfo.m_settingEnabled != previousPageInfo.m_settingEnabled)
593 setAllTextNeedsLayout(); 601 setAllTextNeedsLayout();
594 } else if (previousPageInfo.m_hasAutosized) { 602 } else if (previousPageInfo.m_hasAutosized) {
595 // If we are no longer autosizing the page, we won't do anything during the next layout. 603 // If we are no longer autosizing the page, we won't do anything during the
596 // Set all the multipliers back to 1 now. 604 // next layout. Set all the multipliers back to 1 now.
597 resetMultipliers(); 605 resetMultipliers();
598 m_pageInfo.m_hasAutosized = false; 606 m_pageInfo.m_hasAutosized = false;
599 } 607 }
600 } 608 }
601 609
602 IntSize TextAutosizer::windowSize() const { 610 IntSize TextAutosizer::windowSize() const {
603 Page* page = m_document->page(); 611 Page* page = m_document->page();
604 ASSERT(page); 612 ASSERT(page);
605 return page->frameHost().visualViewport().size(); 613 return page->frameHost().visualViewport().size();
606 } 614 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 bool TextAutosizer::clusterHasEnoughTextToAutosize( 671 bool TextAutosizer::clusterHasEnoughTextToAutosize(
664 Cluster* cluster, 672 Cluster* cluster,
665 const LayoutBlock* widthProvider) { 673 const LayoutBlock* widthProvider) {
666 if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText) 674 if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText)
667 return cluster->m_hasEnoughTextToAutosize == HasEnoughText; 675 return cluster->m_hasEnoughTextToAutosize == HasEnoughText;
668 676
669 const LayoutBlock* root = cluster->m_root; 677 const LayoutBlock* root = cluster->m_root;
670 if (!widthProvider) 678 if (!widthProvider)
671 widthProvider = clusterWidthProvider(root); 679 widthProvider = clusterWidthProvider(root);
672 680
673 // TextAreas and user-modifiable areas get a free pass to autosize regardless of text content. 681 // TextAreas and user-modifiable areas get a free pass to autosize regardless
682 // of text content.
674 if (root->isTextArea() || 683 if (root->isTextArea() ||
675 (root->style() && root->style()->userModify() != READ_ONLY)) { 684 (root->style() && root->style()->userModify() != READ_ONLY)) {
676 cluster->m_hasEnoughTextToAutosize = HasEnoughText; 685 cluster->m_hasEnoughTextToAutosize = HasEnoughText;
677 return true; 686 return true;
678 } 687 }
679 688
680 if (cluster->m_flags & SUPPRESSING) { 689 if (cluster->m_flags & SUPPRESSING) {
681 cluster->m_hasEnoughTextToAutosize = NotEnoughText; 690 cluster->m_hasEnoughTextToAutosize = NotEnoughText;
682 return false; 691 return false;
683 } 692 }
684 693
685 // 4 lines of text is considered enough to autosize. 694 // 4 lines of text is considered enough to autosize.
686 float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4; 695 float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4;
687 696
688 float length = 0; 697 float length = 0;
689 LayoutObject* descendant = root->firstChild(); 698 LayoutObject* descendant = root->firstChild();
690 while (descendant) { 699 while (descendant) {
691 if (descendant->isLayoutBlock()) { 700 if (descendant->isLayoutBlock()) {
692 if (classifyBlock(descendant, INDEPENDENT | SUPPRESSING)) { 701 if (classifyBlock(descendant, INDEPENDENT | SUPPRESSING)) {
693 descendant = descendant->nextInPreOrderAfterChildren(root); 702 descendant = descendant->nextInPreOrderAfterChildren(root);
694 continue; 703 continue;
695 } 704 }
696 } else if (descendant->isText()) { 705 } else if (descendant->isText()) {
697 // Note: Using text().stripWhiteSpace().length() instead of resolvedTextLe ngth() because 706 // Note: Using text().stripWhiteSpace().length() instead of
698 // the lineboxes will not be built until layout. These values can be diffe rent. 707 // resolvedTextLength() because the lineboxes will not be built until
708 // layout. These values can be different.
699 // Note: This is an approximation assuming each character is 1em wide. 709 // Note: This is an approximation assuming each character is 1em wide.
700 length += toLayoutText(descendant)->text().stripWhiteSpace().length() * 710 length += toLayoutText(descendant)->text().stripWhiteSpace().length() *
701 descendant->style()->specifiedFontSize(); 711 descendant->style()->specifiedFontSize();
702 712
703 if (length >= minimumTextLengthToAutosize) { 713 if (length >= minimumTextLengthToAutosize) {
704 cluster->m_hasEnoughTextToAutosize = HasEnoughText; 714 cluster->m_hasEnoughTextToAutosize = HasEnoughText;
705 return true; 715 return true;
706 } 716 }
707 } 717 }
708 descendant = descendant->nextInPreOrder(root); 718 descendant = descendant->nextInPreOrder(root);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster( 774 TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster(
765 const LayoutBlock* block) { 775 const LayoutBlock* block) {
766 BlockFlags flags = classifyBlock(block); 776 BlockFlags flags = classifyBlock(block);
767 if (!(flags & POTENTIAL_ROOT)) 777 if (!(flags & POTENTIAL_ROOT))
768 return nullptr; 778 return nullptr;
769 779
770 Cluster* parentCluster = 780 Cluster* parentCluster =
771 m_clusterStack.isEmpty() ? nullptr : currentCluster(); 781 m_clusterStack.isEmpty() ? nullptr : currentCluster();
772 ASSERT(parentCluster || block->isLayoutView()); 782 ASSERT(parentCluster || block->isLayoutView());
773 783
774 // If a non-independent block would not alter the SUPPRESSING flag, it doesn't need to be a cluster. 784 // If a non-independent block would not alter the SUPPRESSING flag, it doesn't
785 // need to be a cluster.
775 bool parentSuppresses = 786 bool parentSuppresses =
776 parentCluster && (parentCluster->m_flags & SUPPRESSING); 787 parentCluster && (parentCluster->m_flags & SUPPRESSING);
777 if (!(flags & INDEPENDENT) && !(flags & EXPLICIT_WIDTH) && 788 if (!(flags & INDEPENDENT) && !(flags & EXPLICIT_WIDTH) &&
778 !!(flags & SUPPRESSING) == parentSuppresses) 789 !!(flags & SUPPRESSING) == parentSuppresses)
779 return nullptr; 790 return nullptr;
780 791
781 Cluster* cluster = 792 Cluster* cluster =
782 new Cluster(block, flags, parentCluster, getSupercluster(block)); 793 new Cluster(block, flags, parentCluster, getSupercluster(block));
783 #ifdef AUTOSIZING_DOM_DEBUG_INFO 794 #ifdef AUTOSIZING_DOM_DEBUG_INFO
784 // Non-SUPPRESSING clusters are annotated in clusterMultiplier. 795 // Non-SUPPRESSING clusters are annotated in clusterMultiplier.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 float TextAutosizer::widthFromBlock(const LayoutBlock* block) const { 910 float TextAutosizer::widthFromBlock(const LayoutBlock* block) const {
900 RELEASE_ASSERT(block); 911 RELEASE_ASSERT(block);
901 RELEASE_ASSERT(block->style()); 912 RELEASE_ASSERT(block->style());
902 913
903 if (!(block->isTable() || block->isTableCell() || block->isListItem())) 914 if (!(block->isTable() || block->isTableCell() || block->isListItem()))
904 return block->contentLogicalWidth().toFloat(); 915 return block->contentLogicalWidth().toFloat();
905 916
906 if (!block->containingBlock()) 917 if (!block->containingBlock())
907 return 0; 918 return 0;
908 919
909 // Tables may be inflated before computing their preferred widths. Try several methods to 920 // Tables may be inflated before computing their preferred widths. Try several
910 // obtain a width, and fall back on a containing block's width. 921 // methods to obtain a width, and fall back on a containing block's width.
911 for (; block; block = block->containingBlock()) { 922 for (; block; block = block->containingBlock()) {
912 float width; 923 float width;
913 Length specifiedWidth = 924 Length specifiedWidth =
914 block->isTableCell() 925 block->isTableCell()
915 ? toLayoutTableCell(block)->styleOrColLogicalWidth() 926 ? toLayoutTableCell(block)->styleOrColLogicalWidth()
916 : block->style()->logicalWidth(); 927 : block->style()->logicalWidth();
917 if (specifiedWidth.isFixed()) { 928 if (specifiedWidth.isFixed()) {
918 if ((width = specifiedWidth.value()) > 0) 929 if ((width = specifiedWidth.value()) > 0)
919 return width; 930 return width;
920 } 931 }
921 if (specifiedWidth.isPercentOrCalc()) { 932 if (specifiedWidth.isPercentOrCalc()) {
922 if (float containerWidth = 933 if (float containerWidth =
923 block->containingBlock()->contentLogicalWidth().toFloat()) { 934 block->containingBlock()->contentLogicalWidth().toFloat()) {
924 if ((width = floatValueForLength(specifiedWidth, containerWidth)) > 0) 935 if ((width = floatValueForLength(specifiedWidth, containerWidth)) > 0)
925 return width; 936 return width;
926 } 937 }
927 } 938 }
928 if ((width = block->contentLogicalWidth().toFloat()) > 0) 939 if ((width = block->contentLogicalWidth().toFloat()) > 0)
929 return width; 940 return width;
930 } 941 }
931 return 0; 942 return 0;
932 } 943 }
933 944
934 float TextAutosizer::multiplierFromBlock(const LayoutBlock* block) { 945 float TextAutosizer::multiplierFromBlock(const LayoutBlock* block) {
935 // If block->needsLayout() is false, it does not need to be in m_blocksThatHav eBegunLayout. 946 // If block->needsLayout() is false, it does not need to be in
936 // This can happen during layout of a positioned object if the cluster's DBCAT is deeper 947 // m_blocksThatHaveBegunLayout. This can happen during layout of a positioned
937 // than the positioned object's containing block, and wasn't marked as needing layout. 948 // object if the cluster's DBCAT is deeper than the positioned object's
949 // containing block, and wasn't marked as needing layout.
938 ASSERT(m_blocksThatHaveBegunLayout.contains(block) || !block->needsLayout()); 950 ASSERT(m_blocksThatHaveBegunLayout.contains(block) || !block->needsLayout());
939 951
940 // Block width, in CSS pixels. 952 // Block width, in CSS pixels.
941 float blockWidth = widthFromBlock(block); 953 float blockWidth = widthFromBlock(block);
942 float layoutWidth = 954 float layoutWidth =
943 std::min(blockWidth, static_cast<float>(m_pageInfo.m_layoutWidth)); 955 std::min(blockWidth, static_cast<float>(m_pageInfo.m_layoutWidth));
944 float multiplier = 956 float multiplier =
945 m_pageInfo.m_frameWidth ? layoutWidth / m_pageInfo.m_frameWidth : 1.0f; 957 m_pageInfo.m_frameWidth ? layoutWidth / m_pageInfo.m_frameWidth : 1.0f;
946 multiplier *= m_pageInfo.m_accessibilityFontScaleFactor * 958 multiplier *= m_pageInfo.m_accessibilityFontScaleFactor *
947 m_pageInfo.m_deviceScaleAdjustment; 959 m_pageInfo.m_deviceScaleAdjustment;
(...skipping 14 matching lines...) Expand all
962 const LayoutBlock* root) const { 974 const LayoutBlock* root) const {
963 size_t firstDepth = 0; 975 size_t firstDepth = 0;
964 const LayoutObject* firstTextLeaf = findTextLeaf(root, firstDepth, First); 976 const LayoutObject* firstTextLeaf = findTextLeaf(root, firstDepth, First);
965 if (!firstTextLeaf) 977 if (!firstTextLeaf)
966 return root; 978 return root;
967 979
968 size_t lastDepth = 0; 980 size_t lastDepth = 0;
969 const LayoutObject* lastTextLeaf = findTextLeaf(root, lastDepth, Last); 981 const LayoutObject* lastTextLeaf = findTextLeaf(root, lastDepth, Last);
970 ASSERT(lastTextLeaf); 982 ASSERT(lastTextLeaf);
971 983
972 // Equalize the depths if necessary. Only one of the while loops below will ge t executed. 984 // Equalize the depths if necessary. Only one of the while loops below will
985 // get executed.
973 const LayoutObject* firstNode = firstTextLeaf; 986 const LayoutObject* firstNode = firstTextLeaf;
974 const LayoutObject* lastNode = lastTextLeaf; 987 const LayoutObject* lastNode = lastTextLeaf;
975 while (firstDepth > lastDepth) { 988 while (firstDepth > lastDepth) {
976 firstNode = firstNode->parent(); 989 firstNode = firstNode->parent();
977 --firstDepth; 990 --firstDepth;
978 } 991 }
979 while (lastDepth > firstDepth) { 992 while (lastDepth > firstDepth) {
980 lastNode = lastNode->parent(); 993 lastNode = lastNode->parent();
981 --lastDepth; 994 --lastDepth;
982 } 995 }
983 996
984 // Go up from both nodes until the parent is the same. Both pointers will poin t to the LCA then. 997 // Go up from both nodes until the parent is the same. Both pointers will
998 // point to the LCA then.
985 while (firstNode != lastNode) { 999 while (firstNode != lastNode) {
986 firstNode = firstNode->parent(); 1000 firstNode = firstNode->parent();
987 lastNode = lastNode->parent(); 1001 lastNode = lastNode->parent();
988 } 1002 }
989 1003
990 if (firstNode->isLayoutBlock()) 1004 if (firstNode->isLayoutBlock())
991 return toLayoutBlock(firstNode); 1005 return toLayoutBlock(firstNode);
992 1006
993 // containingBlock() should never leave the cluster, since it only skips ances tors when finding 1007 // containingBlock() should never leave the cluster, since it only skips
994 // the container of position:absolute/fixed blocks, and those cannot exist bet ween a cluster and 1008 // ancestors when finding the container of position:absolute/fixed blocks, and
995 // its text node's lowest common ancestor as isAutosizingCluster would have ma de them into their 1009 // those cannot exist between a cluster and its text node's lowest common
996 // own independent cluster. 1010 // ancestor as isAutosizingCluster would have made them into their own
1011 // independent cluster.
997 const LayoutBlock* containingBlock = firstNode->containingBlock(); 1012 const LayoutBlock* containingBlock = firstNode->containingBlock();
998 if (!containingBlock) 1013 if (!containingBlock)
999 return root; 1014 return root;
1000 1015
1001 ASSERT(containingBlock->isDescendantOf(root)); 1016 ASSERT(containingBlock->isDescendantOf(root));
1002 return containingBlock; 1017 return containingBlock;
1003 } 1018 }
1004 1019
1005 const LayoutObject* TextAutosizer::findTextLeaf( 1020 const LayoutObject* TextAutosizer::findTextLeaf(
1006 const LayoutObject* parent, 1021 const LayoutObject* parent,
1007 size_t& depth, 1022 size_t& depth,
1008 TextLeafSearch firstOrLast) const { 1023 TextLeafSearch firstOrLast) const {
1009 // List items are treated as text due to the marker. 1024 // List items are treated as text due to the marker.
1010 if (parent->isListItem()) 1025 if (parent->isListItem())
1011 return parent; 1026 return parent;
1012 1027
1013 if (parent->isText()) 1028 if (parent->isText())
1014 return parent; 1029 return parent;
1015 1030
1016 ++depth; 1031 ++depth;
1017 const LayoutObject* child = (firstOrLast == First) ? parent->slowFirstChild() 1032 const LayoutObject* child = (firstOrLast == First) ? parent->slowFirstChild()
1018 : parent->slowLastChild(); 1033 : parent->slowLastChild();
1019 while (child) { 1034 while (child) {
1020 // Note: At this point clusters may not have been created for these blocks s o we cannot rely 1035 // Note: At this point clusters may not have been created for these blocks
1021 // on m_clusters. Instead, we use a best-guess about whether the block will become a cluster. 1036 // so we cannot rely on m_clusters. Instead, we use a best-guess about
1037 // whether the block will become a cluster.
1022 if (!classifyBlock(child, INDEPENDENT)) { 1038 if (!classifyBlock(child, INDEPENDENT)) {
1023 if (const LayoutObject* leaf = findTextLeaf(child, depth, firstOrLast)) 1039 if (const LayoutObject* leaf = findTextLeaf(child, depth, firstOrLast))
1024 return leaf; 1040 return leaf;
1025 } 1041 }
1026 child = (firstOrLast == First) ? child->nextSibling() 1042 child = (firstOrLast == First) ? child->nextSibling()
1027 : child->previousSibling(); 1043 : child->previousSibling();
1028 } 1044 }
1029 --depth; 1045 --depth;
1030 1046
1031 return nullptr; 1047 return nullptr;
1032 } 1048 }
1033 1049
1034 void TextAutosizer::applyMultiplier(LayoutObject* layoutObject, 1050 void TextAutosizer::applyMultiplier(LayoutObject* layoutObject,
1035 float multiplier, 1051 float multiplier,
1036 SubtreeLayoutScope* layouter, 1052 SubtreeLayoutScope* layouter,
1037 RelayoutBehavior relayoutBehavior) { 1053 RelayoutBehavior relayoutBehavior) {
1038 ASSERT(layoutObject); 1054 ASSERT(layoutObject);
1039 ComputedStyle& currentStyle = layoutObject->mutableStyleRef(); 1055 ComputedStyle& currentStyle = layoutObject->mutableStyleRef();
1040 if (!currentStyle.getTextSizeAdjust().isAuto()) { 1056 if (!currentStyle.getTextSizeAdjust().isAuto()) {
1041 // The accessibility font scale factor is applied by the autosizer so we nee d to apply that 1057 // The accessibility font scale factor is applied by the autosizer so we
1042 // scale factor on top of the text-size-adjust multiplier. 1058 // need to apply that scale factor on top of the text-size-adjust
1059 // multiplier.
1043 multiplier = currentStyle.getTextSizeAdjust().multiplier() * 1060 multiplier = currentStyle.getTextSizeAdjust().multiplier() *
1044 m_pageInfo.m_accessibilityFontScaleFactor; 1061 m_pageInfo.m_accessibilityFontScaleFactor;
1045 } else if (multiplier < 1) { 1062 } else if (multiplier < 1) {
1046 // Unlike text-size-adjust, the text autosizer should only inflate fonts. 1063 // Unlike text-size-adjust, the text autosizer should only inflate fonts.
1047 multiplier = 1; 1064 multiplier = 1;
1048 } 1065 }
1049 1066
1050 if (currentStyle.textAutosizingMultiplier() == multiplier) 1067 if (currentStyle.textAutosizingMultiplier() == multiplier)
1051 return; 1068 return;
1052 1069
1053 // We need to clone the layoutObject style to avoid breaking style sharing. 1070 // We need to clone the layoutObject style to avoid breaking style sharing.
1054 RefPtr<ComputedStyle> style = ComputedStyle::clone(currentStyle); 1071 RefPtr<ComputedStyle> style = ComputedStyle::clone(currentStyle);
1055 style->setTextAutosizingMultiplier(multiplier); 1072 style->setTextAutosizingMultiplier(multiplier);
1056 style->setUnique(); 1073 style->setUnique();
1057 1074
1058 switch (relayoutBehavior) { 1075 switch (relayoutBehavior) {
1059 case AlreadyInLayout: 1076 case AlreadyInLayout:
1060 // Don't free currentStyle until the end of the layout pass. This allows o ther parts of the system 1077 // Don't free currentStyle until the end of the layout pass. This allows
1061 // to safely hold raw ComputedStyle* pointers during layout, e.g. Breaking Context::m_currentStyle. 1078 // other parts of the system to safely hold raw ComputedStyle* pointers
1079 // during layout, e.g. BreakingContext::m_currentStyle.
1062 m_stylesRetainedDuringLayout.append(&currentStyle); 1080 m_stylesRetainedDuringLayout.append(&currentStyle);
1063 1081
1064 layoutObject->setStyleInternal(style.release()); 1082 layoutObject->setStyleInternal(style.release());
1065 DCHECK(!layouter || layoutObject->isDescendantOf(&layouter->root())); 1083 DCHECK(!layouter || layoutObject->isDescendantOf(&layouter->root()));
1066 layoutObject->setNeedsLayoutAndFullPaintInvalidation( 1084 layoutObject->setNeedsLayoutAndFullPaintInvalidation(
1067 LayoutInvalidationReason::TextAutosizing, MarkContainerChain, 1085 LayoutInvalidationReason::TextAutosizing, MarkContainerChain,
1068 layouter); 1086 layouter);
1069 break; 1087 break;
1070 1088
1071 case LayoutNeeded: 1089 case LayoutNeeded:
(...skipping 16 matching lines...) Expand all
1088 const LayoutBlock* parentDeepestBlockContainingAllText = 1106 const LayoutBlock* parentDeepestBlockContainingAllText =
1089 deepestBlockContainingAllText(cluster->m_parent); 1107 deepestBlockContainingAllText(cluster->m_parent);
1090 ASSERT(m_blocksThatHaveBegunLayout.contains(cluster->m_root)); 1108 ASSERT(m_blocksThatHaveBegunLayout.contains(cluster->m_root));
1091 ASSERT(m_blocksThatHaveBegunLayout.contains( 1109 ASSERT(m_blocksThatHaveBegunLayout.contains(
1092 parentDeepestBlockContainingAllText)); 1110 parentDeepestBlockContainingAllText));
1093 1111
1094 float contentWidth = cluster->m_root->contentLogicalWidth().toFloat(); 1112 float contentWidth = cluster->m_root->contentLogicalWidth().toFloat();
1095 float clusterTextWidth = 1113 float clusterTextWidth =
1096 parentDeepestBlockContainingAllText->contentLogicalWidth().toFloat(); 1114 parentDeepestBlockContainingAllText->contentLogicalWidth().toFloat();
1097 1115
1098 // Clusters with a root that is wider than the deepestBlockContainingAllText o f their parent 1116 // Clusters with a root that is wider than the deepestBlockContainingAllText
1099 // autosize independently of their parent. 1117 // of their parent autosize independently of their parent.
1100 if (contentWidth > clusterTextWidth) 1118 if (contentWidth > clusterTextWidth)
1101 return true; 1119 return true;
1102 1120
1103 // Clusters with a root that is significantly narrower than the deepestBlockCo ntainingAllText of 1121 // Clusters with a root that is significantly narrower than the
1104 // their parent autosize independently of their parent. 1122 // deepestBlockContainingAllText of their parent autosize independently of
1123 // their parent.
1105 static float narrowWidthDifference = 200; 1124 static float narrowWidthDifference = 200;
1106 if (clusterTextWidth - contentWidth > narrowWidthDifference) 1125 if (clusterTextWidth - contentWidth > narrowWidthDifference)
1107 return true; 1126 return true;
1108 1127
1109 return false; 1128 return false;
1110 } 1129 }
1111 1130
1112 TextAutosizer::Cluster* TextAutosizer::currentCluster() const { 1131 TextAutosizer::Cluster* TextAutosizer::currentCluster() const {
1113 ASSERT_WITH_SECURITY_IMPLICATION(!m_clusterStack.isEmpty()); 1132 ASSERT_WITH_SECURITY_IMPLICATION(!m_clusterStack.isEmpty());
1114 return m_clusterStack.last().get(); 1133 return m_clusterStack.last().get();
1115 } 1134 }
1116 1135
1117 TextAutosizer::Cluster::Cluster(const LayoutBlock* root, 1136 TextAutosizer::Cluster::Cluster(const LayoutBlock* root,
1118 BlockFlags flags, 1137 BlockFlags flags,
1119 Cluster* parent, 1138 Cluster* parent,
1120 Supercluster* supercluster) 1139 Supercluster* supercluster)
1121 : m_root(root), 1140 : m_root(root),
1122 m_flags(flags), 1141 m_flags(flags),
1123 m_deepestBlockContainingAllText(nullptr), 1142 m_deepestBlockContainingAllText(nullptr),
1124 m_parent(parent), 1143 m_parent(parent),
1125 m_multiplier(0), 1144 m_multiplier(0),
1126 m_hasEnoughTextToAutosize(UnknownAmountOfText), 1145 m_hasEnoughTextToAutosize(UnknownAmountOfText),
1127 m_supercluster(supercluster), 1146 m_supercluster(supercluster),
1128 m_hasTableAncestor(root->isTableCell() || 1147 m_hasTableAncestor(root->isTableCell() ||
1129 (m_parent && m_parent->m_hasTableAncestor)) {} 1148 (m_parent && m_parent->m_hasTableAncestor)) {}
1130 1149
1131 #if ENABLE(ASSERT) 1150 #if ENABLE(ASSERT)
1132 void TextAutosizer::FingerprintMapper::assertMapsAreConsistent() { 1151 void TextAutosizer::FingerprintMapper::assertMapsAreConsistent() {
1133 // For each fingerprint -> block mapping in m_blocksForFingerprint we should h ave an associated 1152 // For each fingerprint -> block mapping in m_blocksForFingerprint we should
1134 // map from block -> fingerprint in m_fingerprints. 1153 // have an associated map from block -> fingerprint in m_fingerprints.
1135 ReverseFingerprintMap::iterator end = m_blocksForFingerprint.end(); 1154 ReverseFingerprintMap::iterator end = m_blocksForFingerprint.end();
1136 for (ReverseFingerprintMap::iterator fingerprintIt = 1155 for (ReverseFingerprintMap::iterator fingerprintIt =
1137 m_blocksForFingerprint.begin(); 1156 m_blocksForFingerprint.begin();
1138 fingerprintIt != end; ++fingerprintIt) { 1157 fingerprintIt != end; ++fingerprintIt) {
1139 Fingerprint fingerprint = fingerprintIt->key; 1158 Fingerprint fingerprint = fingerprintIt->key;
1140 BlockSet* blocks = fingerprintIt->value.get(); 1159 BlockSet* blocks = fingerprintIt->value.get();
1141 for (BlockSet::iterator blockIt = blocks->begin(); blockIt != blocks->end(); 1160 for (BlockSet::iterator blockIt = blocks->begin(); blockIt != blocks->end();
1142 ++blockIt) { 1161 ++blockIt) {
1143 const LayoutBlock* block = (*blockIt); 1162 const LayoutBlock* block = (*blockIt);
1144 ASSERT(m_fingerprints.get(block) == fingerprint); 1163 ASSERT(m_fingerprints.get(block) == fingerprint);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1258 // multiplier; hence for specifiedSize == pleasantSize, computedSize will be 1277 // multiplier; hence for specifiedSize == pleasantSize, computedSize will be
1259 // multiplier * pleasantSize. For greater specifiedSizes we want to 1278 // multiplier * pleasantSize. For greater specifiedSizes we want to
1260 // gradually fade out the multiplier, so for every 1px increase in 1279 // gradually fade out the multiplier, so for every 1px increase in
1261 // specifiedSize beyond pleasantSize we will only increase computedSize 1280 // specifiedSize beyond pleasantSize we will only increase computedSize
1262 // by gradientAfterPleasantSize px until we meet the 1281 // by gradientAfterPleasantSize px until we meet the
1263 // computedSize = specifiedSize line, after which we stay on that line (so 1282 // computedSize = specifiedSize line, after which we stay on that line (so
1264 // then every 1px increase in specifiedSize increases computedSize by 1px). 1283 // then every 1px increase in specifiedSize increases computedSize by 1px).
1265 const float gradientAfterPleasantSize = 0.5; 1284 const float gradientAfterPleasantSize = 0.5;
1266 1285
1267 float computedSize; 1286 float computedSize;
1268 // Skip linear backoff for multipliers that shrink the size or when the font s izes are small. 1287 // Skip linear backoff for multipliers that shrink the size or when the font
1288 // sizes are small.
1269 if (multiplier <= 1 || specifiedSize <= pleasantSize) { 1289 if (multiplier <= 1 || specifiedSize <= pleasantSize) {
1270 computedSize = multiplier * specifiedSize; 1290 computedSize = multiplier * specifiedSize;
1271 } else { 1291 } else {
1272 computedSize = multiplier * pleasantSize + 1292 computedSize = multiplier * pleasantSize +
1273 gradientAfterPleasantSize * (specifiedSize - pleasantSize); 1293 gradientAfterPleasantSize * (specifiedSize - pleasantSize);
1274 if (computedSize < specifiedSize) 1294 if (computedSize < specifiedSize)
1275 computedSize = specifiedSize; 1295 computedSize = specifiedSize;
1276 } 1296 }
1277 return computedSize; 1297 return computedSize;
1278 } 1298 }
1279 1299
1280 DEFINE_TRACE(TextAutosizer) { 1300 DEFINE_TRACE(TextAutosizer) {
1281 visitor->trace(m_document); 1301 visitor->trace(m_document);
1282 } 1302 }
1283 1303
1284 } // namespace blink 1304 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698