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

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: Add comments for heuristic, adjust widths of hyphens-auto-mock 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/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
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
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
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
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
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
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
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
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
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
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