OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. |
4 * Copyright (C) 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
5 * Copyright (C) 2013 Adobe Systems Incorporated. | 5 * Copyright (C) 2013 Adobe Systems Incorporated. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 | 95 |
96 void increment(); | 96 void increment(); |
97 | 97 |
98 void handleBR(EClear&); | 98 void handleBR(EClear&); |
99 void handleOutOfFlowPositioned(Vector<LineLayoutBox>& positionedObjects); | 99 void handleOutOfFlowPositioned(Vector<LineLayoutBox>& positionedObjects); |
100 void handleFloat(); | 100 void handleFloat(); |
101 void handleEmptyInline(); | 101 void handleEmptyInline(); |
102 void handleReplaced(); | 102 void handleReplaced(); |
103 bool handleText(WordMeasurements&, bool& hyphenated); | 103 bool handleText(WordMeasurements&, bool& hyphenated); |
104 void prepareForNextCharacter(const LineLayoutText&, bool& prohibitBreakInsid
e, bool previousCharacterIsSpace, bool previousCharacterShouldCollapseIfPreWap); | 104 void prepareForNextCharacter(const LineLayoutText&, bool& prohibitBreakInsid
e, bool previousCharacterIsSpace, bool previousCharacterShouldCollapseIfPreWap); |
| 105 bool canBreakAtWhitespace(bool breakWords, WordMeasurement&, bool stoppedIgn
oringSpaces, bool& hyphenated, float charWidth, float& hyphenWidth, bool between
Words, bool midWordBreak, bool breakAll, bool previousCharacterIsSpace, float la
stWidthMeasurement, const LineLayoutText&, const Font&, bool applyWordSpacing, f
loat wordSpacing); |
| 106 bool trailingSpaceExceedsAvailableWidth(bool midWordBreak, const LineLayoutT
ext&, WordMeasurement&, bool applyWordSpacing, bool wordSpacing, const Font&); |
| 107 WordMeasurement& calculateWordWidth(WordMeasurements&, LineLayoutText&, unsi
gned lastSpace, float& lastWidthMeasurement, float wordSpacingForWordMeasurement
, const Font&, float wordTrailingSpaceWidth, UChar); |
| 108 void stopIgnoringSpaces(unsigned& lastSpace); |
105 void commitAndUpdateLineBreakIfNeeded(); | 109 void commitAndUpdateLineBreakIfNeeded(); |
106 InlineIterator handleEndOfLine(); | 110 InlineIterator handleEndOfLine(); |
107 | 111 |
108 void clearLineBreakIfFitsOnLine() | 112 void clearLineBreakIfFitsOnLine() |
109 { | 113 { |
110 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) | 114 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) |
111 m_lineBreak.clear(); | 115 m_lineBreak.clear(); |
112 } | 116 } |
113 | 117 |
114 private: | 118 private: |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) | 620 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) |
617 m_lineInfo.setEmpty(false, m_block, &m_width); | 621 m_lineInfo.setEmpty(false, m_block, &m_width); |
618 | 622 |
619 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth) { | 623 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth) { |
620 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode(
m_resolver.position().direction())); | 624 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode(
m_resolver.position().direction())); |
621 m_width.addUncommittedWidth(hyphenWidth); | 625 m_width.addUncommittedWidth(hyphenWidth); |
622 } | 626 } |
623 | 627 |
624 bool applyWordSpacing = false; | 628 bool applyWordSpacing = false; |
625 | 629 |
| 630 // Determine if we should try breaking in the middle of a word. |
626 if (breakWords && !midWordBreak) { | 631 if (breakWords && !midWordBreak) { |
627 widthFromLastBreakingOpportunity += charWidth; | 632 widthFromLastBreakingOpportunity += charWidth; |
628 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current
.offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar
acterAt(m_current.offset() + 1)); | 633 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current
.offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar
acterAt(m_current.offset() + 1)); |
629 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs
BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak
ingOpportunity, m_collapseWhiteSpace); | 634 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs
BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak
ingOpportunity, m_collapseWhiteSpace); |
630 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor
tunity + charWidth > m_width.availableWidth(); | 635 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor
tunity + charWidth > m_width.availableWidth(); |
631 } | 636 } |
632 | 637 |
| 638 // Determine if we are in the whitespace between words. |
633 int nextBreakablePosition = m_current.nextBreakablePosition(); | 639 int nextBreakablePosition = m_current.nextBreakablePosition(); |
634 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt
art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next
BreakablePosition, breakAll ? LineBreakType::BreakAll : keepAll ? LineBreakType:
:KeepAll : LineBreakType::Normal)); | 640 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt
art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next
BreakablePosition, breakAll ? LineBreakType::BreakAll : keepAll ? LineBreakType:
:KeepAll : LineBreakType::Normal)); |
635 m_current.setNextBreakablePosition(nextBreakablePosition); | 641 m_current.setNextBreakablePosition(nextBreakablePosition); |
636 | 642 |
637 // If we're in the middle of a word or at the start of a new one and can
't break there, then continue to the next character. | 643 // If we're in the middle of a word or at the start of a new one and can
't break there, then continue to the next character. |
638 if (!betweenWords && !midWordBreak) { | 644 if (!betweenWords && !midWordBreak) { |
639 if (m_ignoringSpaces) { | 645 if (m_ignoringSpaces) { |
640 // Stop ignoring spaces and begin at this | 646 // Stop ignoring spaces and begin at this |
641 // new point. | 647 // new point. |
642 m_ignoringSpaces = false; | |
643 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | 648 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
644 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure
ments.last().width) ? wordSpacing : 0; | 649 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure
ments.last().width) ? wordSpacing : 0; |
645 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add
in any of the ignored spaces. | 650 stopIgnoringSpaces(lastSpace); |
646 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_curre
nt.object(), m_current.offset())); | |
647 } | 651 } |
648 | 652 |
649 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCha
racterIsSpace, previousCharacterShouldCollapseIfPreWap); | 653 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCha
racterIsSpace, previousCharacterShouldCollapseIfPreWap); |
650 m_atStart = false; | 654 m_atStart = false; |
651 nextCharacter(c, lastCharacter, secondToLastCharacter); | 655 nextCharacter(c, lastCharacter, secondToLastCharacter); |
652 continue; | 656 continue; |
653 } | 657 } |
654 | 658 |
655 // If we're ignoring space and we're at a collapsible space such as a sp
ace or tab, continue to the next character. | 659 // If we're collapsing space and we're at a collapsible space such as a
space or tab, continue to the next character. |
| 660 if (m_ignoringSpaces && m_currentCharacterIsSpace) { |
| 661 lastSpaceWordSpacing = 0; |
| 662 // Just keep ignoring these spaces. |
| 663 nextCharacter(c, lastCharacter, secondToLastCharacter); |
| 664 continue; |
| 665 } |
| 666 |
| 667 // We're in the first whitespace after a word or in whitespace that we d
on't collapse, which means we may have a breaking opportunity here. |
| 668 |
| 669 // If we're here and we're collapsing space then the current character i
sn't a form of whitespace we can collapse. Stop ignoring spaces. |
656 bool stoppedIgnoringSpaces = false; | 670 bool stoppedIgnoringSpaces = false; |
657 if (m_ignoringSpaces) { | 671 if (m_ignoringSpaces) { |
658 lastSpaceWordSpacing = 0; | 672 lastSpaceWordSpacing = 0; |
659 if (!m_currentCharacterIsSpace) { | 673 wordSpacingForWordMeasurement = 0; |
660 // Stop ignoring spaces and begin at this | 674 stoppedIgnoringSpaces = true; |
661 // new point. | 675 stopIgnoringSpaces(lastSpace); |
662 m_ignoringSpaces = false; | |
663 wordSpacingForWordMeasurement = 0; | |
664 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add
in any of the ignored spaces. | |
665 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_curre
nt.object(), m_current.offset())); | |
666 stoppedIgnoringSpaces = true; | |
667 } else { | |
668 // Just keep ignoring these spaces. | |
669 nextCharacter(c, lastCharacter, secondToLastCharacter); | |
670 continue; | |
671 } | |
672 } | 676 } |
673 | 677 |
674 // We're in the first whitespace after a word or in whitespace that we d
on't collapse, which means we may have a breaking opportunity here. | 678 // Update our tally of the width since the last breakable position with
the width of the word we're now at the end of. |
675 wordMeasurements.grow(wordMeasurements.size() + 1); | |
676 WordMeasurement& wordMeasurement = wordMeasurements.last(); | |
677 | |
678 wordMeasurement.layoutText = layoutText; | |
679 wordMeasurement.endOffset = m_current.offset(); | |
680 wordMeasurement.startOffset = lastSpace; | |
681 | |
682 float lastWidthMeasurement; | 679 float lastWidthMeasurement; |
683 if (wordTrailingSpaceWidth && c == spaceCharacter) | 680 WordMeasurement& wordMeasurement = calculateWordWidth(wordMeasurements,
layoutText, lastSpace, lastWidthMeasurement, wordSpacingForWordMeasurement, font
, wordTrailingSpaceWidth, c); |
684 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.of
fset() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wor
dMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpaceWid
th; | |
685 else | |
686 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.of
fset() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMea
surement.fallbackFonts, &wordMeasurement.glyphBounds); | |
687 | |
688 wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMeasure
ment; | |
689 wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0); | |
690 lastWidthMeasurement += lastSpaceWordSpacing; | 681 lastWidthMeasurement += lastSpaceWordSpacing; |
691 m_width.addUncommittedWidth(lastWidthMeasurement); | 682 m_width.addUncommittedWidth(lastWidthMeasurement); |
692 | 683 |
| 684 // We keep track of the total width contributed by trailing space as we
often want to exclude it when determining |
| 685 // if a run fits on a line. |
693 if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharact
erIsSpace && lastWidthMeasurement) | 686 if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharact
erIsSpace && lastWidthMeasurement) |
694 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); | 687 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); |
695 | 688 |
| 689 // If this is the end of the first word in run of text then make sure we
apply the width from any leading inlines. |
| 690 // For example: '<span style="margin-left: 5px;"><span style="margin-lef
t: 10px;">FirstWord</span></span>' would |
| 691 // apply a width of 15px from the two span ancestors. |
696 if (!m_appliedStartWidth) { | 692 if (!m_appliedStartWidth) { |
697 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded(
m_current.object(), true, false).toFloat()); | 693 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded(
m_current.object(), true, false).toFloat()); |
698 m_appliedStartWidth = true; | 694 m_appliedStartWidth = true; |
699 } | 695 } |
700 | 696 |
701 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; | 697 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
702 | 698 |
| 699 // If we haven't hit a breakable position yet and already don't fit on t
he line try to move below any floats. |
703 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() &&
!widthMeasurementAtLastBreakOpportunity) | 700 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() &&
!widthMeasurementAtLastBreakOpportunity) |
704 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 701 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
705 | 702 |
706 if (m_autoWrap || breakWords) { | 703 // If there is a soft-break available at this whitespace position then t
ake it. |
707 // If we break only after white-space, consider the current characte
r | 704 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
708 // as candidate width for this line. | 705 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa
ces, hyphenated, charWidth, hyphenWidth, betweenWords, midWordBreak, breakAll, p
reviousCharacterIsSpace, lastWidthMeasurement, layoutText, font, applyWordSpacin
g, wordSpacing)) |
709 bool lineWasTooWide = false; | 706 return false; |
710 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentSt
yle->breakOnlyAfterWhiteSpace() && !midWordBreak) { | |
711 float charWidth = textWidth(layoutText, m_current.offset(), 1, f
ont, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFont
s, &wordMeasurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0); | |
712 // Check if line is too big even without the extra space | |
713 // at the end of the line. If it is not, do nothing. | |
714 // If the line needs the extra whitespace to be too long, | |
715 // then move the line break to the space and skip all | |
716 // additional whitespace. | |
717 if (!m_width.fitsOnLine(charWidth)) { | |
718 lineWasTooWide = true; | |
719 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m
_current.nextBreakablePosition()); | |
720 skipTrailingWhitespace(m_lineBreak, m_lineInfo); | |
721 } | |
722 } | |
723 if (lineWasTooWide || !m_width.fitsOnLine()) { | |
724 if (m_lineBreak.atTextParagraphSeparator()) { | |
725 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | |
726 m_lineMidpointState.ensureCharacterGetsLineBox(m_current
); | |
727 m_lineBreak.increment(); | |
728 m_lineInfo.setPreviousLineBrokeCleanly(true); | |
729 wordMeasurement.endOffset = m_lineBreak.offset(); | |
730 } | |
731 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.
object().isText() && LineLayoutText(m_lineBreak.object()).textLength() && LineLa
youtText(m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == softHyph
enCharacter) | |
732 hyphenated = true; | |
733 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wo
rdMeasurement.endOffset && !wordMeasurement.width) { | |
734 if (charWidth) { | |
735 wordMeasurement.endOffset = m_lineBreak.offset(); | |
736 wordMeasurement.width = charWidth; | |
737 } | |
738 } | |
739 // Didn't fit. Jump to the end unless there's still an opportuni
ty to collapse whitespace. | |
740 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentChara
cterIsSpace || !previousCharacterIsSpace) { | |
741 m_atEnd = true; | |
742 return false; | |
743 } | |
744 } else { | |
745 if (!betweenWords || (midWordBreak && !m_autoWrap) || (breakAll
&& !m_currentCharacterIsSpace)) | |
746 m_width.addUncommittedWidth(-lastWidthMeasurement); | |
747 if (hyphenWidth) { | |
748 // Subtract the width of the soft hyphen out since we fit on
a line. | |
749 m_width.addUncommittedWidth(-hyphenWidth); | |
750 hyphenWidth = 0; | |
751 } | |
752 } | |
753 } | |
754 | 707 |
| 708 // If there is a hard-break available at this whitespace position then t
ake it. |
755 if (c == newlineCharacter && m_preservesNewline) { | 709 if (c == newlineCharacter && m_preservesNewline) { |
756 if (!stoppedIgnoringSpaces && m_current.offset()) | 710 if (!stoppedIgnoringSpaces && m_current.offset()) |
757 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 711 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
758 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); | 712 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
759 m_lineBreak.increment(); | 713 m_lineBreak.increment(); |
760 m_lineInfo.setPreviousLineBrokeCleanly(true); | 714 m_lineInfo.setPreviousLineBrokeCleanly(true); |
761 return true; | 715 return true; |
762 } | 716 } |
763 | 717 |
| 718 // Auto-wrapping text should not wrap in the middle of a word once it ha
s had an |
| 719 // opportunity to break after a word. |
764 if (m_autoWrap && betweenWords) { | 720 if (m_autoWrap && betweenWords) { |
765 m_width.commit(); | 721 m_width.commit(); |
766 widthFromLastBreakingOpportunity = 0; | 722 widthFromLastBreakingOpportunity = 0; |
767 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); | 723 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
768 // Auto-wrapping text should not wrap in the middle of a word once i
t has had an | |
769 // opportunity to break after a word. | |
770 breakWords = false; | 724 breakWords = false; |
771 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; | 725 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; |
772 } | 726 } |
773 | 727 |
| 728 // Remember this as a breakable position in case adding the end width fo
rces a break. |
774 if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (W
TF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark
_SpacingCombining))) { | 729 if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (W
TF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark
_SpacingCombining))) { |
775 // Remember this as a breakable position in case | |
776 // adding the end width forces a break. | |
777 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); | 730 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
778 midWordBreak &= (breakWords || breakAll); | 731 midWordBreak &= (breakWords || breakAll); |
779 } | 732 } |
780 | 733 |
781 if (betweenWords) { | 734 if (betweenWords) { |
782 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | 735 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
783 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement
.width) ? wordSpacing : 0; | 736 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement
.width) ? wordSpacing : 0; |
784 lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.offse
t() : lastSpace; | 737 lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.offse
t() : lastSpace; |
785 } | 738 } |
786 | 739 |
| 740 // If we encounter a newline, or if we encounter a second space, we need
to go ahead and break up |
| 741 // this run and enter a mode where we start collapsing spaces. |
787 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { | 742 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { |
788 // If we encounter a newline, or if we encounter a | |
789 // second space, we need to go ahead and break up this | |
790 // run and enter a mode where we start collapsing spaces. | |
791 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { | 743 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { |
792 m_ignoringSpaces = true; | 744 m_ignoringSpaces = true; |
793 | 745 |
794 // We just entered a mode where we are ignoring | 746 // We just entered a mode where we are ignoring spaces. Create a
midpoint to terminate the run |
795 // spaces. Create a midpoint to terminate the run | |
796 // before the second space. | 747 // before the second space. |
797 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces); | 748 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces); |
798 m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpoi
ntState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); | 749 m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpoi
ntState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); |
799 } | 750 } |
800 } | 751 } |
801 | 752 |
802 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCharact
erIsSpace, previousCharacterShouldCollapseIfPreWap); | 753 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCharact
erIsSpace, previousCharacterShouldCollapseIfPreWap); |
803 m_atStart = false; | 754 m_atStart = false; |
804 nextCharacter(c, lastCharacter, secondToLastCharacter); | 755 nextCharacter(c, lastCharacter, secondToLastCharacter); |
805 } | 756 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) | 813 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) |
863 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); | 814 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
864 } | 815 } |
865 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces) | 816 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces) |
866 m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.object(
))); | 817 m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.object(
))); |
867 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace
) | 818 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace
) |
868 m_trailingObjects.clear(); | 819 m_trailingObjects.clear(); |
869 } | 820 } |
870 | 821 |
871 | 822 |
| 823 inline void BreakingContext::stopIgnoringSpaces(unsigned& lastSpace) |
| 824 { |
| 825 m_ignoringSpaces = false; |
| 826 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of t
he ignored spaces. |
| 827 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(),
m_current.offset())); |
| 828 } |
| 829 |
| 830 inline WordMeasurement& BreakingContext::calculateWordWidth(WordMeasurements& wo
rdMeasurements, LineLayoutText& layoutText, unsigned lastSpace, float& lastWidth
Measurement, float wordSpacingForWordMeasurement, const Font& font, float wordTr
ailingSpaceWidth, UChar c) |
| 831 { |
| 832 wordMeasurements.grow(wordMeasurements.size() + 1); |
| 833 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
| 834 wordMeasurement.layoutText = layoutText; |
| 835 wordMeasurement.endOffset = m_current.offset(); |
| 836 wordMeasurement.startOffset = lastSpace; |
| 837 |
| 838 if (wordTrailingSpaceWidth && c == spaceCharacter) |
| 839 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset
() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMea
surement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpaceWidth; |
| 840 else |
| 841 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset
() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasure
ment.fallbackFonts, &wordMeasurement.glyphBounds); |
| 842 |
| 843 wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMeasurement
; |
| 844 wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0); |
| 845 return wordMeasurement; |
| 846 } |
| 847 |
| 848 inline bool BreakingContext::trailingSpaceExceedsAvailableWidth(bool midWordBrea
k, const LineLayoutText& layoutText, WordMeasurement& wordMeasurement, bool appl
yWordSpacing, bool wordSpacing, const Font& font) |
| 849 { |
| 850 // If we break only after white-space, consider the current character |
| 851 // as candidate width for this line. |
| 852 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentStyle->bre
akOnlyAfterWhiteSpace() && !midWordBreak) { |
| 853 float charWidth = textWidth(layoutText, m_current.offset(), 1, font, m_w
idth.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &word
Measurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0); |
| 854 // Check if line is too big even without the extra space |
| 855 // at the end of the line. If it is not, do nothing. |
| 856 // If the line needs the extra whitespace to be too long, |
| 857 // then move the line break to the space and skip all |
| 858 // additional whitespace. |
| 859 if (!m_width.fitsOnLine(charWidth)) { |
| 860 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
| 861 skipTrailingWhitespace(m_lineBreak, m_lineInfo); |
| 862 return true; |
| 863 } |
| 864 } |
| 865 return false; |
| 866 } |
| 867 |
| 868 inline bool BreakingContext::canBreakAtWhitespace(bool breakWords, WordMeasureme
nt& wordMeasurement, bool stoppedIgnoringSpaces, bool& hyphenated, float charWid
th, float& hyphenWidth, bool betweenWords, bool midWordBreak, bool breakAll, boo
l previousCharacterIsSpace, float lastWidthMeasurement, const LineLayoutText& la
youtText, const Font& font, bool applyWordSpacing, float wordSpacing) |
| 869 { |
| 870 if (!m_autoWrap && !breakWords) |
| 871 return false; |
| 872 |
| 873 // If we break only after white-space, consider the current character |
| 874 // as candidate width for this line. |
| 875 if (trailingSpaceExceedsAvailableWidth(midWordBreak, layoutText, wordMeasure
ment, applyWordSpacing, wordSpacing, font) || !m_width.fitsOnLine()) { |
| 876 if (m_lineBreak.atTextParagraphSeparator()) { |
| 877 if (!stoppedIgnoringSpaces && m_current.offset() > 0) |
| 878 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
| 879 m_lineBreak.increment(); |
| 880 m_lineInfo.setPreviousLineBrokeCleanly(true); |
| 881 wordMeasurement.endOffset = m_lineBreak.offset(); |
| 882 } |
| 883 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.object()
.isText() && LineLayoutText(m_lineBreak.object()).textLength() && LineLayoutText
(m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == softHyphenCharac
ter) |
| 884 hyphenated = true; |
| 885 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasur
ement.endOffset && !wordMeasurement.width) { |
| 886 if (charWidth) { |
| 887 wordMeasurement.endOffset = m_lineBreak.offset(); |
| 888 wordMeasurement.width = charWidth; |
| 889 } |
| 890 } |
| 891 // Didn't fit. Jump to the end unless there's still an opportunity to co
llapse whitespace. |
| 892 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSp
ace || !previousCharacterIsSpace) { |
| 893 m_atEnd = true; |
| 894 return true; |
| 895 } |
| 896 } else { |
| 897 if (!betweenWords || (midWordBreak && !m_autoWrap) || (breakAll && !m_cu
rrentCharacterIsSpace)) |
| 898 m_width.addUncommittedWidth(-lastWidthMeasurement); |
| 899 if (hyphenWidth) { |
| 900 // Subtract the width of the soft hyphen out since we fit on a line. |
| 901 m_width.addUncommittedWidth(-hyphenWidth); |
| 902 hyphenWidth = 0; |
| 903 } |
| 904 } |
| 905 return false; |
| 906 } |
| 907 |
872 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() | 908 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() |
873 { | 909 { |
874 bool checkForBreak = m_autoWrap; | 910 bool checkForBreak = m_autoWrap; |
875 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object(
) && m_currWS == NOWRAP) { | 911 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object(
) && m_currWS == NOWRAP) { |
876 checkForBreak = true; | 912 checkForBreak = true; |
877 } else if (m_nextObject && m_current.object().isText() && m_nextObject.isTex
t() && !m_nextObject.isBR() && (m_autoWrap || m_nextObject.style()->autoWrap()))
{ | 913 } else if (m_nextObject && m_current.object().isText() && m_nextObject.isTex
t() && !m_nextObject.isBR() && (m_autoWrap || m_nextObject.style()->autoWrap()))
{ |
878 if (m_autoWrap && m_currentCharacterIsSpace) { | 914 if (m_autoWrap && m_currentCharacterIsSpace) { |
879 checkForBreak = true; | 915 checkForBreak = true; |
880 } else { | 916 } else { |
881 LineLayoutText nextText(m_nextObject); | 917 LineLayoutText nextText(m_nextObject); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 | 980 |
945 if (style.textIndentType() == TextIndentHanging) | 981 if (style.textIndentType() == TextIndentHanging) |
946 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In
dentText; | 982 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In
dentText; |
947 | 983 |
948 return shouldIndentText; | 984 return shouldIndentText; |
949 } | 985 } |
950 | 986 |
951 } | 987 } |
952 | 988 |
953 #endif // BreakingContextInlineHeaders_h | 989 #endif // BreakingContextInlineHeaders_h |
OLD | NEW |