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

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

Issue 2077313002: Prevent to measure the whole word when break-all (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Created 4 years, 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 InlineIterator handleEndOfLine(); 109 InlineIterator handleEndOfLine();
110 110
111 void clearLineBreakIfFitsOnLine() 111 void clearLineBreakIfFitsOnLine()
112 { 112 {
113 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) 113 if (m_width.fitsOnLine() || m_lastWS == NOWRAP)
114 m_lineBreak.clear(); 114 m_lineBreak.clear();
115 } 115 }
116 116
117 private: 117 private:
118 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); 118 void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
119 bool shouldMidWordBreak(UChar, LineLayoutText, const Font&,
120 float& charWidth, float& widthFromLastBreakingOpportunity,
121 bool breakAll, int& nextBreakablePositionForBreakAll);
119 bool rewindToMidWordBreak(WordMeasurement&, int end, float width); 122 bool rewindToMidWordBreak(WordMeasurement&, int end, float width);
120 bool rewindToFirstMidWordBreak(LineLayoutText, const ComputedStyle&, const F ont&, bool breakAll, WordMeasurement&); 123 bool rewindToFirstMidWordBreak(LineLayoutText, const ComputedStyle&, const F ont&, bool breakAll, WordMeasurement&);
121 bool rewindToMidWordBreak(LineLayoutText, const ComputedStyle&, const Font&, bool breakAll, WordMeasurement&); 124 bool rewindToMidWordBreak(LineLayoutText, const ComputedStyle&, const Font&, bool breakAll, WordMeasurement&);
122 bool hyphenate(LineLayoutText, const ComputedStyle&, const Font&, const Hyph enation&, float lastSpaceWordSpacing, WordMeasurement&); 125 bool hyphenate(LineLayoutText, const ComputedStyle&, const Font&, const Hyph enation&, float lastSpaceWordSpacing, WordMeasurement&);
123 126
124 InlineBidiResolver& m_resolver; 127 InlineBidiResolver& m_resolver;
125 128
126 InlineIterator m_current; 129 InlineIterator m_current;
127 InlineIterator m_lineBreak; 130 InlineIterator m_lineBreak;
128 InlineIterator m_startOfIgnoredSpaces; 131 InlineIterator m_startOfIgnoredSpaces;
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 { 538 {
536 if ((!from && len == text.textLength()) || text.style()->hasTextCombine()) 539 if ((!from && len == text.textLength()) || text.style()->hasTextCombine())
537 return text.width(from, len, font, LayoutUnit(xPos), text.style()->direc tion(), fallbackFonts, glyphBounds); 540 return text.width(from, len, font, LayoutUnit(xPos), text.style()->direc tion(), fallbackFonts, glyphBounds);
538 541
539 TextRun run = constructTextRun(font, text, from, len, text.styleRef()); 542 TextRun run = constructTextRun(font, text, from, len, text.styleRef());
540 run.setTabSize(!collapseWhiteSpace, text.style()->getTabSize()); 543 run.setTabSize(!collapseWhiteSpace, text.style()->getTabSize());
541 run.setXPos(xPos); 544 run.setXPos(xPos);
542 return font.width(run, fallbackFonts, glyphBounds); 545 return font.width(run, fallbackFonts, glyphBounds);
543 } 546 }
544 547
548 ALWAYS_INLINE bool BreakingContext::shouldMidWordBreak(
549 UChar c, LineLayoutText layoutText, const Font& font,
550 float& charWidth, float& widthFromLastBreakingOpportunity,
551 bool breakAll, int& nextBreakablePositionForBreakAll)
552 {
553 // For breakWords/breakAll, we need to measure up to normal break
554 // opportunity and then rewindToMidWordBreak() because ligatures/kerning can
555 // shorten the width as we add more characters.
556 // However, doing so can hit the performance when a "word" is really long,
557 // such as minimized JS, because the next line will re-shape the rest of the
558 // word in the current architecture.
559 // This function is a heuristic optimization to stop at 2em overflow.
560 float overflowAllowance = 2 * font.getFontDescription().computedSize();
561
562 widthFromLastBreakingOpportunity += charWidth;
563 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.offset( ) + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedCharacterAt( m_current.offset() + 1));
564 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIsBeforeSu rrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreakingOppor tunity, m_collapseWhiteSpace);
565 if (m_width.committedWidth() + widthFromLastBreakingOpportunity + charWidth <= m_width.availableWidth() + overflowAllowance)
566 return false;
567
kojii 2016/07/05 11:37:58 Up to this point in this function is just a move f
568 // breakAll has different break opportunities. Ensure we break only at
569 // breakAll allows to break.
570 if (breakAll &&
571 !m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), ne xtBreakablePositionForBreakAll, LineBreakType::BreakAll)) {
572 return false;
573 }
574
575 return true;
576 }
577
545 ALWAYS_INLINE int lastBreakablePositionForBreakAll(LineLayoutText text, 578 ALWAYS_INLINE int lastBreakablePositionForBreakAll(LineLayoutText text,
546 const ComputedStyle& style, int start, int end) 579 const ComputedStyle& style, int start, int end)
547 { 580 {
548 LazyLineBreakIterator lineBreakIterator(text.text(), style.locale()); 581 LazyLineBreakIterator lineBreakIterator(text.text(), style.locale());
549 int lastBreakablePosition = 0, nextBreakablePosition = -1; 582 int lastBreakablePosition = 0, nextBreakablePosition = -1;
550 for (int i = start; ;i = nextBreakablePosition + 1) { 583 for (int i = start; ;i = nextBreakablePosition + 1) {
551 lineBreakIterator.isBreakable(i, nextBreakablePosition, LineBreakType::B reakAll); 584 lineBreakIterator.isBreakable(i, nextBreakablePosition, LineBreakType::B reakAll);
552 if (nextBreakablePosition == end) 585 if (nextBreakablePosition == end)
553 return end; 586 return end;
554 if (nextBreakablePosition < 0 || nextBreakablePosition > end) 587 if (nextBreakablePosition < 0 || nextBreakablePosition > end)
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 if (layoutText.isSVGInlineText()) { 741 if (layoutText.isSVGInlineText()) {
709 breakWords = false; 742 breakWords = false;
710 breakAll = false; 743 breakAll = false;
711 keepAll = false; 744 keepAll = false;
712 } 745 }
713 746
714 // Use LineBreakType::Normal for break-all. When a word does not fit, 747 // Use LineBreakType::Normal for break-all. When a word does not fit,
715 // rewindToMidWordBreak() finds the mid-word break point. 748 // rewindToMidWordBreak() finds the mid-word break point.
716 LineBreakType lineBreakType = keepAll ? LineBreakType::KeepAll : LineBreakTy pe::Normal; 749 LineBreakType lineBreakType = keepAll ? LineBreakType::KeepAll : LineBreakTy pe::Normal;
717 bool canBreakMidWord = breakAll || breakWords; 750 bool canBreakMidWord = breakAll || breakWords;
751 int nextBreakablePositionForBreakAll = -1;
718 752
719 if (layoutText.isWordBreak()) { 753 if (layoutText.isWordBreak()) {
720 m_width.commit(); 754 m_width.commit();
721 m_lineBreak.moveToStartOf(m_current.getLineLayoutItem()); 755 m_lineBreak.moveToStartOf(m_current.getLineLayoutItem());
722 ASSERT(m_current.offset() == layoutText.textLength()); 756 ASSERT(m_current.offset() == layoutText.textLength());
723 } 757 }
724 758
725 if (m_layoutTextInfo.m_text != layoutText) { 759 if (m_layoutTextInfo.m_text != layoutText) {
726 m_layoutTextInfo.m_text = layoutText; 760 m_layoutTextInfo.m_text = layoutText;
727 m_layoutTextInfo.m_font = &font; 761 m_layoutTextInfo.m_font = &font;
(...skipping 21 matching lines...) Expand all
749 } 783 }
750 784
751 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth && !disableSo ftHyphen) { 785 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth && !disableSo ftHyphen) {
752 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); 786 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction()));
753 m_width.addUncommittedWidth(hyphenWidth); 787 m_width.addUncommittedWidth(hyphenWidth);
754 } 788 }
755 789
756 bool applyWordSpacing = false; 790 bool applyWordSpacing = false;
757 791
758 // Determine if we should try breaking in the middle of a word. 792 // Determine if we should try breaking in the middle of a word.
759 if (breakWords && !midWordBreak && !U16_IS_TRAIL(c)) { 793 if (canBreakMidWord && !midWordBreak && !U16_IS_TRAIL(c))
760 widthFromLastBreakingOpportunity += charWidth; 794 midWordBreak = shouldMidWordBreak(c, layoutText, font, charWidth, wi dthFromLastBreakingOpportunity, breakAll, nextBreakablePositionForBreakAll);
761 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current .offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar acterAt(m_current.offset() + 1));
762 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak ingOpportunity, m_collapseWhiteSpace);
763 // Measure up to 2em overflow since ligatures/kerning can shorten
764 // the width as we add more characters. rewindToMidWordBreak() can
765 // measure the accurate mid-word break point then.
766 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor tunity + charWidth > m_width.availableWidth()
767 + 2 * font.getFontDescription().computedSize();
768 }
769 795
770 // Determine if we are in the whitespace between words. 796 // Determine if we are in the whitespace between words.
771 int nextBreakablePosition = m_current.nextBreakablePosition(); 797 int nextBreakablePosition = m_current.nextBreakablePosition();
772 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next BreakablePosition, lineBreakType) 798 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next BreakablePosition, lineBreakType)
773 && (!disableSoftHyphen || m_current.previousInSameNode() != softHyph enCharacter)); 799 && (!disableSoftHyphen || m_current.previousInSameNode() != softHyph enCharacter));
774 m_current.setNextBreakablePosition(nextBreakablePosition); 800 m_current.setNextBreakablePosition(nextBreakablePosition);
775 801
776 // 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. 802 // 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 (!betweenWords && !midWordBreak) { 803 if (!betweenWords && !midWordBreak) {
778 if (m_ignoringSpaces) { 804 if (m_ignoringSpaces) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); 846 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement);
821 847
822 // If this is the end of the first word in run of text then make sure we apply the width from any leading inlines. 848 // If this is the end of the first word in run of text then make sure we apply the width from any leading inlines.
823 // For example: '<span style="margin-left: 5px;"><span style="margin-lef t: 10px;">FirstWord</span></span>' would 849 // For example: '<span style="margin-left: 5px;"><span style="margin-lef t: 10px;">FirstWord</span></span>' would
824 // apply a width of 15px from the two span ancestors. 850 // apply a width of 15px from the two span ancestors.
825 if (!m_appliedStartWidth) { 851 if (!m_appliedStartWidth) {
826 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.getLineLayoutItem(), true, false).toFloat()); 852 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.getLineLayoutItem(), true, false).toFloat());
827 m_appliedStartWidth = true; 853 m_appliedStartWidth = true;
828 } 854 }
829 855
830 // 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 (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity)
832 m_width.fitBelowFloats(m_lineInfo.isFirstLine());
833
834 midWordBreak = false; 856 midWordBreak = false;
835 if (!m_width.fitsOnLine()) { 857 if (!m_width.fitsOnLine()) {
836 if (canBreakMidWord) { 858 if (canBreakMidWord) {
837 m_width.addUncommittedWidth(-wordMeasurement.width); 859 m_width.addUncommittedWidth(-wordMeasurement.width);
838 if (rewindToMidWordBreak(layoutText, style, font, breakAll, word Measurement)) { 860 if (rewindToMidWordBreak(layoutText, style, font, breakAll, word Measurement)) {
839 lastWidthMeasurement = wordMeasurement.width + lastSpaceWord Spacing; 861 lastWidthMeasurement = wordMeasurement.width + lastSpaceWord Spacing;
840 midWordBreak = true; 862 midWordBreak = true;
841 } 863 }
842 m_width.addUncommittedWidth(wordMeasurement.width); 864 m_width.addUncommittedWidth(wordMeasurement.width);
843 } else if (hyphenation) { 865 } else if (hyphenation) {
844 m_width.addUncommittedWidth(-wordMeasurement.width); 866 m_width.addUncommittedWidth(-wordMeasurement.width);
845 DCHECK(lastSpace == static_cast<unsigned>(wordMeasurement.startO ffset)); 867 DCHECK(lastSpace == static_cast<unsigned>(wordMeasurement.startO ffset));
846 DCHECK(m_current.offset() == static_cast<unsigned>(wordMeasureme nt.endOffset)); 868 DCHECK(m_current.offset() == static_cast<unsigned>(wordMeasureme nt.endOffset));
847 if (hyphenate(layoutText, style, font, *hyphenation, lastSpaceWo rdSpacing, wordMeasurement)) { 869 if (hyphenate(layoutText, style, font, *hyphenation, lastSpaceWo rdSpacing, wordMeasurement)) {
848 m_width.addUncommittedWidth(wordMeasurement.width); 870 m_width.addUncommittedWidth(wordMeasurement.width);
849 hyphenated = true; 871 hyphenated = true;
850 m_atEnd = true; 872 m_atEnd = true;
851 return false; 873 return false;
852 } 874 }
853 m_width.addUncommittedWidth(wordMeasurement.width); 875 m_width.addUncommittedWidth(wordMeasurement.width);
854 } 876 }
855 } 877 }
856 878
879 // If we haven't hit a breakable position yet and already don't fit on t he line try to move below any floats.
880 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) {
881 float availableWidthBefore = m_width.availableWidth();
882 m_width.fitBelowFloats(m_lineInfo.isFirstLine());
883 // If availableWidth changes by moving the line below floats, needs to measure midWordBreak again.
884 if (midWordBreak && availableWidthBefore != m_width.availableWidth() )
885 midWordBreak = false;
886 }
kojii 2016/07/05 11:37:58 Doing this before rewindToMidWordBreak was the pre
887
857 // If there is a soft-break available at this whitespace position then t ake it. 888 // If there is a soft-break available at this whitespace position then t ake it.
858 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; 889 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
859 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa ces, charWidth, hyphenated, disableSoftHyphen, hyphenWidth, betweenWords, midWor dBreak, canBreakMidWord, previousCharacterIsSpace, lastWidthMeasurement, layoutT ext, font, applyWordSpacing, wordSpacing)) 890 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa ces, charWidth, hyphenated, disableSoftHyphen, hyphenWidth, betweenWords, midWor dBreak, canBreakMidWord, previousCharacterIsSpace, lastWidthMeasurement, layoutT ext, font, applyWordSpacing, wordSpacing))
860 return false; 891 return false;
861 892
862 // If there is a hard-break available at this whitespace position then t ake it. 893 // If there is a hard-break available at this whitespace position then t ake it.
863 if (c == newlineCharacter && m_preservesNewline) { 894 if (c == newlineCharacter && m_preservesNewline) {
864 if (!stoppedIgnoringSpaces && m_current.offset()) 895 if (!stoppedIgnoringSpaces && m_current.offset())
865 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); 896 m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
866 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition()); 897 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset() , m_current.nextBreakablePosition());
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 1183
1153 if (style.getTextIndentType() == TextIndentHanging) 1184 if (style.getTextIndentType() == TextIndentHanging)
1154 indentText = indentText == IndentText ? DoNotIndentText : IndentText; 1185 indentText = indentText == IndentText ? DoNotIndentText : IndentText;
1155 1186
1156 return indentText; 1187 return indentText;
1157 } 1188 }
1158 1189
1159 } // namespace blink 1190 } // namespace blink
1160 1191
1161 #endif // BreakingContextInlineHeaders_h 1192 #endif // BreakingContextInlineHeaders_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698