Changeset 57030 in webkit
- Timestamp:
- Apr 2, 2010 4:21:35 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r57028 r57030 1 2010-04-02 James Robinson <jamesr@chromium.org> 2 3 Reviewed by Darin Adler. 4 5 Splits RenderBlock::layoutInline into smaller functions 6 https://bugs.webkit.org/show_bug.cgi?id=36921 7 8 RenderBlock::layoutInlineChildren is 351 lines long and very difficult 9 to comprehend or edit safely. This patch splits it up into a few 10 slightly smaller functions. Most of the code is now in the 241 line 11 layoutRunsAndFloats() which is a slight improvement. 12 13 Perf neutral on the page cyclers. This doesn't introduce any function 14 calls into the hottest layout paths inside layoutRunsAndFloats and 15 findNextLineBreak. 16 17 No change in behavior, no new tests. 18 19 * rendering/RenderBlock.h: 20 (WebCore::RenderBlock::FloatWithRect::FloatWithRect): 21 * rendering/RenderBlockLineLayout.cpp: 22 (WebCore::RenderBlock::layoutReplacedElements): 23 (WebCore::RenderBlock::createLineBoxesForResolver): 24 (WebCore::RenderBlock::layoutRunsAndFloats): 25 (WebCore::RenderBlock::layoutInlineChildren): 26 1 27 2010-04-02 Evan Stade <estade@chromium.org> 2 28 -
trunk/WebCore/rendering/RenderBlock.h
r55890 r57030 484 484 // End helper functions and structs used by layoutBlockChildren. 485 485 486 // Helper functions for layoutInlineChildren() 487 bool layoutReplacedElements(bool relayoutChildren, bool fullLayout, Vector<FloatWithRect>&); 488 RootInlineBox* createLineBoxesForResolver(const InlineBidiResolver&, const InlineIterator& position, bool firstLine, bool previousLineBrokeCleanly, BidiRun* trailingSpaceRun); 489 void layoutRunsAndFloats(bool fullLayout, Vector<FloatWithRect>&, int& repaintTop, int& repaintBottom); 490 486 491 typedef ListHashSet<RenderBox*>::const_iterator Iterator; 487 492 DeprecatedPtrList<FloatingObject>* m_floatingObjects; -
trunk/WebCore/rendering/RenderBlockLineLayout.cpp
r56186 r57030 515 515 } 516 516 517 void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom) 518 { 517 // This is a helper for RenderBlock::layoutInlineChildren. It iterates through a RenderBlock's inline children 518 // in bidi order and: 519 // - calls layoutIfNeeded() on all replaced children 520 // - assembles a list of floats 521 // - adds all positioned children to their containing block's positioned object set 522 // - dirties line boxes on inline children if fullLayout is set 523 bool RenderBlock::layoutReplacedElements(bool relayoutChildren, bool fullLayout, Vector<FloatWithRect>& floats) 524 { 525 bool endOfInline = false; 526 bool hasInlineChild = false; 527 // FIXME: Use a more descriptive variable name and use a for loop instead of while here. 528 RenderObject* o = bidiFirst(this, 0, false); 529 while (o) { 530 if (o->isReplaced() || o->isFloating() || o->isPositioned()) { 531 RenderBox* box = toRenderBox(o); 532 533 if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent()) 534 o->setChildNeedsLayout(true, false); 535 536 // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths. 537 if (relayoutChildren && (o->style()->paddingLeft().isPercent() || o->style()->paddingRight().isPercent())) 538 o->setPrefWidthsDirty(true, false); 539 540 if (o->isPositioned()) 541 o->containingBlock()->insertPositionedObject(box); 542 else { 543 if (o->isFloating()) 544 floats.append(RenderBlock::FloatWithRect(box)); 545 else if (fullLayout || o->needsLayout()) // Replaced elements 546 toRenderBox(o)->dirtyLineBoxes(fullLayout); 547 548 o->layoutIfNeeded(); 549 } 550 } else if (o->isText() || (o->isRenderInline() && !endOfInline)) { 551 hasInlineChild = true; 552 if (fullLayout || o->selfNeedsLayout()) 553 dirtyLineBoxesForRenderer(o, fullLayout); 554 o->setNeedsLayout(false); 555 if (!o->isText()) 556 toRenderInline(o)->invalidateVerticalPosition(); // FIXME: Should do better here and not always invalidate everything. 557 } 558 o = bidiNext(this, o, 0, false, &endOfInline); 559 } 560 return hasInlineChild; 561 } 562 563 // This function constructs line boxes for all of the text runs in the resolver and computes their position. 564 RootInlineBox* RenderBlock::createLineBoxesForResolver(const InlineBidiResolver& resolver, const InlineIterator& position, bool firstLine, bool previousLineBrokeCleanly, BidiRun* trailingSpaceRun) 565 { 566 RootInlineBox* lineBox = 0; 567 if (resolver.runCount()) { 568 lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), firstLine, !position.obj, position.obj && !position.pos ? position.obj : 0); 569 if (lineBox) { 570 lineBox->setEndsWithBreak(previousLineBrokeCleanly); 571 572 // Now we position all of our text runs horizontally. 573 computeHorizontalPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, position.atEnd()); 574 575 // Now position our text runs vertically. 576 computeVerticalPositionsForLine(lineBox, resolver.firstRun()); 577 578 #if ENABLE(SVG) 579 // Special SVG text layout code 580 lineBox->computePerCharacterLayoutInformation(); 581 #endif 582 583 #if PLATFORM(MAC) 584 // Highlight acts as an overflow inflation. 585 if (style()->highlight() != nullAtom) 586 lineBox->addHighlightOverflow(); 587 #endif 588 } 589 } 590 591 return lineBox; 592 } 593 594 void RenderBlock::layoutRunsAndFloats(bool fullLayout, Vector<FloatWithRect>& floats, int& repaintTop, int& repaintBottom) 595 { 596 // We want to skip ahead to the first dirty line 597 InlineBidiResolver resolver; 598 unsigned floatIndex; 599 bool firstLine = true; 600 bool previousLineBrokeCleanly = true; 519 601 bool useRepaintBounds = false; 520 602 603 RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, previousLineBrokeCleanly, resolver, floats, floatIndex); 604 605 FloatingObject* lastFloat = m_floatingObjects ? m_floatingObjects->last() : 0; 606 607 LineMidpointState& lineMidpointState = resolver.midpointState(); 608 609 // We also find the first clean line and extract these lines. We will add them back 610 // if we determine that we're able to synchronize after handling all our dirty lines. 611 InlineIterator cleanLineStart; 612 BidiStatus cleanLineBidiStatus; 613 int endLineYPos = 0; 614 RootInlineBox* endLine = (fullLayout || !startLine) ? 615 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, endLineYPos); 616 617 if (startLine) { 618 useRepaintBounds = true; 619 repaintTop = height(); 620 repaintBottom = height(); 621 RenderArena* arena = renderArena(); 622 RootInlineBox* box = startLine; 623 while (box) { 624 repaintTop = min(repaintTop, box->topVisibleOverflow()); 625 repaintBottom = max(repaintBottom, box->bottomVisibleOverflow()); 626 RootInlineBox* next = box->nextRootBox(); 627 box->deleteLine(arena); 628 box = next; 629 } 630 } 631 632 InlineIterator currentPosition = resolver.position(); 633 634 if (!fullLayout && lastRootBox() && lastRootBox()->endsWithBreak()) { 635 // If the last line before the start line ends with a line break that clear floats, 636 // adjust the height accordingly. 637 // A line break can be either the first or the last object on a line, depending on its direction. 638 if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) { 639 RenderObject* lastObject = lastLeafChild->renderer(); 640 if (!lastObject->isBR()) 641 lastObject = lastRootBox()->firstLeafChild()->renderer(); 642 if (lastObject->isBR()) { 643 EClear clear = lastObject->style()->clear(); 644 if (clear != CNONE) 645 newLine(clear); 646 } 647 } 648 } 649 650 bool endLineMatched = false; 651 bool checkForEndLineMatch = endLine; 652 bool checkForFloatsFromLastLine = false; 653 654 bool isLineEmpty = true; 655 656 while (!currentPosition.atEnd()) { 657 // FIXME: Is this check necessary before the first iteration or can it be moved to the end? 658 if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop))) 659 break; 660 661 lineMidpointState.reset(); 662 663 isLineEmpty = true; 664 665 EClear clear = CNONE; 666 currentPosition = findNextLineBreak(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly, &clear); 667 if (resolver.position().atEnd()) { 668 resolver.deleteRuns(); 669 checkForFloatsFromLastLine = true; 670 break; 671 } 672 ASSERT(currentPosition != resolver.position()); 673 674 if (!isLineEmpty) { 675 bidiReorderLine(resolver, currentPosition, previousLineBrokeCleanly); 676 ASSERT(resolver.position() == currentPosition); 677 678 BidiRun* trailingSpaceRun = 0; 679 if (!previousLineBrokeCleanly && resolver.runCount() && resolver.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace() 680 && resolver.logicallyLastRun()->m_object->style()->autoWrap()) { 681 trailingSpaceRun = resolver.logicallyLastRun(); 682 RenderObject* lastObject = trailingSpaceRun->m_object; 683 if (lastObject->isText()) { 684 RenderText* lastText = toRenderText(lastObject); 685 const UChar* characters = lastText->characters(); 686 int firstSpace = trailingSpaceRun->stop(); 687 while (firstSpace > trailingSpaceRun->start()) { 688 UChar current = characters[firstSpace - 1]; 689 if (!isCollapsibleSpace(current, lastText)) 690 break; 691 firstSpace--; 692 } 693 if (firstSpace == trailingSpaceRun->stop()) 694 trailingSpaceRun = 0; 695 else { 696 TextDirection direction = style()->direction(); 697 bool shouldReorder = trailingSpaceRun != (direction == LTR ? resolver.lastRun() : resolver.firstRun()); 698 if (firstSpace != trailingSpaceRun->start()) { 699 BidiContext* baseContext = resolver.context(); 700 while (BidiContext* parent = baseContext->parent()) 701 baseContext = parent; 702 703 BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral); 704 trailingSpaceRun->m_stop = firstSpace; 705 if (direction == LTR) 706 resolver.addRun(newTrailingRun); 707 else 708 resolver.prependRun(newTrailingRun); 709 trailingSpaceRun = newTrailingRun; 710 shouldReorder = false; 711 } 712 if (shouldReorder) { 713 if (direction == LTR) { 714 resolver.moveRunToEnd(trailingSpaceRun); 715 trailingSpaceRun->m_level = 0; 716 } else { 717 resolver.moveRunToBeginning(trailingSpaceRun); 718 trailingSpaceRun->m_level = 1; 719 } 720 } 721 } 722 } else 723 trailingSpaceRun = 0; 724 } 725 726 // Now that the runs have been ordered, we create the line boxes. 727 RootInlineBox* lineBox = createLineBoxesForResolver(resolver, currentPosition, firstLine, previousLineBrokeCleanly, trailingSpaceRun); 728 resolver.deleteRuns(); 729 730 // At the same time we figure out where border/padding/margin should be applied for 731 // inline flow boxes. 732 if (lineBox) { 733 lineBox->setLineBreakInfo(currentPosition.obj, currentPosition.pos, resolver.status()); 734 if (useRepaintBounds) { 735 repaintTop = min(repaintTop, lineBox->topVisibleOverflow()); 736 repaintBottom = max(repaintBottom, lineBox->bottomVisibleOverflow()); 737 } 738 } 739 740 firstLine = false; 741 newLine(clear); 742 } 743 744 if (m_floatingObjects && lastRootBox()) { 745 if (lastFloat) { 746 for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { 747 } 748 m_floatingObjects->next(); 749 } else 750 m_floatingObjects->first(); 751 for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) { 752 lastRootBox()->floats().append(f->m_renderer); 753 ASSERT(f->m_renderer == floats[floatIndex].object); 754 // If a float's geometry has changed, give up on syncing with clean lines. 755 if (floats[floatIndex].rect != IntRect(f->m_left, f->m_top, f->m_width, f->m_bottom - f->m_top)) 756 checkForEndLineMatch = false; 757 floatIndex++; 758 } 759 lastFloat = m_floatingObjects->last(); 760 } 761 762 lineMidpointState.reset(); 763 resolver.setPosition(currentPosition); 764 } 765 766 if (endLine) { 767 if (endLineMatched) { 768 // Attach all the remaining lines, and then adjust their y-positions as needed. 769 int delta = height() - endLineYPos; 770 for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { 771 line->attachLine(); 772 if (delta) { 773 repaintTop = min(repaintTop, line->topVisibleOverflow() + min(delta, 0)); 774 repaintBottom = max(repaintBottom, line->bottomVisibleOverflow() + max(delta, 0)); 775 line->adjustPosition(0, delta); 776 } 777 if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { 778 Vector<RenderBox*>::iterator end = cleanLineFloats->end(); 779 for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) { 780 int floatTop = (*f)->y() - (*f)->marginTop(); 781 insertFloatingObject(*f); 782 setHeight(floatTop + delta); 783 positionNewFloats(); 784 } 785 } 786 } 787 setHeight(lastRootBox()->blockHeight()); 788 } else { 789 // Delete all the remaining lines. 790 RootInlineBox* line = endLine; 791 RenderArena* arena = renderArena(); 792 while (line) { 793 repaintTop = min(repaintTop, line->topVisibleOverflow()); 794 repaintBottom = max(repaintBottom, line->bottomVisibleOverflow()); 795 RootInlineBox* next = line->nextRootBox(); 796 line->deleteLine(arena); 797 line = next; 798 } 799 } 800 } 801 if (m_floatingObjects && (checkForFloatsFromLastLine || positionNewFloats()) && lastRootBox()) { 802 // In case we have a float on the last line, it might not be positioned up to now. 803 // This has to be done before adding in the bottom border/padding, or the float will 804 // include the padding incorrectly. -dwh 805 if (checkForFloatsFromLastLine) { 806 int bottomVisualOverflow = lastRootBox()->bottomVisualOverflow(); 807 int bottomLayoutOverflow = lastRootBox()->bottomLayoutOverflow(); 808 TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this); 809 m_lineBoxes.appendLineBox(trailingFloatsLineBox); 810 trailingFloatsLineBox->setConstructed(); 811 trailingFloatsLineBox->verticallyAlignBoxes(height()); 812 trailingFloatsLineBox->setVerticalOverflowPositions(height(), bottomLayoutOverflow, height(), bottomVisualOverflow, 0); 813 trailingFloatsLineBox->setBlockHeight(height()); 814 } 815 if (lastFloat) { 816 for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { 817 } 818 m_floatingObjects->next(); 819 } else 820 m_floatingObjects->first(); 821 for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) 822 lastRootBox()->floats().append(f->m_renderer); 823 lastFloat = m_floatingObjects->last(); 824 } 825 // Floats that did not have layout did not repaint when we laid them out. They would have 826 // painted by now if they had moved, but if they stayed at (0, 0), they still need to be 827 // painted. 828 size_t floatCount = floats.size(); 829 for (size_t i = 0; i < floatCount; ++i) { 830 if (!floats[i].everHadLayout) { 831 RenderBox* f = floats[i].object; 832 if (!f->x() && !f->y() && f->checkForRepaintDuringLayout()) 833 f->repaint(); 834 } 835 } 836 } 837 838 void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom) 839 { 521 840 m_overflow.clear(); 522 841 … … 542 861 543 862 if (firstChild()) { 544 // layout replaced elements545 bool endOfInline = false;546 RenderObject* o = bidiFirst(this, 0, false);547 863 Vector<FloatWithRect> floats; 548 bool hasInlineChild = false; 549 while (o) { 550 if (o->isReplaced() || o->isFloating() || o->isPositioned()) { 551 RenderBox* box = toRenderBox(o); 552 553 if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent()) 554 o->setChildNeedsLayout(true, false); 555 556 // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths. 557 if (relayoutChildren && (o->style()->paddingLeft().isPercent() || o->style()->paddingRight().isPercent())) 558 o->setPrefWidthsDirty(true, false); 559 560 if (o->isPositioned()) 561 o->containingBlock()->insertPositionedObject(box); 562 else { 563 if (o->isFloating()) 564 floats.append(FloatWithRect(box)); 565 else if (fullLayout || o->needsLayout()) // Replaced elements 566 toRenderBox(o)->dirtyLineBoxes(fullLayout); 567 568 o->layoutIfNeeded(); 569 } 570 } else if (o->isText() || (o->isRenderInline() && !endOfInline)) { 571 hasInlineChild = true; 572 if (fullLayout || o->selfNeedsLayout()) 573 dirtyLineBoxesForRenderer(o, fullLayout); 574 o->setNeedsLayout(false); 575 if (!o->isText()) 576 toRenderInline(o)->invalidateVerticalPosition(); // FIXME: Should do better here and not always invalidate everything. 577 } 578 o = bidiNext(this, o, 0, false, &endOfInline); 579 } 580 581 // We want to skip ahead to the first dirty line 582 InlineBidiResolver resolver; 583 unsigned floatIndex; 584 bool firstLine = true; 585 bool previousLineBrokeCleanly = true; 586 RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, previousLineBrokeCleanly, resolver, floats, floatIndex); 864 bool hasInlineChild = layoutReplacedElements(relayoutChildren, fullLayout, floats); 587 865 588 866 if (fullLayout && hasInlineChild && !selfNeedsLayout()) { 589 setNeedsLayout(true, false); 590 867 setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like 868 // we're supposed to. 591 869 RenderView* v = view(); 592 870 if (v && !v->doingFullRepaint() && hasLayer()) { … … 599 877 } 600 878 601 FloatingObject* lastFloat = m_floatingObjects ? m_floatingObjects->last() : 0; 602 603 LineMidpointState& lineMidpointState = resolver.midpointState(); 604 605 // We also find the first clean line and extract these lines. We will add them back 606 // if we determine that we're able to synchronize after handling all our dirty lines. 607 InlineIterator cleanLineStart; 608 BidiStatus cleanLineBidiStatus; 609 int endLineYPos = 0; 610 RootInlineBox* endLine = (fullLayout || !startLine) ? 611 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, endLineYPos); 612 613 if (startLine) { 614 useRepaintBounds = true; 615 repaintTop = height(); 616 repaintBottom = height(); 617 RenderArena* arena = renderArena(); 618 RootInlineBox* box = startLine; 619 while (box) { 620 repaintTop = min(repaintTop, box->topVisibleOverflow()); 621 repaintBottom = max(repaintBottom, box->bottomVisibleOverflow()); 622 RootInlineBox* next = box->nextRootBox(); 623 box->deleteLine(arena); 624 box = next; 625 } 626 } 627 628 InlineIterator end = resolver.position(); 629 630 if (!fullLayout && lastRootBox() && lastRootBox()->endsWithBreak()) { 631 // If the last line before the start line ends with a line break that clear floats, 632 // adjust the height accordingly. 633 // A line break can be either the first or the last object on a line, depending on its direction. 634 if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) { 635 RenderObject* lastObject = lastLeafChild->renderer(); 636 if (!lastObject->isBR()) 637 lastObject = lastRootBox()->firstLeafChild()->renderer(); 638 if (lastObject->isBR()) { 639 EClear clear = lastObject->style()->clear(); 640 if (clear != CNONE) 641 newLine(clear); 642 } 643 } 644 } 645 646 bool endLineMatched = false; 647 bool checkForEndLineMatch = endLine; 648 bool checkForFloatsFromLastLine = false; 649 650 bool isLineEmpty = true; 651 652 while (!end.atEnd()) { 653 // FIXME: Is this check necessary before the first iteration or can it be moved to the end? 654 if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop))) 655 break; 656 657 lineMidpointState.reset(); 658 659 isLineEmpty = true; 660 661 EClear clear = CNONE; 662 end = findNextLineBreak(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly, &clear); 663 if (resolver.position().atEnd()) { 664 resolver.deleteRuns(); 665 checkForFloatsFromLastLine = true; 666 break; 667 } 668 ASSERT(end != resolver.position()); 669 670 if (!isLineEmpty) { 671 bidiReorderLine(resolver, end, previousLineBrokeCleanly); 672 ASSERT(resolver.position() == end); 673 674 BidiRun* trailingSpaceRun = 0; 675 if (!previousLineBrokeCleanly && resolver.runCount() && resolver.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace() 676 && resolver.logicallyLastRun()->m_object->style()->autoWrap()) { 677 trailingSpaceRun = resolver.logicallyLastRun(); 678 RenderObject* lastObject = trailingSpaceRun->m_object; 679 if (lastObject->isText()) { 680 RenderText* lastText = toRenderText(lastObject); 681 const UChar* characters = lastText->characters(); 682 int firstSpace = trailingSpaceRun->stop(); 683 while (firstSpace > trailingSpaceRun->start()) { 684 UChar current = characters[firstSpace - 1]; 685 if (!isCollapsibleSpace(current, lastText)) 686 break; 687 firstSpace--; 688 } 689 if (firstSpace == trailingSpaceRun->stop()) 690 trailingSpaceRun = 0; 691 else { 692 TextDirection direction = style()->direction(); 693 bool shouldReorder = trailingSpaceRun != (direction == LTR ? resolver.lastRun() : resolver.firstRun()); 694 if (firstSpace != trailingSpaceRun->start()) { 695 BidiContext* baseContext = resolver.context(); 696 while (BidiContext* parent = baseContext->parent()) 697 baseContext = parent; 698 699 BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral); 700 trailingSpaceRun->m_stop = firstSpace; 701 if (direction == LTR) 702 resolver.addRun(newTrailingRun); 703 else 704 resolver.prependRun(newTrailingRun); 705 trailingSpaceRun = newTrailingRun; 706 shouldReorder = false; 707 } 708 if (shouldReorder) { 709 if (direction == LTR) { 710 resolver.moveRunToEnd(trailingSpaceRun); 711 trailingSpaceRun->m_level = 0; 712 } else { 713 resolver.moveRunToBeginning(trailingSpaceRun); 714 trailingSpaceRun->m_level = 1; 715 } 716 } 717 } 718 } else 719 trailingSpaceRun = 0; 720 } 721 722 // Now that the runs have been ordered, we create the line boxes. 723 // At the same time we figure out where border/padding/margin should be applied for 724 // inline flow boxes. 725 726 RootInlineBox* lineBox = 0; 727 if (resolver.runCount()) { 728 lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), firstLine, !end.obj, end.obj && !end.pos ? end.obj : 0); 729 if (lineBox) { 730 lineBox->setEndsWithBreak(previousLineBrokeCleanly); 731 732 // Now we position all of our text runs horizontally. 733 computeHorizontalPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd()); 734 735 // Now position our text runs vertically. 736 computeVerticalPositionsForLine(lineBox, resolver.firstRun()); 737 738 #if ENABLE(SVG) 739 // Special SVG text layout code 740 lineBox->computePerCharacterLayoutInformation(); 741 #endif 742 743 #if PLATFORM(MAC) 744 // Highlight acts as an overflow inflation. 745 if (style()->highlight() != nullAtom) 746 lineBox->addHighlightOverflow(); 747 #endif 748 } 749 } 750 751 resolver.deleteRuns(); 752 753 if (lineBox) { 754 lineBox->setLineBreakInfo(end.obj, end.pos, resolver.status()); 755 if (useRepaintBounds) { 756 repaintTop = min(repaintTop, lineBox->topVisibleOverflow()); 757 repaintBottom = max(repaintBottom, lineBox->bottomVisibleOverflow()); 758 } 759 } 760 761 firstLine = false; 762 newLine(clear); 763 } 764 765 if (m_floatingObjects && lastRootBox()) { 766 if (lastFloat) { 767 for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { 768 } 769 m_floatingObjects->next(); 770 } else 771 m_floatingObjects->first(); 772 for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) { 773 lastRootBox()->floats().append(f->m_renderer); 774 ASSERT(f->m_renderer == floats[floatIndex].object); 775 // If a float's geometry has changed, give up on syncing with clean lines. 776 if (floats[floatIndex].rect != IntRect(f->m_left, f->m_top, f->m_width, f->m_bottom - f->m_top)) 777 checkForEndLineMatch = false; 778 floatIndex++; 779 } 780 lastFloat = m_floatingObjects->last(); 781 } 782 783 lineMidpointState.reset(); 784 resolver.setPosition(end); 785 } 786 787 if (endLine) { 788 if (endLineMatched) { 789 // Attach all the remaining lines, and then adjust their y-positions as needed. 790 int delta = height() - endLineYPos; 791 for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { 792 line->attachLine(); 793 if (delta) { 794 repaintTop = min(repaintTop, line->topVisibleOverflow() + min(delta, 0)); 795 repaintBottom = max(repaintBottom, line->bottomVisibleOverflow() + max(delta, 0)); 796 line->adjustPosition(0, delta); 797 } 798 if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { 799 Vector<RenderBox*>::iterator end = cleanLineFloats->end(); 800 for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) { 801 int floatTop = (*f)->y() - (*f)->marginTop(); 802 insertFloatingObject(*f); 803 setHeight(floatTop + delta); 804 positionNewFloats(); 805 } 806 } 807 } 808 setHeight(lastRootBox()->blockHeight()); 809 } else { 810 // Delete all the remaining lines. 811 RootInlineBox* line = endLine; 812 RenderArena* arena = renderArena(); 813 while (line) { 814 repaintTop = min(repaintTop, line->topVisibleOverflow()); 815 repaintBottom = max(repaintBottom, line->bottomVisibleOverflow()); 816 RootInlineBox* next = line->nextRootBox(); 817 line->deleteLine(arena); 818 line = next; 819 } 820 } 821 } 822 if (m_floatingObjects && (checkForFloatsFromLastLine || positionNewFloats()) && lastRootBox()) { 823 // In case we have a float on the last line, it might not be positioned up to now. 824 // This has to be done before adding in the bottom border/padding, or the float will 825 // include the padding incorrectly. -dwh 826 if (checkForFloatsFromLastLine) { 827 int bottomVisualOverflow = lastRootBox()->bottomVisualOverflow(); 828 int bottomLayoutOverflow = lastRootBox()->bottomLayoutOverflow(); 829 TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this); 830 m_lineBoxes.appendLineBox(trailingFloatsLineBox); 831 trailingFloatsLineBox->setConstructed(); 832 trailingFloatsLineBox->verticallyAlignBoxes(height()); 833 trailingFloatsLineBox->setVerticalOverflowPositions(height(), bottomLayoutOverflow, height(), bottomVisualOverflow, 0); 834 trailingFloatsLineBox->setBlockHeight(height()); 835 } 836 if (lastFloat) { 837 for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { 838 } 839 m_floatingObjects->next(); 840 } else 841 m_floatingObjects->first(); 842 for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) 843 lastRootBox()->floats().append(f->m_renderer); 844 lastFloat = m_floatingObjects->last(); 845 } 846 size_t floatCount = floats.size(); 847 // Floats that did not have layout did not repaint when we laid them out. They would have 848 // painted by now if they had moved, but if they stayed at (0, 0), they still need to be 849 // painted. 850 for (size_t i = 0; i < floatCount; ++i) { 851 if (!floats[i].everHadLayout) { 852 RenderBox* f = floats[i].object; 853 if (!f->x() && !f->y() && f->checkForRepaintDuringLayout()) 854 f->repaint(); 855 } 856 } 879 layoutRunsAndFloats(fullLayout, floats, repaintTop, repaintBottom); 857 880 } 858 881
Note: See TracChangeset
for help on using the changeset viewer.