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, bool& hyphenated, float charWidth, bool disableSoftHyphen, float& h yphenWidth, bool betweenWords, bool midWordBreak, bool canBreakMidWord, bool pre viousCharacterIsSpace, float lastWidthMeasurement, const LineLayoutText&, const Font&, bool applyWordSpacing, float wordSpacing); |
drott
2016/05/16 08:58:20
Would it make sense to bring all the hyphenation r
kojii
2016/05/16 10:21:53
Done.
| |
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() | |
641 - m_width.currentWidth() - hyphenWidth - lastSpaceWordSpacing; | |
642 | |
643 // If the maximum width available for the prefix before the hyphen is small, | |
644 // then it is very unlikely that an hyphenation opportunity exists, so do | |
645 // not bother to look for it. | |
646 if (maxPrefixWidth <= font.getFontDescription().computedSize() * 5 / 4) | |
drott
2016/05/16 08:58:20
Could you perhaps explain the 5/4 magic number and
kojii
2016/05/16 10:21:53
I guess it's a heuristic value introduced in WebKi
| |
647 return false; | |
648 | |
649 TextRun run = constructTextRun(font, text, start, len, style); | |
650 run.setTabSize(!m_collapseWhiteSpace, style.getTabSize()); | |
651 run.setXPos(m_width.currentWidth()); | |
652 unsigned maxPrefixLength = font.offsetForPosition(run, maxPrefixWidth, false ); | |
653 if (maxPrefixLength < minimumPrefixLength) | |
654 return false; | |
655 | |
656 unsigned prefixLength = hyphenation.lastHyphenLocation( | |
657 text.text().createView(start, len), | |
658 std::min(maxPrefixLength, len - minimumSuffixLength) + 1); | |
659 if (!prefixLength || prefixLength < minimumPrefixLength) | |
660 return false; | |
661 | |
662 FloatRect rect = font.selectionRectForText(run, FloatPoint(), 0, 0, prefixLe ngth); | |
663 return rewindToMidWordBreak(wordMeasurement, start + prefixLength, rect.widt h()); | |
664 } | |
665 | |
625 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool & hyphenated) | 666 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool & hyphenated) |
626 { | 667 { |
627 if (!m_current.offset()) | 668 if (!m_current.offset()) |
628 m_appliedStartWidth = false; | 669 m_appliedStartWidth = false; |
629 | 670 |
630 LineLayoutText layoutText(m_current.getLineLayoutItem()); | 671 LineLayoutText layoutText(m_current.getLineLayoutItem()); |
631 | 672 |
632 // If we have left a no-wrap inline and entered an autowrap inline while ign oring spaces | 673 // 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. | 674 // 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) { | 675 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; | 694 bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWr ap; |
654 bool keepAll = m_currentStyle->wordBreak() == KeepAllWordBreak && m_autoWrap ; | 695 bool keepAll = m_currentStyle->wordBreak() == KeepAllWordBreak && m_autoWrap ; |
655 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is CombineText() && LineLayoutTextCombine(layoutText).isCombined(); | 696 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is CombineText() && LineLayoutTextCombine(layoutText).isCombined(); |
656 | 697 |
657 // This is currently only used for word-break: break-all, specifically for t he case | 698 // 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 | 699 // 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. | 700 // 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 | 701 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html |
661 float widthMeasurementAtLastBreakOpportunity = 0; | 702 float widthMeasurementAtLastBreakOpportunity = 0; |
662 | 703 |
704 Hyphenation* hyphenation = style.getHyphens() == HyphensAuto | |
705 ? Hyphenation::get(font.getFontDescription().locale()) : nullptr; | |
706 bool disableSoftHyphen = style.getHyphens() == HyphensNone; | |
663 float hyphenWidth = 0; | 707 float hyphenWidth = 0; |
664 | 708 |
665 if (layoutText.isSVGInlineText()) { | 709 if (layoutText.isSVGInlineText()) { |
666 breakWords = false; | 710 breakWords = false; |
667 breakAll = false; | 711 breakAll = false; |
668 keepAll = false; | 712 keepAll = false; |
669 } | 713 } |
670 | 714 |
671 // Use LineBreakType::Normal for break-all. When a word does not fit, | 715 // Use LineBreakType::Normal for break-all. When a word does not fit, |
672 // rewindToMidWordBreak() finds the mid-word break point. | 716 // 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()) { | 742 for (; m_current.offset() < layoutText.textLength(); m_current.fastIncrement InTextNode()) { |
699 bool previousCharacterIsSpace = m_currentCharacterIsSpace; | 743 bool previousCharacterIsSpace = m_currentCharacterIsSpace; |
700 UChar c = m_current.current(); | 744 UChar c = m_current.current(); |
701 m_currentCharacterIsSpace = c == spaceCharacter || c == tabulationCharac ter || (!m_preservesNewline && (c == newlineCharacter)); | 745 m_currentCharacterIsSpace = c == spaceCharacter || c == tabulationCharac ter || (!m_preservesNewline && (c == newlineCharacter)); |
702 | 746 |
703 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) { | 747 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) { |
704 m_lineInfo.setEmpty(false); | 748 m_lineInfo.setEmpty(false); |
705 m_width.setTrailingWhitespaceWidth(0); | 749 m_width.setTrailingWhitespaceWidth(0); |
706 } | 750 } |
707 | 751 |
708 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth) { | 752 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth && !disableSo ftHyphen) { |
709 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); | 753 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); |
710 m_width.addUncommittedWidth(hyphenWidth); | 754 m_width.addUncommittedWidth(hyphenWidth); |
711 } | 755 } |
712 | 756 |
713 bool applyWordSpacing = false; | 757 bool applyWordSpacing = false; |
714 | 758 |
715 // Determine if we should try breaking in the middle of a word. | 759 // Determine if we should try breaking in the middle of a word. |
716 if (breakWords && !midWordBreak && !U16_IS_TRAIL(c)) { | 760 if (breakWords && !midWordBreak && !U16_IS_TRAIL(c)) { |
717 widthFromLastBreakingOpportunity += charWidth; | 761 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)); | 762 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); | 763 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 | 764 // Measure up to 2em overflow since ligatures/kerning can shorten |
721 // the width as we add more characters. rewindToMidWordBreak() can | 765 // the width as we add more characters. rewindToMidWordBreak() can |
722 // measure the accurate mid-word break point then. | 766 // measure the accurate mid-word break point then. |
723 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor tunity + charWidth > m_width.availableWidth() | 767 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor tunity + charWidth > m_width.availableWidth() |
724 + 2 * font.getFontDescription().computedSize(); | 768 + 2 * font.getFontDescription().computedSize(); |
725 } | 769 } |
726 | 770 |
727 // Determine if we are in the whitespace between words. | 771 // Determine if we are in the whitespace between words. |
728 int nextBreakablePosition = m_current.nextBreakablePosition(); | 772 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)); | 773 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next BreakablePosition, lineBreakType) |
774 && (!disableSoftHyphen || m_current.previousInSameNode() != softHyph enCharacter)); | |
730 m_current.setNextBreakablePosition(nextBreakablePosition); | 775 m_current.setNextBreakablePosition(nextBreakablePosition); |
731 | 776 |
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. | 777 // 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) { | 778 if (!betweenWords && !midWordBreak) { |
734 if (m_ignoringSpaces) { | 779 if (m_ignoringSpaces) { |
735 // Stop ignoring spaces and begin at this | 780 // Stop ignoring spaces and begin at this |
736 // new point. | 781 // new point. |
737 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | 782 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
738 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure ments.last().width) ? wordSpacing : 0; | 783 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure ments.last().width) ? wordSpacing : 0; |
739 stopIgnoringSpaces(lastSpace); | 784 stopIgnoringSpaces(lastSpace); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 if (!m_appliedStartWidth) { | 826 if (!m_appliedStartWidth) { |
782 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.getLineLayoutItem(), true, false).toFloat()); | 827 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.getLineLayoutItem(), true, false).toFloat()); |
783 m_appliedStartWidth = true; | 828 m_appliedStartWidth = true; |
784 } | 829 } |
785 | 830 |
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. | 831 // 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) | 832 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) |
788 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 833 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
789 | 834 |
790 midWordBreak = false; | 835 midWordBreak = false; |
791 if (canBreakMidWord && !m_width.fitsOnLine()) { | 836 if (!m_width.fitsOnLine()) { |
792 m_width.addUncommittedWidth(-wordMeasurement.width); | 837 if (canBreakMidWord) { |
793 if (rewindToMidWordBreak(layoutText, style, font, breakAll, wordMeas urement)) { | 838 m_width.addUncommittedWidth(-wordMeasurement.width); |
794 lastWidthMeasurement = wordMeasurement.width + lastSpaceWordSpac ing; | 839 if (rewindToMidWordBreak(layoutText, style, font, breakAll, word Measurement)) { |
795 midWordBreak = true; | 840 lastWidthMeasurement = wordMeasurement.width + lastSpaceWord Spacing; |
841 midWordBreak = true; | |
842 } | |
843 m_width.addUncommittedWidth(wordMeasurement.width); | |
844 } else if (hyphenation) { | |
845 m_width.addUncommittedWidth(-wordMeasurement.width); | |
846 DCHECK(lastSpace == static_cast<unsigned>(wordMeasurement.startO ffset)); | |
847 DCHECK(m_current.offset() == static_cast<unsigned>(wordMeasureme nt.endOffset)); | |
848 if (hyphenate(layoutText, style, font, *hyphenation, lastSpaceWo rdSpacing, wordMeasurement)) { | |
849 m_width.addUncommittedWidth(wordMeasurement.width); | |
850 hyphenated = true; | |
851 m_atEnd = true; | |
852 return false; | |
853 } | |
854 m_width.addUncommittedWidth(wordMeasurement.width); | |
796 } | 855 } |
797 m_width.addUncommittedWidth(wordMeasurement.width); | |
798 } | 856 } |
799 | 857 |
800 // If there is a soft-break available at this whitespace position then t ake it. | 858 // If there is a soft-break available at this whitespace position then t ake it. |
801 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; | 859 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)) | 860 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa ces, hyphenated, charWidth, disableSoftHyphen, hyphenWidth, betweenWords, midWor dBreak, canBreakMidWord, previousCharacterIsSpace, lastWidthMeasurement, layoutT ext, font, applyWordSpacing, wordSpacing)) |
803 return false; | 861 return false; |
804 | 862 |
805 // If there is a hard-break available at this whitespace position then t ake it. | 863 // If there is a hard-break available at this whitespace position then t ake it. |
806 if (c == newlineCharacter && m_preservesNewline) { | 864 if (c == newlineCharacter && m_preservesNewline) { |
807 if (!stoppedIgnoringSpaces && m_current.offset()) | 865 if (!stoppedIgnoringSpaces && m_current.offset()) |
808 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 866 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
809 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); | 867 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); |
810 m_lineBreak.increment(); | 868 m_lineBreak.increment(); |
811 m_lineInfo.setPreviousLineBrokeCleanly(true); | 869 m_lineInfo.setPreviousLineBrokeCleanly(true); |
812 return true; | 870 return true; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
875 m_width.addUncommittedWidth(lastWidthMeasurement + additionalWidthFromAncest ors); | 933 m_width.addUncommittedWidth(lastWidthMeasurement + additionalWidthFromAncest ors); |
876 | 934 |
877 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && lastWidthMeasuremen t) | 935 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && lastWidthMeasuremen t) |
878 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement + additionalWidt hFromAncestors); | 936 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement + additionalWidt hFromAncestors); |
879 | 937 |
880 m_includeEndWidth = false; | 938 m_includeEndWidth = false; |
881 | 939 |
882 if (midWordBreak) { | 940 if (midWordBreak) { |
883 m_width.commit(); | 941 m_width.commit(); |
884 m_atEnd = true; | 942 m_atEnd = true; |
885 } else if (!m_width.fitsOnLine() && !hyphenated | 943 } else if (!m_width.fitsOnLine()) { |
886 && m_lineBreak.previousInSameNode() == softHyphenCharacter) { | 944 if (hyphenation && (m_nextObject || m_lineInfo.isEmpty())) { |
887 hyphenated = true; | 945 m_width.addUncommittedWidth(-wordMeasurement.width); |
888 m_atEnd = true; | 946 DCHECK(lastSpace == static_cast<unsigned>(wordMeasurement.startOffse t)); |
947 DCHECK(m_current.offset() == static_cast<unsigned>(wordMeasurement.e ndOffset)); | |
948 if (hyphenate(layoutText, style, font, *hyphenation, lastSpaceWordSp acing, wordMeasurement)) { | |
949 hyphenated = true; | |
950 m_atEnd = true; | |
951 } | |
952 m_width.addUncommittedWidth(wordMeasurement.width); | |
953 } | |
954 if (!hyphenated | |
955 && m_lineBreak.previousInSameNode() == softHyphenCharacter | |
956 && !disableSoftHyphen) { | |
957 hyphenated = true; | |
958 m_atEnd = true; | |
959 } | |
889 } | 960 } |
890 return false; | 961 return false; |
891 } | 962 } |
892 | 963 |
893 inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layou tText, bool& prohibitBreakInside, bool previousCharacterIsSpace) | 964 inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layou tText, bool& prohibitBreakInside, bool previousCharacterIsSpace) |
894 { | 965 { |
895 if (layoutText.isSVGInlineText() && m_current.offset()) { | 966 if (layoutText.isSVGInlineText() && m_current.offset()) { |
896 // Force creation of new InlineBoxes for each absolute positioned charac ter (those that start new text chunks). | 967 // 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())) | 968 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_cu rrent.offset())) |
898 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 969 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
954 // additional whitespace. | 1025 // additional whitespace. |
955 if (!m_width.fitsOnLine(charWidth)) { | 1026 if (!m_width.fitsOnLine(charWidth)) { |
956 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); | 1027 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); |
957 skipTrailingWhitespace(m_lineBreak, m_lineInfo); | 1028 skipTrailingWhitespace(m_lineBreak, m_lineInfo); |
958 return true; | 1029 return true; |
959 } | 1030 } |
960 } | 1031 } |
961 return false; | 1032 return false; |
962 } | 1033 } |
963 | 1034 |
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) | 1035 inline bool BreakingContext::canBreakAtWhitespace(bool breakWords, WordMeasureme nt& wordMeasurement, bool stoppedIgnoringSpaces, bool& hyphenated, float charWid th, 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 { | 1036 { |
966 if (!m_autoWrap && !breakWords) | 1037 if (!m_autoWrap && !breakWords) |
967 return false; | 1038 return false; |
968 | 1039 |
969 // If we break only after white-space, consider the current character | 1040 // If we break only after white-space, consider the current character |
970 // as candidate width for this line. | 1041 // as candidate width for this line. |
971 if (midWordBreak | 1042 if (midWordBreak |
972 || trailingSpaceExceedsAvailableWidth(canBreakMidWord, layoutText, wordM easurement, applyWordSpacing, wordSpacing, font) | 1043 || trailingSpaceExceedsAvailableWidth(canBreakMidWord, layoutText, wordM easurement, applyWordSpacing, wordSpacing, font) |
973 || !m_width.fitsOnLine()) { | 1044 || !m_width.fitsOnLine()) { |
974 if (m_lineBreak.atTextParagraphSeparator()) { | 1045 if (m_lineBreak.atTextParagraphSeparator()) { |
975 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | 1046 if (!stoppedIgnoringSpaces && m_current.offset() > 0) |
976 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 1047 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
977 m_lineBreak.increment(); | 1048 m_lineBreak.increment(); |
978 m_lineInfo.setPreviousLineBrokeCleanly(true); | 1049 m_lineInfo.setPreviousLineBrokeCleanly(true); |
979 wordMeasurement.endOffset = m_lineBreak.offset(); | 1050 wordMeasurement.endOffset = m_lineBreak.offset(); |
980 } | 1051 } |
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) | 1052 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; | 1053 hyphenated = true; |
983 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasur ement.endOffset && !wordMeasurement.width) { | 1054 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasur ement.endOffset && !wordMeasurement.width) { |
984 if (charWidth) { | 1055 if (charWidth) { |
985 wordMeasurement.endOffset = m_lineBreak.offset(); | 1056 wordMeasurement.endOffset = m_lineBreak.offset(); |
986 wordMeasurement.width = charWidth; | 1057 wordMeasurement.width = charWidth; |
987 } | 1058 } |
988 } | 1059 } |
989 // Didn't fit. Jump to the end unless there's still an opportunity to co llapse whitespace. | 1060 // 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) { | 1061 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSp ace || !previousCharacterIsSpace) { |
991 m_atEnd = true; | 1062 m_atEnd = true; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1082 | 1153 |
1083 if (style.getTextIndentType() == TextIndentHanging) | 1154 if (style.getTextIndentType() == TextIndentHanging) |
1084 indentText = indentText == IndentText ? DoNotIndentText : IndentText; | 1155 indentText = indentText == IndentText ? DoNotIndentText : IndentText; |
1085 | 1156 |
1086 return indentText; | 1157 return indentText; |
1087 } | 1158 } |
1088 | 1159 |
1089 } // namespace blink | 1160 } // namespace blink |
1090 | 1161 |
1091 #endif // BreakingContextInlineHeaders_h | 1162 #endif // BreakingContextInlineHeaders_h |
OLD | NEW |