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 22 matching lines...) Expand all Loading... | |
33 #include "core/layout/api/LineLayoutTextCombine.h" | 33 #include "core/layout/api/LineLayoutTextCombine.h" |
34 #include "core/layout/line/InlineIterator.h" | 34 #include "core/layout/line/InlineIterator.h" |
35 #include "core/layout/line/InlineTextBox.h" | 35 #include "core/layout/line/InlineTextBox.h" |
36 #include "core/layout/line/LayoutTextInfo.h" | 36 #include "core/layout/line/LayoutTextInfo.h" |
37 #include "core/layout/line/LineBreaker.h" | 37 #include "core/layout/line/LineBreaker.h" |
38 #include "core/layout/line/LineInfo.h" | 38 #include "core/layout/line/LineInfo.h" |
39 #include "core/layout/line/LineWidth.h" | 39 #include "core/layout/line/LineWidth.h" |
40 #include "core/layout/line/TrailingObjects.h" | 40 #include "core/layout/line/TrailingObjects.h" |
41 #include "core/layout/line/WordMeasurement.h" | 41 #include "core/layout/line/WordMeasurement.h" |
42 #include "core/paint/PaintLayer.h" | 42 #include "core/paint/PaintLayer.h" |
43 #include "platform/text/Hyphenation.h" | |
43 #include "platform/text/TextBreakIterator.h" | 44 #include "platform/text/TextBreakIterator.h" |
44 #include "wtf/Allocator.h" | 45 #include "wtf/Allocator.h" |
45 #include "wtf/Vector.h" | 46 #include "wtf/Vector.h" |
46 | 47 |
47 namespace blink { | 48 namespace blink { |
48 | 49 |
49 // We don't let our line box tree for a single line get any deeper than this. | 50 // We don't let our line box tree for a single line get any deeper than this. |
50 const unsigned cMaxLineDepth = 200; | 51 const unsigned cMaxLineDepth = 200; |
51 | 52 |
52 class BreakingContext { | 53 class BreakingContext { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 | 93 |
93 void increment(); | 94 void increment(); |
94 | 95 |
95 void handleBR(EClear&); | 96 void handleBR(EClear&); |
96 void handleOutOfFlowPositioned(Vector<LineLayoutBox>& positionedObjects); | 97 void handleOutOfFlowPositioned(Vector<LineLayoutBox>& positionedObjects); |
97 void handleFloat(); | 98 void handleFloat(); |
98 void handleEmptyInline(); | 99 void handleEmptyInline(); |
99 void handleReplaced(); | 100 void handleReplaced(); |
100 bool handleText(WordMeasurements&, bool& hyphenated); | 101 bool handleText(WordMeasurements&, bool& hyphenated); |
101 void prepareForNextCharacter(const LineLayoutText&, bool& prohibitBreakInsid e, bool previousCharacterIsSpace); | 102 void prepareForNextCharacter(const LineLayoutText&, bool& prohibitBreakInsid e, bool previousCharacterIsSpace); |
102 bool canBreakAtWhitespace(bool breakWords, WordMeasurement&, bool stoppedIgn oringSpaces, bool& hyphenated, float charWidth, float& hyphenWidth, bool between Words, bool midWordBreak, bool canBreakMidWord, bool previousCharacterIsSpace, f loat lastWidthMeasurement, const LineLayoutText&, const Font&, bool applyWordSpa cing, float wordSpacing); | 103 bool canBreakAtWhitespace(bool breakWords, WordMeasurement&, bool stoppedIgn oringSpaces, float charWidth, bool& hyphenated, bool disableSoftHyphen, float& h yphenWidth, bool betweenWords, bool midWordBreak, bool canBreakMidWord, bool pre viousCharacterIsSpace, float lastWidthMeasurement, const LineLayoutText&, const Font&, bool applyWordSpacing, float wordSpacing); |
103 bool trailingSpaceExceedsAvailableWidth(bool canBreakMidWord, const LineLayo utText&, WordMeasurement&, bool applyWordSpacing, bool wordSpacing, const Font&) ; | 104 bool trailingSpaceExceedsAvailableWidth(bool canBreakMidWord, const LineLayo utText&, WordMeasurement&, bool applyWordSpacing, bool wordSpacing, const Font&) ; |
104 WordMeasurement& calculateWordWidth(WordMeasurements&, LineLayoutText&, unsi gned lastSpace, float& lastWidthMeasurement, float wordSpacingForWordMeasurement , const Font&, float wordTrailingSpaceWidth, UChar); | 105 WordMeasurement& calculateWordWidth(WordMeasurements&, LineLayoutText&, unsi gned lastSpace, float& lastWidthMeasurement, float wordSpacingForWordMeasurement , const Font&, float wordTrailingSpaceWidth, UChar); |
105 void stopIgnoringSpaces(unsigned& lastSpace); | 106 void stopIgnoringSpaces(unsigned& lastSpace); |
106 void commitAndUpdateLineBreakIfNeeded(); | 107 void commitAndUpdateLineBreakIfNeeded(); |
107 InlineIterator handleEndOfLine(); | 108 InlineIterator handleEndOfLine(); |
108 | 109 |
109 void clearLineBreakIfFitsOnLine() | 110 void clearLineBreakIfFitsOnLine() |
110 { | 111 { |
111 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) | 112 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) |
112 m_lineBreak.clear(); | 113 m_lineBreak.clear(); |
113 } | 114 } |
114 | 115 |
115 private: | 116 private: |
116 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); | 117 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); |
117 bool rewindToMidWordBreak(WordMeasurement&, int end, float width); | 118 bool rewindToMidWordBreak(WordMeasurement&, int end, float width); |
118 bool rewindToFirstMidWordBreak(LineLayoutText, const ComputedStyle&, const F ont&, bool breakAll, WordMeasurement&); | 119 bool rewindToFirstMidWordBreak(LineLayoutText, const ComputedStyle&, const F ont&, bool breakAll, WordMeasurement&); |
119 bool rewindToMidWordBreak(LineLayoutText, const ComputedStyle&, const Font&, bool breakAll, WordMeasurement&); | 120 bool rewindToMidWordBreak(LineLayoutText, const ComputedStyle&, const Font&, bool breakAll, WordMeasurement&); |
121 bool hyphenate(LineLayoutText, const ComputedStyle&, const Font&, const Hyph enation&, float lastSpaceWordSpacing, WordMeasurement&); | |
120 | 122 |
121 InlineBidiResolver& m_resolver; | 123 InlineBidiResolver& m_resolver; |
122 | 124 |
123 InlineIterator m_current; | 125 InlineIterator m_current; |
124 InlineIterator m_lineBreak; | 126 InlineIterator m_lineBreak; |
125 InlineIterator m_startOfIgnoredSpaces; | 127 InlineIterator m_startOfIgnoredSpaces; |
126 | 128 |
127 LineLayoutBlockFlow m_block; | 129 LineLayoutBlockFlow m_block; |
128 LineLayoutItem m_lastObject; | 130 LineLayoutItem m_lastObject; |
129 LineLayoutItem m_nextObject; | 131 LineLayoutItem m_nextObject; |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 lastBreakablePosition = nextBreakablePosition; | 555 lastBreakablePosition = nextBreakablePosition; |
554 } | 556 } |
555 } | 557 } |
556 | 558 |
557 ALWAYS_INLINE bool BreakingContext::rewindToMidWordBreak( | 559 ALWAYS_INLINE bool BreakingContext::rewindToMidWordBreak( |
558 WordMeasurement& wordMeasurement, int end, float width) | 560 WordMeasurement& wordMeasurement, int end, float width) |
559 { | 561 { |
560 wordMeasurement.endOffset = end; | 562 wordMeasurement.endOffset = end; |
561 wordMeasurement.width = width; | 563 wordMeasurement.width = width; |
562 | 564 |
563 m_current.moveTo(m_current.getLineLayoutItem(), end); | 565 m_current.moveTo(m_current.getLineLayoutItem(), end, m_current.nextBreakable Position()); |
564 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset()); | 566 m_lineBreak.moveTo(m_current.getLineLayoutItem(), end, m_current.nextBreakab lePosition()); |
565 return true; | 567 return true; |
566 } | 568 } |
567 | 569 |
568 ALWAYS_INLINE bool BreakingContext::rewindToFirstMidWordBreak(LineLayoutText tex t, | 570 ALWAYS_INLINE bool BreakingContext::rewindToFirstMidWordBreak(LineLayoutText tex t, |
569 const ComputedStyle& style, const Font& font, bool breakAll, | 571 const ComputedStyle& style, const Font& font, bool breakAll, |
570 WordMeasurement& wordMeasurement) | 572 WordMeasurement& wordMeasurement) |
571 { | 573 { |
572 int start = wordMeasurement.startOffset; | 574 int start = wordMeasurement.startOffset; |
573 int end; | 575 int end; |
574 if (breakAll) { | 576 if (breakAll) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
615 end = lastBreakablePositionForBreakAll(text, style, start, end); | 617 end = lastBreakablePositionForBreakAll(text, style, start, end); |
616 if (!end) | 618 if (!end) |
617 return false; | 619 return false; |
618 len = end - start; | 620 len = end - start; |
619 } | 621 } |
620 FloatRect rect = font.selectionRectForText(run, FloatPoint(), 0, 0, len); | 622 FloatRect rect = font.selectionRectForText(run, FloatPoint(), 0, 0, len); |
621 DCHECK(m_width.fitsOnLine(rect.width() - 1)); // avoid failure when rect is rounded up. | 623 DCHECK(m_width.fitsOnLine(rect.width() - 1)); // avoid failure when rect is rounded up. |
622 return rewindToMidWordBreak(wordMeasurement, end, rect.width()); | 624 return rewindToMidWordBreak(wordMeasurement, end, rect.width()); |
623 } | 625 } |
624 | 626 |
627 ALWAYS_INLINE bool BreakingContext::hyphenate(LineLayoutText text, | |
628 const ComputedStyle& style, const Font& font, | |
629 const Hyphenation& hyphenation, float lastSpaceWordSpacing, | |
630 WordMeasurement& wordMeasurement) | |
631 { | |
632 const unsigned minimumPrefixLength = 2; | |
633 const unsigned minimumSuffixLength = 2; | |
634 unsigned start = wordMeasurement.startOffset; | |
635 unsigned len = wordMeasurement.endOffset - start; | |
636 if (len <= minimumSuffixLength) | |
637 return false; | |
638 | |
639 float hyphenWidth = text.hyphenWidth(font, textDirectionFromUnicode(m_resolv er.position().direction())); | |
640 float maxPrefixWidth = m_width.availableWidth() + LayoutUnit::epsilon() | |
eae
2016/05/16 16:43:26
Do we need epsilon here? If we can ceil a floor to
kojii
2016/05/16 17:29:34
When tests use ch/em that should exactly fit, this
eae
2016/05/16 17:32:38
Thanks. We're trying to remove epsilon from LineWi
| |
641 - m_width.currentWidth() - hyphenWidth - lastSpaceWordSpacing; | |
642 | |
643 // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely | |
644 // that an hyphenation opportunity exists, so do not bother to look for it. | |
645 const int minPrefixWidthNumerator = 5; | |
eae
2016/05/16 16:43:25
Where did you get these numbers from?
kojii
2016/05/16 17:29:34
From our removal patch (crrev.com/20526006). ToT W
eae
2016/05/16 17:32:38
Ok, could you add a quick comment explaining the n
| |
646 const int minPrefixWidthDenominator = 4; | |
647 if (maxPrefixWidth <= font.getFontDescription().computedSize() * minPrefixWi dthNumerator / minPrefixWidthDenominator) | |
648 return false; | |
649 | |
650 TextRun run = constructTextRun(font, text, start, len, style); | |
651 run.setTabSize(!m_collapseWhiteSpace, style.getTabSize()); | |
652 run.setXPos(m_width.currentWidth()); | |
653 unsigned maxPrefixLength = font.offsetForPosition(run, maxPrefixWidth, false ); | |
654 if (maxPrefixLength < minimumPrefixLength) | |
655 return false; | |
656 | |
657 unsigned prefixLength = hyphenation.lastHyphenLocation( | |
658 text.text().createView(start, len), | |
659 std::min(maxPrefixLength, len - minimumSuffixLength) + 1); | |
660 if (!prefixLength || prefixLength < minimumPrefixLength) | |
661 return false; | |
662 | |
663 FloatRect rect = font.selectionRectForText(run, FloatPoint(), 0, 0, prefixLe ngth); | |
eae
2016/05/16 16:43:25
Calling shaper.getCharacterRange instead of select
kojii
2016/05/16 17:29:34
Done.
eae
2016/05/16 17:32:38
Thanks!`
| |
664 return rewindToMidWordBreak(wordMeasurement, start + prefixLength, rect.widt h()); | |
665 } | |
666 | |
625 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool & hyphenated) | 667 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool & hyphenated) |
626 { | 668 { |
627 if (!m_current.offset()) | 669 if (!m_current.offset()) |
628 m_appliedStartWidth = false; | 670 m_appliedStartWidth = false; |
629 | 671 |
630 LineLayoutText layoutText(m_current.getLineLayoutItem()); | 672 LineLayoutText layoutText(m_current.getLineLayoutItem()); |
631 | 673 |
632 // If we have left a no-wrap inline and entered an autowrap inline while ign oring spaces | 674 // If we have left a no-wrap inline and entered an autowrap inline while ign oring spaces |
633 // then we need to mark the start of the autowrap inline as a potential line break now. | 675 // then we need to mark the start of the autowrap inline as a potential line break now. |
634 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { | 676 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { |
(...skipping 18 matching lines...) Expand all Loading... | |
653 bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWr ap; | 695 bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWr ap; |
654 bool keepAll = m_currentStyle->wordBreak() == KeepAllWordBreak && m_autoWrap ; | 696 bool keepAll = m_currentStyle->wordBreak() == KeepAllWordBreak && m_autoWrap ; |
655 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is CombineText() && LineLayoutTextCombine(layoutText).isCombined(); | 697 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is CombineText() && LineLayoutTextCombine(layoutText).isCombined(); |
656 | 698 |
657 // This is currently only used for word-break: break-all, specifically for t he case | 699 // This is currently only used for word-break: break-all, specifically for t he case |
658 // where we have a break opportunity within a word, then a string of non-bre akable | 700 // where we have a break opportunity within a word, then a string of non-bre akable |
659 // content that ends up making our word wider than the current line. | 701 // content that ends up making our word wider than the current line. |
660 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html | 702 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html |
661 float widthMeasurementAtLastBreakOpportunity = 0; | 703 float widthMeasurementAtLastBreakOpportunity = 0; |
662 | 704 |
705 Hyphenation* hyphenation = style.getHyphens() == HyphensAuto | |
706 ? Hyphenation::get(font.getFontDescription().locale()) : nullptr; | |
707 bool disableSoftHyphen = style.getHyphens() == HyphensNone; | |
663 float hyphenWidth = 0; | 708 float hyphenWidth = 0; |
664 | 709 |
665 if (layoutText.isSVGInlineText()) { | 710 if (layoutText.isSVGInlineText()) { |
666 breakWords = false; | 711 breakWords = false; |
667 breakAll = false; | 712 breakAll = false; |
668 keepAll = false; | 713 keepAll = false; |
669 } | 714 } |
670 | 715 |
671 // Use LineBreakType::Normal for break-all. When a word does not fit, | 716 // Use LineBreakType::Normal for break-all. When a word does not fit, |
672 // rewindToMidWordBreak() finds the mid-word break point. | 717 // rewindToMidWordBreak() finds the mid-word break point. |
(...skipping 25 matching lines...) Expand all Loading... | |
698 for (; m_current.offset() < layoutText.textLength(); m_current.fastIncrement InTextNode()) { | 743 for (; m_current.offset() < layoutText.textLength(); m_current.fastIncrement InTextNode()) { |
699 bool previousCharacterIsSpace = m_currentCharacterIsSpace; | 744 bool previousCharacterIsSpace = m_currentCharacterIsSpace; |
700 UChar c = m_current.current(); | 745 UChar c = m_current.current(); |
701 m_currentCharacterIsSpace = c == spaceCharacter || c == tabulationCharac ter || (!m_preservesNewline && (c == newlineCharacter)); | 746 m_currentCharacterIsSpace = c == spaceCharacter || c == tabulationCharac ter || (!m_preservesNewline && (c == newlineCharacter)); |
702 | 747 |
703 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) { | 748 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) { |
704 m_lineInfo.setEmpty(false); | 749 m_lineInfo.setEmpty(false); |
705 m_width.setTrailingWhitespaceWidth(0); | 750 m_width.setTrailingWhitespaceWidth(0); |
706 } | 751 } |
707 | 752 |
708 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth) { | 753 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth && !disableSo ftHyphen) { |
709 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); | 754 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); |
710 m_width.addUncommittedWidth(hyphenWidth); | 755 m_width.addUncommittedWidth(hyphenWidth); |
711 } | 756 } |
712 | 757 |
713 bool applyWordSpacing = false; | 758 bool applyWordSpacing = false; |
714 | 759 |
715 // Determine if we should try breaking in the middle of a word. | 760 // Determine if we should try breaking in the middle of a word. |
716 if (breakWords && !midWordBreak && !U16_IS_TRAIL(c)) { | 761 if (breakWords && !midWordBreak && !U16_IS_TRAIL(c)) { |
717 widthFromLastBreakingOpportunity += charWidth; | 762 widthFromLastBreakingOpportunity += charWidth; |
718 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current .offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar acterAt(m_current.offset() + 1)); | 763 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current .offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar acterAt(m_current.offset() + 1)); |
719 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak ingOpportunity, m_collapseWhiteSpace); | 764 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak ingOpportunity, m_collapseWhiteSpace); |
720 // Measure up to 2em overflow since ligatures/kerning can shorten | 765 // Measure up to 2em overflow since ligatures/kerning can shorten |
721 // the width as we add more characters. rewindToMidWordBreak() can | 766 // the width as we add more characters. rewindToMidWordBreak() can |
722 // measure the accurate mid-word break point then. | 767 // measure the accurate mid-word break point then. |
723 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor tunity + charWidth > m_width.availableWidth() | 768 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor tunity + charWidth > m_width.availableWidth() |
724 + 2 * font.getFontDescription().computedSize(); | 769 + 2 * font.getFontDescription().computedSize(); |
725 } | 770 } |
726 | 771 |
727 // Determine if we are in the whitespace between words. | 772 // Determine if we are in the whitespace between words. |
728 int nextBreakablePosition = m_current.nextBreakablePosition(); | 773 int nextBreakablePosition = m_current.nextBreakablePosition(); |
729 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next BreakablePosition, lineBreakType)); | 774 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next BreakablePosition, lineBreakType) |
775 && (!disableSoftHyphen || m_current.previousInSameNode() != softHyph enCharacter)); | |
730 m_current.setNextBreakablePosition(nextBreakablePosition); | 776 m_current.setNextBreakablePosition(nextBreakablePosition); |
731 | 777 |
732 // 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. | 778 // 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. |
733 if (!betweenWords && !midWordBreak) { | 779 if (!betweenWords && !midWordBreak) { |
734 if (m_ignoringSpaces) { | 780 if (m_ignoringSpaces) { |
735 // Stop ignoring spaces and begin at this | 781 // Stop ignoring spaces and begin at this |
736 // new point. | 782 // new point. |
737 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | 783 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
738 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure ments.last().width) ? wordSpacing : 0; | 784 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure ments.last().width) ? wordSpacing : 0; |
739 stopIgnoringSpaces(lastSpace); | 785 stopIgnoringSpaces(lastSpace); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 if (!m_appliedStartWidth) { | 827 if (!m_appliedStartWidth) { |
782 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.getLineLayoutItem(), true, false).toFloat()); | 828 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.getLineLayoutItem(), true, false).toFloat()); |
783 m_appliedStartWidth = true; | 829 m_appliedStartWidth = true; |
784 } | 830 } |
785 | 831 |
786 // If we haven't hit a breakable position yet and already don't fit on t he line try to move below any floats. | 832 // If we haven't hit a breakable position yet and already don't fit on t he line try to move below any floats. |
787 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) | 833 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) |
788 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 834 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
789 | 835 |
790 midWordBreak = false; | 836 midWordBreak = false; |
791 if (canBreakMidWord && !m_width.fitsOnLine()) { | 837 if (!m_width.fitsOnLine()) { |
792 m_width.addUncommittedWidth(-wordMeasurement.width); | 838 if (canBreakMidWord) { |
793 if (rewindToMidWordBreak(layoutText, style, font, breakAll, wordMeas urement)) { | 839 m_width.addUncommittedWidth(-wordMeasurement.width); |
794 lastWidthMeasurement = wordMeasurement.width + lastSpaceWordSpac ing; | 840 if (rewindToMidWordBreak(layoutText, style, font, breakAll, word Measurement)) { |
795 midWordBreak = true; | 841 lastWidthMeasurement = wordMeasurement.width + lastSpaceWord Spacing; |
842 midWordBreak = true; | |
843 } | |
844 m_width.addUncommittedWidth(wordMeasurement.width); | |
845 } else if (hyphenation) { | |
846 m_width.addUncommittedWidth(-wordMeasurement.width); | |
847 DCHECK(lastSpace == static_cast<unsigned>(wordMeasurement.startO ffset)); | |
848 DCHECK(m_current.offset() == static_cast<unsigned>(wordMeasureme nt.endOffset)); | |
849 if (hyphenate(layoutText, style, font, *hyphenation, lastSpaceWo rdSpacing, wordMeasurement)) { | |
850 m_width.addUncommittedWidth(wordMeasurement.width); | |
851 hyphenated = true; | |
852 m_atEnd = true; | |
853 return false; | |
854 } | |
855 m_width.addUncommittedWidth(wordMeasurement.width); | |
796 } | 856 } |
797 m_width.addUncommittedWidth(wordMeasurement.width); | |
798 } | 857 } |
799 | 858 |
800 // If there is a soft-break available at this whitespace position then t ake it. | 859 // If there is a soft-break available at this whitespace position then t ake it. |
801 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; | 860 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
802 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa ces, hyphenated, charWidth, hyphenWidth, betweenWords, midWordBreak, canBreakMid Word, previousCharacterIsSpace, lastWidthMeasurement, layoutText, font, applyWor dSpacing, wordSpacing)) | 861 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa ces, charWidth, hyphenated, disableSoftHyphen, hyphenWidth, betweenWords, midWor dBreak, canBreakMidWord, previousCharacterIsSpace, lastWidthMeasurement, layoutT ext, font, applyWordSpacing, wordSpacing)) |
803 return false; | 862 return false; |
804 | 863 |
805 // If there is a hard-break available at this whitespace position then t ake it. | 864 // If there is a hard-break available at this whitespace position then t ake it. |
806 if (c == newlineCharacter && m_preservesNewline) { | 865 if (c == newlineCharacter && m_preservesNewline) { |
807 if (!stoppedIgnoringSpaces && m_current.offset()) | 866 if (!stoppedIgnoringSpaces && m_current.offset()) |
808 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 867 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
809 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); | 868 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); |
810 m_lineBreak.increment(); | 869 m_lineBreak.increment(); |
811 m_lineInfo.setPreviousLineBrokeCleanly(true); | 870 m_lineInfo.setPreviousLineBrokeCleanly(true); |
812 return true; | 871 return true; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
875 m_width.addUncommittedWidth(lastWidthMeasurement + additionalWidthFromAncest ors); | 934 m_width.addUncommittedWidth(lastWidthMeasurement + additionalWidthFromAncest ors); |
876 | 935 |
877 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && lastWidthMeasuremen t) | 936 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && lastWidthMeasuremen t) |
878 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement + additionalWidt hFromAncestors); | 937 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement + additionalWidt hFromAncestors); |
879 | 938 |
880 m_includeEndWidth = false; | 939 m_includeEndWidth = false; |
881 | 940 |
882 if (midWordBreak) { | 941 if (midWordBreak) { |
883 m_width.commit(); | 942 m_width.commit(); |
884 m_atEnd = true; | 943 m_atEnd = true; |
885 } else if (!m_width.fitsOnLine() && !hyphenated | 944 } else if (!m_width.fitsOnLine()) { |
886 && m_lineBreak.previousInSameNode() == softHyphenCharacter) { | 945 if (hyphenation && (m_nextObject || m_lineInfo.isEmpty())) { |
887 hyphenated = true; | 946 m_width.addUncommittedWidth(-wordMeasurement.width); |
888 m_atEnd = true; | 947 DCHECK(lastSpace == static_cast<unsigned>(wordMeasurement.startOffse t)); |
948 DCHECK(m_current.offset() == static_cast<unsigned>(wordMeasurement.e ndOffset)); | |
949 if (hyphenate(layoutText, style, font, *hyphenation, lastSpaceWordSp acing, wordMeasurement)) { | |
950 hyphenated = true; | |
951 m_atEnd = true; | |
952 } | |
953 m_width.addUncommittedWidth(wordMeasurement.width); | |
954 } | |
955 if (!hyphenated | |
956 && m_lineBreak.previousInSameNode() == softHyphenCharacter | |
957 && !disableSoftHyphen) { | |
958 hyphenated = true; | |
959 m_atEnd = true; | |
960 } | |
889 } | 961 } |
890 return false; | 962 return false; |
891 } | 963 } |
892 | 964 |
893 inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layou tText, bool& prohibitBreakInside, bool previousCharacterIsSpace) | 965 inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layou tText, bool& prohibitBreakInside, bool previousCharacterIsSpace) |
894 { | 966 { |
895 if (layoutText.isSVGInlineText() && m_current.offset()) { | 967 if (layoutText.isSVGInlineText() && m_current.offset()) { |
896 // Force creation of new InlineBoxes for each absolute positioned charac ter (those that start new text chunks). | 968 // Force creation of new InlineBoxes for each absolute positioned charac ter (those that start new text chunks). |
897 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_cu rrent.offset())) | 969 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_cu rrent.offset())) |
898 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 970 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
954 // additional whitespace. | 1026 // additional whitespace. |
955 if (!m_width.fitsOnLine(charWidth)) { | 1027 if (!m_width.fitsOnLine(charWidth)) { |
956 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); | 1028 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); |
957 skipTrailingWhitespace(m_lineBreak, m_lineInfo); | 1029 skipTrailingWhitespace(m_lineBreak, m_lineInfo); |
958 return true; | 1030 return true; |
959 } | 1031 } |
960 } | 1032 } |
961 return false; | 1033 return false; |
962 } | 1034 } |
963 | 1035 |
964 inline bool BreakingContext::canBreakAtWhitespace(bool breakWords, WordMeasureme nt& wordMeasurement, bool stoppedIgnoringSpaces, bool& hyphenated, float charWid th, float& hyphenWidth, bool betweenWords, bool midWordBreak, bool canBreakMidWo rd, bool previousCharacterIsSpace, float lastWidthMeasurement, const LineLayoutT ext& layoutText, const Font& font, bool applyWordSpacing, float wordSpacing) | 1036 inline bool BreakingContext::canBreakAtWhitespace(bool breakWords, WordMeasureme nt& wordMeasurement, bool stoppedIgnoringSpaces, float charWidth, bool& hyphenat ed, bool disableSoftHyphen, float& hyphenWidth, bool betweenWords, bool midWordB reak, bool canBreakMidWord, bool previousCharacterIsSpace, float lastWidthMeasur ement, const LineLayoutText& layoutText, const Font& font, bool applyWordSpacing , float wordSpacing) |
965 { | 1037 { |
966 if (!m_autoWrap && !breakWords) | 1038 if (!m_autoWrap && !breakWords) |
967 return false; | 1039 return false; |
968 | 1040 |
969 // If we break only after white-space, consider the current character | 1041 // If we break only after white-space, consider the current character |
970 // as candidate width for this line. | 1042 // as candidate width for this line. |
971 if (midWordBreak | 1043 if (midWordBreak |
972 || trailingSpaceExceedsAvailableWidth(canBreakMidWord, layoutText, wordM easurement, applyWordSpacing, wordSpacing, font) | 1044 || trailingSpaceExceedsAvailableWidth(canBreakMidWord, layoutText, wordM easurement, applyWordSpacing, wordSpacing, font) |
973 || !m_width.fitsOnLine()) { | 1045 || !m_width.fitsOnLine()) { |
974 if (m_lineBreak.atTextParagraphSeparator()) { | 1046 if (m_lineBreak.atTextParagraphSeparator()) { |
975 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | 1047 if (!stoppedIgnoringSpaces && m_current.offset() > 0) |
976 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 1048 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
977 m_lineBreak.increment(); | 1049 m_lineBreak.increment(); |
978 m_lineInfo.setPreviousLineBrokeCleanly(true); | 1050 m_lineInfo.setPreviousLineBrokeCleanly(true); |
979 wordMeasurement.endOffset = m_lineBreak.offset(); | 1051 wordMeasurement.endOffset = m_lineBreak.offset(); |
980 } | 1052 } |
981 if (m_lineBreak.getLineLayoutItem() && m_lineBreak.offset() && m_lineBre ak.getLineLayoutItem().isText() && LineLayoutText(m_lineBreak.getLineLayoutItem( )).textLength() && LineLayoutText(m_lineBreak.getLineLayoutItem()).characterAt(m _lineBreak.offset() - 1) == softHyphenCharacter) | 1053 if (m_lineBreak.getLineLayoutItem() && m_lineBreak.offset() && m_lineBre ak.getLineLayoutItem().isText() && LineLayoutText(m_lineBreak.getLineLayoutItem( )).textLength() && LineLayoutText(m_lineBreak.getLineLayoutItem()).characterAt(m _lineBreak.offset() - 1) == softHyphenCharacter && !disableSoftHyphen) |
982 hyphenated = true; | 1054 hyphenated = true; |
983 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasur ement.endOffset && !wordMeasurement.width) { | 1055 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasur ement.endOffset && !wordMeasurement.width) { |
984 if (charWidth) { | 1056 if (charWidth) { |
985 wordMeasurement.endOffset = m_lineBreak.offset(); | 1057 wordMeasurement.endOffset = m_lineBreak.offset(); |
986 wordMeasurement.width = charWidth; | 1058 wordMeasurement.width = charWidth; |
987 } | 1059 } |
988 } | 1060 } |
989 // Didn't fit. Jump to the end unless there's still an opportunity to co llapse whitespace. | 1061 // Didn't fit. Jump to the end unless there's still an opportunity to co llapse whitespace. |
990 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSp ace || !previousCharacterIsSpace) { | 1062 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSp ace || !previousCharacterIsSpace) { |
991 m_atEnd = true; | 1063 m_atEnd = true; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1082 | 1154 |
1083 if (style.getTextIndentType() == TextIndentHanging) | 1155 if (style.getTextIndentType() == TextIndentHanging) |
1084 indentText = indentText == IndentText ? DoNotIndentText : IndentText; | 1156 indentText = indentText == IndentText ? DoNotIndentText : IndentText; |
1085 | 1157 |
1086 return indentText; | 1158 return indentText; |
1087 } | 1159 } |
1088 | 1160 |
1089 } // namespace blink | 1161 } // namespace blink |
1090 | 1162 |
1091 #endif // BreakingContextInlineHeaders_h | 1163 #endif // BreakingContextInlineHeaders_h |
OLD | NEW |