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: Fix test 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, 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
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()
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
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
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
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
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
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
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
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