Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h

Issue 1978683002: Enable hyphens: auto and none in BreakingContext (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: drott review Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/core.gypi ('k') | third_party/WebKit/Source/core/testing/Internals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698