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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 { | 227 { |
228 ASSERT(isPotentialClusterRoot(block)); | 228 ASSERT(isPotentialClusterRoot(block)); |
229 return isIndependentDescendant(block) || mightBeWiderOrNarrowerDescendant(bl
ock) || block->isTable(); | 229 return isIndependentDescendant(block) || mightBeWiderOrNarrowerDescendant(bl
ock) || block->isTable(); |
230 } | 230 } |
231 | 231 |
232 FastTextAutosizer::FastTextAutosizer(const Document* document) | 232 FastTextAutosizer::FastTextAutosizer(const Document* document) |
233 : m_document(document) | 233 : m_document(document) |
234 , m_frameWidth(0) | 234 , m_frameWidth(0) |
235 , m_layoutWidth(0) | 235 , m_layoutWidth(0) |
236 , m_baseMultiplier(0) | 236 , m_baseMultiplier(0) |
237 , m_pageNeedsAutosizing(false) | 237 , m_pageAutosizingStatus(PageAutosizingStatusUnknown) |
238 , m_previouslyAutosized(false) | |
239 , m_firstBlock(0) | 238 , m_firstBlock(0) |
240 #ifndef NDEBUG | 239 #ifndef NDEBUG |
| 240 , m_renderViewInfoPrepared(false) |
241 , m_blocksThatHaveBegunLayout() | 241 , m_blocksThatHaveBegunLayout() |
242 #endif | 242 #endif |
243 , m_superclusters() | 243 , m_superclusters() |
244 , m_clusterStack() | 244 , m_clusterStack() |
245 , m_fingerprintMapper() | 245 , m_fingerprintMapper() |
246 { | 246 { |
247 } | 247 } |
248 | 248 |
249 void FastTextAutosizer::record(const RenderBlock* block) | 249 void FastTextAutosizer::record(const RenderBlock* block) |
250 { | 250 { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 #ifndef NDEBUG | 283 #ifndef NDEBUG |
284 m_blocksThatHaveBegunLayout.add(block); | 284 m_blocksThatHaveBegunLayout.add(block); |
285 #endif | 285 #endif |
286 if (Cluster* cluster = maybeCreateCluster(block)) | 286 if (Cluster* cluster = maybeCreateCluster(block)) |
287 m_clusterStack.append(adoptPtr(cluster)); | 287 m_clusterStack.append(adoptPtr(cluster)); |
288 } | 288 } |
289 } | 289 } |
290 | 290 |
291 void FastTextAutosizer::beginLayout(RenderBlock* block) | 291 void FastTextAutosizer::beginLayout(RenderBlock* block) |
292 { | 292 { |
293 ASSERT(enabled() && m_pageNeedsAutosizing); | 293 ASSERT(enabled() && m_pageAutosizingStatus == PageNeedsAutosizing); |
294 #ifndef NDEBUG | 294 #ifndef NDEBUG |
295 m_blocksThatHaveBegunLayout.add(block); | 295 m_blocksThatHaveBegunLayout.add(block); |
296 #endif | 296 #endif |
297 | 297 |
298 if (!m_firstBlock) { | 298 if (!m_firstBlock) { |
299 m_firstBlock = block; | 299 m_firstBlock = block; |
300 prepareClusterStack(block->parent()); | 300 prepareClusterStack(block->parent()); |
301 } else if (block == currentCluster()->m_root) { | 301 } else if (block == currentCluster()->m_root) { |
302 // Ignore beginLayout on the same block twice. | 302 // Ignore beginLayout on the same block twice. |
303 // This can happen with paginated overflow. | 303 // This can happen with paginated overflow. |
304 return; | 304 return; |
305 } | 305 } |
306 | 306 |
307 if (Cluster* cluster = maybeCreateCluster(block)) { | 307 if (Cluster* cluster = maybeCreateCluster(block)) { |
308 m_clusterStack.append(adoptPtr(cluster)); | 308 m_clusterStack.append(adoptPtr(cluster)); |
309 if (block->isTable()) | 309 if (block->isTable()) |
310 inflateTable(toRenderTable(block)); | 310 inflateTable(toRenderTable(block)); |
311 } | 311 } |
312 | 312 |
313 if (block->childrenInline() && block->firstChild()) | 313 if (block->childrenInline() && block->firstChild()) |
314 inflate(block); | 314 inflate(block); |
315 } | 315 } |
316 | 316 |
317 void FastTextAutosizer::inflateListItem(RenderListItem* listItem, RenderListMark
er* listItemMarker) | 317 void FastTextAutosizer::inflateListItem(RenderListItem* listItem, RenderListMark
er* listItemMarker) |
318 { | 318 { |
319 if (!enabled() || !m_pageNeedsAutosizing) | 319 if (!enabled() || m_pageAutosizingStatus != PageNeedsAutosizing) |
320 return; | 320 return; |
321 ASSERT(listItem && listItemMarker); | 321 ASSERT(listItem && listItemMarker); |
322 #ifndef NDEBUG | 322 #ifndef NDEBUG |
323 m_blocksThatHaveBegunLayout.add(listItem); | 323 m_blocksThatHaveBegunLayout.add(listItem); |
324 #endif | 324 #endif |
325 // Force the LI to be inside the DBCAT when computing the multiplier. | 325 // Force the LI to be inside the DBCAT when computing the multiplier. |
326 // This guarantees that the DBCAT has entered layout, so we can ask for its
width. | 326 // This guarantees that the DBCAT has entered layout, so we can ask for its
width. |
327 // It also makes sense because the list marker is autosized like a text node
. | 327 // It also makes sense because the list marker is autosized like a text node
. |
328 float multiplier = clusterMultiplier(currentCluster()); | 328 float multiplier = clusterMultiplier(currentCluster()); |
329 | 329 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 } | 372 } |
373 } | 373 } |
374 } | 374 } |
375 } | 375 } |
376 } | 376 } |
377 } | 377 } |
378 } | 378 } |
379 | 379 |
380 void FastTextAutosizer::endLayout(RenderBlock* block) | 380 void FastTextAutosizer::endLayout(RenderBlock* block) |
381 { | 381 { |
382 ASSERT(enabled() && m_pageNeedsAutosizing); | 382 ASSERT(enabled() && m_pageAutosizingStatus == PageNeedsAutosizing); |
383 | 383 |
384 if (block == m_firstBlock) { | 384 if (block == m_firstBlock) { |
385 m_firstBlock = 0; | 385 m_firstBlock = 0; |
| 386 m_pageAutosizingStatus = PageAutosizingStatusUnknown; |
386 m_clusterStack.clear(); | 387 m_clusterStack.clear(); |
387 m_superclusters.clear(); | 388 m_superclusters.clear(); |
388 #ifndef NDEBUG | 389 #ifndef NDEBUG |
389 m_blocksThatHaveBegunLayout.clear(); | 390 m_blocksThatHaveBegunLayout.clear(); |
390 #endif | 391 #endif |
391 } else if (currentCluster()->m_root == block) { | 392 } else if (currentCluster()->m_root == block) { |
392 m_clusterStack.removeLast(); | 393 m_clusterStack.removeLast(); |
393 } | 394 } |
394 } | 395 } |
395 | 396 |
(...skipping 21 matching lines...) Expand all Loading... |
417 } | 418 } |
418 | 419 |
419 bool FastTextAutosizer::enabled() | 420 bool FastTextAutosizer::enabled() |
420 { | 421 { |
421 if (!m_document->settings() || !m_document->page() || m_document->printing()
) | 422 if (!m_document->settings() || !m_document->page() || m_document->printing()
) |
422 return false; | 423 return false; |
423 | 424 |
424 return m_document->settings()->textAutosizingEnabled(); | 425 return m_document->settings()->textAutosizingEnabled(); |
425 } | 426 } |
426 | 427 |
427 void FastTextAutosizer::updatePageInfoInAllFrames() | 428 void FastTextAutosizer::updateRenderViewInfo() |
428 { | 429 { |
429 if (!enabled()) | |
430 return; | |
431 | |
432 ASSERT(m_document->frame()->isMainFrame()); | |
433 | |
434 for (LocalFrame* frame = m_document->frame(); frame; frame = frame->tree().t
raverseNext()) { | |
435 if (FastTextAutosizer* textAutosizer = frame->document()->fastTextAutosi
zer()) | |
436 textAutosizer->updatePageInfo(); | |
437 } | |
438 } | |
439 | |
440 void FastTextAutosizer::updatePageInfo() | |
441 { | |
442 if (!enabled()) | |
443 return; | |
444 | |
445 int previousFrameWidth = m_frameWidth; | |
446 int previousLayoutWidth = m_layoutWidth; | |
447 float previousBaseMultiplier = m_baseMultiplier; | |
448 | |
449 RenderView* renderView = toRenderView(m_document->renderer()); | 430 RenderView* renderView = toRenderView(m_document->renderer()); |
450 bool horizontalWritingMode = isHorizontalWritingMode(renderView->style()->wr
itingMode()); | 431 bool horizontalWritingMode = isHorizontalWritingMode(renderView->style()->wr
itingMode()); |
451 | 432 |
452 LocalFrame* mainFrame = m_document->page()->mainFrame(); | 433 LocalFrame* mainFrame = m_document->page()->mainFrame(); |
453 IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride
(); | 434 IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride
(); |
454 if (frameSize.isEmpty()) | 435 if (frameSize.isEmpty()) |
455 frameSize = mainFrame->view()->unscaledVisibleContentSize(IncludeScrollb
ars); | 436 frameSize = mainFrame->view()->unscaledVisibleContentSize(IncludeScrollb
ars); |
456 m_frameWidth = horizontalWritingMode ? frameSize.width() : frameSize.height(
); | 437 m_frameWidth = horizontalWritingMode ? frameSize.width() : frameSize.height(
); |
457 | 438 |
458 IntSize layoutSize = m_document->page()->mainFrame()->view()->layoutSize(); | 439 IntSize layoutSize = m_document->page()->mainFrame()->view()->layoutSize(); |
459 m_layoutWidth = horizontalWritingMode ? layoutSize.width() : layoutSize.heig
ht(); | 440 m_layoutWidth = horizontalWritingMode ? layoutSize.width() : layoutSize.heig
ht(); |
460 | 441 |
461 // Compute the base font scale multiplier based on device and accessibility
settings. | 442 // Compute the base font scale multiplier based on device and accessibility
settings. |
462 m_baseMultiplier = m_document->settings()->accessibilityFontScaleFactor(); | 443 m_baseMultiplier = m_document->settings()->accessibilityFontScaleFactor(); |
463 // If the page has a meta viewport or @viewport, don't apply the device scal
e adjustment. | 444 // If the page has a meta viewport or @viewport, don't apply the device scal
e adjustment. |
464 const ViewportDescription& viewportDescription = m_document->page()->mainFra
me()->document()->viewportDescription(); | 445 const ViewportDescription& viewportDescription = m_document->page()->mainFra
me()->document()->viewportDescription(); |
465 if (!viewportDescription.isSpecifiedByAuthor()) { | 446 if (!viewportDescription.isSpecifiedByAuthor()) { |
466 float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustm
ent(); | 447 float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustm
ent(); |
467 m_baseMultiplier *= deviceScaleAdjustment; | 448 m_baseMultiplier *= deviceScaleAdjustment; |
468 } | 449 } |
469 | 450 |
470 m_pageNeedsAutosizing = !!m_frameWidth | 451 m_pageAutosizingStatus = m_frameWidth && (m_baseMultiplier * (static_cast<fl
oat>(m_layoutWidth) / m_frameWidth) > 1.0f) |
471 && (m_baseMultiplier * (static_cast<float>(m_layoutWidth) / m_frameWidth
) > 1.0f); | 452 ? PageNeedsAutosizing : PageDoesNotNeedAutosizing; |
472 | 453 |
473 // If we are no longer autosizing the page, we won't do anything during the
next layout. | 454 #ifndef NDEBUG |
474 // Set all the multipliers back to 1 now. | 455 m_renderViewInfoPrepared = true; |
475 if (!m_pageNeedsAutosizing && m_previouslyAutosized) | 456 #endif |
476 resetMultipliers(); | |
477 | |
478 // If page info has changed, multipliers may have changed. Force a layout to
recompute them. | |
479 if (m_pageNeedsAutosizing | |
480 && (m_frameWidth != previousFrameWidth | |
481 || m_layoutWidth != previousLayoutWidth | |
482 || m_baseMultiplier != previousBaseMultiplier)) | |
483 setAllTextNeedsLayout(); | |
484 } | |
485 | |
486 void FastTextAutosizer::resetMultipliers() | |
487 { | |
488 RenderObject* renderer = m_document->renderer(); | |
489 while (renderer) { | |
490 if (RenderStyle* style = renderer->style()) { | |
491 if (style->textAutosizingMultiplier() != 1) | |
492 applyMultiplier(renderer, 1, LayoutNeeded); | |
493 } | |
494 renderer = renderer->nextInPreOrder(); | |
495 } | |
496 m_previouslyAutosized = false; | |
497 } | |
498 | |
499 void FastTextAutosizer::setAllTextNeedsLayout() | |
500 { | |
501 RenderObject* renderer = m_document->renderer(); | |
502 while (renderer) { | |
503 if (renderer->isText()) | |
504 renderer->setNeedsLayout(); | |
505 renderer = renderer->nextInPreOrder(); | |
506 } | |
507 } | 457 } |
508 | 458 |
509 bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock*
root, const RenderBlock* widthProvider) | 459 bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock*
root, const RenderBlock* widthProvider) |
510 { | 460 { |
511 Cluster hypotheticalCluster(root, true, 0); | 461 Cluster hypotheticalCluster(root, true, 0); |
512 return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider); | 462 return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider); |
513 } | 463 } |
514 | 464 |
515 bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const R
enderBlock* widthProvider) | 465 bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const R
enderBlock* widthProvider) |
516 { | 466 { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 if (ancestors.count(block) == blocks.size()) | 614 if (ancestors.count(block) == blocks.size()) |
665 return block; | 615 return block; |
666 } | 616 } |
667 } | 617 } |
668 ASSERT_NOT_REACHED(); | 618 ASSERT_NOT_REACHED(); |
669 return 0; | 619 return 0; |
670 } | 620 } |
671 | 621 |
672 float FastTextAutosizer::clusterMultiplier(Cluster* cluster) | 622 float FastTextAutosizer::clusterMultiplier(Cluster* cluster) |
673 { | 623 { |
| 624 ASSERT(m_renderViewInfoPrepared); |
674 if (!cluster->m_multiplier) { | 625 if (!cluster->m_multiplier) { |
675 if (cluster->m_root->isTable() | 626 if (cluster->m_root->isTable() |
676 || isIndependentDescendant(cluster->m_root) | 627 || isIndependentDescendant(cluster->m_root) |
677 || isWiderOrNarrowerDescendant(cluster)) { | 628 || isWiderOrNarrowerDescendant(cluster)) { |
678 | 629 |
679 if (cluster->m_supercluster) { | 630 if (cluster->m_supercluster) { |
680 cluster->m_multiplier = superclusterMultiplier(cluster); | 631 cluster->m_multiplier = superclusterMultiplier(cluster); |
681 } else if (clusterHasEnoughTextToAutosize(cluster)) { | 632 } else if (clusterHasEnoughTextToAutosize(cluster)) { |
682 cluster->m_multiplier = multiplierFromBlock(clusterWidthProvider
(cluster->m_root)); | 633 cluster->m_multiplier = multiplierFromBlock(clusterWidthProvider
(cluster->m_root)); |
683 // Do not inflate table descendants above the table's multiplier
. See inflateTable(...) for details. | 634 // Do not inflate table descendants above the table's multiplier
. See inflateTable(...) for details. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 if (leaf) | 783 if (leaf) |
833 return leaf; | 784 return leaf; |
834 } | 785 } |
835 child = (firstOrLast == First) ? child->nextSibling() : child->previousS
ibling(); | 786 child = (firstOrLast == First) ? child->nextSibling() : child->previousS
ibling(); |
836 } | 787 } |
837 --depth; | 788 --depth; |
838 | 789 |
839 return 0; | 790 return 0; |
840 } | 791 } |
841 | 792 |
842 void FastTextAutosizer::applyMultiplier(RenderObject* renderer, float multiplier
, RelayoutBehavior relayoutBehavior) | 793 void FastTextAutosizer::applyMultiplier(RenderObject* renderer, float multiplier
) |
843 { | 794 { |
844 ASSERT(renderer); | 795 ASSERT(renderer); |
845 RenderStyle* currentStyle = renderer->style(); | 796 RenderStyle* currentStyle = renderer->style(); |
846 if (currentStyle->textAutosizingMultiplier() == multiplier) | 797 if (currentStyle->textAutosizingMultiplier() == multiplier) |
847 return; | 798 return; |
848 | 799 |
849 // We need to clone the render style to avoid breaking style sharing. | 800 // We need to clone the render style to avoid breaking style sharing. |
850 RefPtr<RenderStyle> style = RenderStyle::clone(currentStyle); | 801 RefPtr<RenderStyle> style = RenderStyle::clone(currentStyle); |
851 style->setTextAutosizingMultiplier(multiplier); | 802 style->setTextAutosizingMultiplier(multiplier); |
852 style->setUnique(); | 803 style->setUnique(); |
853 | 804 renderer->setStyleInternal(style.release()); |
854 switch (relayoutBehavior) { | |
855 case AlreadyInLayout: | |
856 renderer->setStyleInternal(style.release()); | |
857 if (renderer->isRenderBlock()) | |
858 toRenderBlock(renderer)->invalidateLineHeight(); | |
859 break; | |
860 | |
861 case LayoutNeeded: | |
862 renderer->setStyle(style.release()); | |
863 break; | |
864 } | |
865 | |
866 if (multiplier != 1) | |
867 m_previouslyAutosized = true; | |
868 } | 805 } |
869 | 806 |
870 bool FastTextAutosizer::isWiderOrNarrowerDescendant(Cluster* cluster) | 807 bool FastTextAutosizer::isWiderOrNarrowerDescendant(Cluster* cluster) |
871 { | 808 { |
872 if (!cluster->m_parent || !mightBeWiderOrNarrowerDescendant(cluster->m_root)
) | 809 if (!cluster->m_parent || !mightBeWiderOrNarrowerDescendant(cluster->m_root)
) |
873 return true; | 810 return true; |
874 | 811 |
875 const RenderBlock* parentDeepestBlockContainingAllText = deepestBlockContain
ingAllText(cluster->m_parent); | 812 const RenderBlock* parentDeepestBlockContainingAllText = deepestBlockContain
ingAllText(cluster->m_parent); |
876 ASSERT(m_blocksThatHaveBegunLayout.contains(cluster->m_root)); | 813 ASSERT(m_blocksThatHaveBegunLayout.contains(cluster->m_root)); |
877 ASSERT(m_blocksThatHaveBegunLayout.contains(parentDeepestBlockContainingAllT
ext)); | 814 ASSERT(m_blocksThatHaveBegunLayout.contains(parentDeepestBlockContainingAllT
ext)); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 return *m_blocksForFingerprint.get(fingerprint); | 905 return *m_blocksForFingerprint.get(fingerprint); |
969 } | 906 } |
970 | 907 |
971 FastTextAutosizer::LayoutScope::LayoutScope(RenderBlock* block) | 908 FastTextAutosizer::LayoutScope::LayoutScope(RenderBlock* block) |
972 : m_textAutosizer(block->document().fastTextAutosizer()) | 909 : m_textAutosizer(block->document().fastTextAutosizer()) |
973 , m_block(block) | 910 , m_block(block) |
974 { | 911 { |
975 if (!m_textAutosizer) | 912 if (!m_textAutosizer) |
976 return; | 913 return; |
977 | 914 |
978 if (m_textAutosizer->enabled() && m_textAutosizer->m_pageNeedsAutosizing) | 915 if (!m_textAutosizer->enabled()) { |
| 916 m_textAutosizer = 0; |
| 917 return; |
| 918 } |
| 919 |
| 920 if (m_textAutosizer->m_pageAutosizingStatus == PageAutosizingStatusUnknown) |
| 921 m_textAutosizer->updateRenderViewInfo(); |
| 922 |
| 923 if (m_textAutosizer->m_pageAutosizingStatus == PageNeedsAutosizing) |
979 m_textAutosizer->beginLayout(m_block); | 924 m_textAutosizer->beginLayout(m_block); |
980 else | 925 else |
981 m_textAutosizer = 0; | 926 m_textAutosizer = 0; |
982 } | 927 } |
983 | 928 |
984 FastTextAutosizer::LayoutScope::~LayoutScope() | 929 FastTextAutosizer::LayoutScope::~LayoutScope() |
985 { | 930 { |
986 if (m_textAutosizer) | 931 if (m_textAutosizer) |
987 m_textAutosizer->endLayout(m_block); | 932 m_textAutosizer->endLayout(m_block); |
988 } | 933 } |
989 | 934 |
990 } // namespace WebCore | 935 } // namespace WebCore |
OLD | NEW |