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