| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. |
| 4 * All right reserved. | 4 * All right reserved. |
| 5 * Copyright (C) 2010 Google Inc. All rights reserved. | 5 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 6 * Copyright (C) 2013 Adobe Systems Incorporated. | 6 * Copyright (C) 2013 Adobe Systems Incorporated. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 void setCurrentCharacterIsSpace(UChar); | 154 void setCurrentCharacterIsSpace(UChar); |
| 155 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); | 155 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); |
| 156 bool shouldMidWordBreak(UChar, | 156 bool shouldMidWordBreak(UChar, |
| 157 LineLayoutText, | 157 LineLayoutText, |
| 158 const Font&, | 158 const Font&, |
| 159 float& charWidth, | 159 float& charWidth, |
| 160 float& widthFromLastBreakingOpportunity, | 160 float& widthFromLastBreakingOpportunity, |
| 161 bool breakAll, | 161 bool breakAll, |
| 162 int& nextBreakablePositionForBreakAll); | 162 int& nextBreakablePositionForBreakAll); |
| 163 bool rewindToMidWordBreak(WordMeasurement&, int end, float width); | 163 bool rewindToMidWordBreak(WordMeasurement&, int end, float width); |
| 164 bool canMidWordBreakBefore(LineLayoutText); |
| 164 bool rewindToFirstMidWordBreak(LineLayoutText, | 165 bool rewindToFirstMidWordBreak(LineLayoutText, |
| 165 const ComputedStyle&, | 166 const ComputedStyle&, |
| 166 const Font&, | 167 const Font&, |
| 167 bool breakAll, | 168 bool breakAll, |
| 168 WordMeasurement&); | 169 WordMeasurement&); |
| 169 bool rewindToMidWordBreak(LineLayoutText, | 170 bool rewindToMidWordBreak(LineLayoutText, |
| 170 const ComputedStyle&, | 171 const ComputedStyle&, |
| 171 const Font&, | 172 const Font&, |
| 172 bool breakAll, | 173 bool breakAll, |
| 173 WordMeasurement&); | 174 WordMeasurement&); |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 wordMeasurement.width = width; | 748 wordMeasurement.width = width; |
| 748 | 749 |
| 749 m_current.moveTo(m_current.getLineLayoutItem(), end, | 750 m_current.moveTo(m_current.getLineLayoutItem(), end, |
| 750 m_current.nextBreakablePosition()); | 751 m_current.nextBreakablePosition()); |
| 751 setCurrentCharacterIsSpace(m_current.current()); | 752 setCurrentCharacterIsSpace(m_current.current()); |
| 752 m_lineBreak.moveTo(m_current.getLineLayoutItem(), end, | 753 m_lineBreak.moveTo(m_current.getLineLayoutItem(), end, |
| 753 m_current.nextBreakablePosition()); | 754 m_current.nextBreakablePosition()); |
| 754 return true; | 755 return true; |
| 755 } | 756 } |
| 756 | 757 |
| 758 ALWAYS_INLINE bool BreakingContext::canMidWordBreakBefore(LineLayoutText text) { |
| 759 // No break opportunities at the beginning of a line. |
| 760 if (!m_width.currentWidth()) |
| 761 return false; |
| 762 // If this text node is not the first child of an inline, the parent and the |
| 763 // preivous have the same style. |
| 764 if (text.previousSibling()) |
| 765 return true; |
| 766 // Element boundaries belong to the parent of the element. |
| 767 // TODO(kojii): Not all cases of element boundaries are supported yet. |
| 768 // crbug.com/282134 |
| 769 if (LineLayoutItem element = text.parent()) { |
| 770 if (LineLayoutItem parent = element.parent()) { |
| 771 const ComputedStyle& parentStyle = parent.styleRef(); |
| 772 return parentStyle.autoWrap() && |
| 773 ((parentStyle.breakWords() && !m_width.committedWidth()) || |
| 774 parentStyle.wordBreak() == BreakAllWordBreak); |
| 775 } |
| 776 } |
| 777 return false; |
| 778 } |
| 779 |
| 757 ALWAYS_INLINE bool BreakingContext::rewindToFirstMidWordBreak( | 780 ALWAYS_INLINE bool BreakingContext::rewindToFirstMidWordBreak( |
| 758 LineLayoutText text, | 781 LineLayoutText text, |
| 759 const ComputedStyle& style, | 782 const ComputedStyle& style, |
| 760 const Font& font, | 783 const Font& font, |
| 761 bool breakAll, | 784 bool breakAll, |
| 762 WordMeasurement& wordMeasurement) { | 785 WordMeasurement& wordMeasurement) { |
| 763 int start = wordMeasurement.startOffset; | 786 int start = wordMeasurement.startOffset; |
| 764 int end; | 787 int end = canMidWordBreakBefore(text) ? start : start + 1; |
| 765 if (breakAll) { | 788 if (breakAll) { |
| 766 LazyLineBreakIterator lineBreakIterator(text.text(), style.locale()); | 789 LazyLineBreakIterator lineBreakIterator(text.text(), style.locale()); |
| 767 end = -1; | 790 int nextBreakable = -1; |
| 768 lineBreakIterator.isBreakable(start + 1, end, LineBreakType::BreakAll); | 791 lineBreakIterator.isBreakable(end, nextBreakable, LineBreakType::BreakAll); |
| 769 if (end < 0) | 792 if (nextBreakable < 0) |
| 770 return false; | 793 return false; |
| 771 } else { | 794 end = nextBreakable; |
| 772 end = start + 1; | |
| 773 } | 795 } |
| 774 if (end >= wordMeasurement.endOffset) | 796 if (end >= wordMeasurement.endOffset) |
| 775 return false; | 797 return false; |
| 776 | 798 |
| 777 float width = textWidth(text, start, end - start, font, | 799 float width = textWidth(text, start, end - start, font, |
| 778 m_width.currentWidth(), m_collapseWhiteSpace); | 800 m_width.currentWidth(), m_collapseWhiteSpace); |
| 801 // If the first break opportunity doesn't fit, and if there's a break |
| 802 // opportunity in previous runs, break at the opportunity. |
| 803 if (!m_width.fitsOnLine(width) && m_width.committedWidth()) |
| 804 return false; |
| 779 return rewindToMidWordBreak(wordMeasurement, end, width); | 805 return rewindToMidWordBreak(wordMeasurement, end, width); |
| 780 } | 806 } |
| 781 | 807 |
| 782 ALWAYS_INLINE bool BreakingContext::rewindToMidWordBreak( | 808 ALWAYS_INLINE bool BreakingContext::rewindToMidWordBreak( |
| 783 LineLayoutText text, | 809 LineLayoutText text, |
| 784 const ComputedStyle& style, | 810 const ComputedStyle& style, |
| 785 const Font& font, | 811 const Font& font, |
| 786 bool breakAll, | 812 bool breakAll, |
| 787 WordMeasurement& wordMeasurement) { | 813 WordMeasurement& wordMeasurement) { |
| 788 int start = wordMeasurement.startOffset; | 814 int start = wordMeasurement.startOffset; |
| 789 int len = wordMeasurement.endOffset - start; | 815 int len = wordMeasurement.endOffset - start; |
| 790 if (!len) | 816 if (!len) |
| 791 return false; | 817 return false; |
| 792 if (m_width.availableWidth() <= LayoutUnit::epsilon()) | 818 float xPosToBreak = m_width.availableWidth() - m_width.currentWidth(); |
| 819 if (xPosToBreak <= LayoutUnit::epsilon()) { |
| 820 // There were no space left. Skip computing how many characters can fit. |
| 793 return rewindToFirstMidWordBreak(text, style, font, breakAll, | 821 return rewindToFirstMidWordBreak(text, style, font, breakAll, |
| 794 wordMeasurement); | 822 wordMeasurement); |
| 823 } |
| 795 | 824 |
| 796 TextRun run = constructTextRun(font, text, start, len, style); | 825 TextRun run = constructTextRun(font, text, start, len, style); |
| 797 run.setTabSize(!m_collapseWhiteSpace, style.getTabSize()); | 826 run.setTabSize(!m_collapseWhiteSpace, style.getTabSize()); |
| 798 run.setXPos(m_width.currentWidth()); | 827 run.setXPos(m_width.currentWidth()); |
| 799 | 828 |
| 800 // TODO(kojii): should be replaced with safe-to-break when hb is ready. | 829 // TODO(kojii): should be replaced with safe-to-break when hb is ready. |
| 801 float x = | 830 xPosToBreak += LayoutUnit::epsilon(); |
| 802 m_width.availableWidth() + LayoutUnit::epsilon() - m_width.currentWidth(); | |
| 803 if (run.rtl()) | 831 if (run.rtl()) |
| 804 x = wordMeasurement.width - x; | 832 xPosToBreak = wordMeasurement.width - xPosToBreak; |
| 805 len = font.offsetForPosition(run, x, false); | 833 len = font.offsetForPosition(run, xPosToBreak, false); |
| 806 if (!len && !m_width.currentWidth()) | 834 if (!len) { |
| 835 // No characters can fit in the available space. |
| 807 return rewindToFirstMidWordBreak(text, style, font, breakAll, | 836 return rewindToFirstMidWordBreak(text, style, font, breakAll, |
| 808 wordMeasurement); | 837 wordMeasurement); |
| 838 } |
| 809 | 839 |
| 810 int end = start + len; | 840 int end = start + len; |
| 811 if (breakAll) { | 841 if (breakAll) { |
| 812 end = lastBreakablePositionForBreakAll(text, style, start, end); | 842 end = lastBreakablePositionForBreakAll(text, style, start, end); |
| 813 if (!end) | 843 if (!end) |
| 814 return false; | 844 return false; |
| 815 len = end - start; | 845 len = end - start; |
| 816 } | 846 } |
| 817 FloatRect rect = font.selectionRectForText(run, FloatPoint(), 0, 0, len); | 847 FloatRect rect = font.selectionRectForText(run, FloatPoint(), 0, 0, len); |
| 818 return rewindToMidWordBreak(wordMeasurement, end, rect.width()); | 848 return rewindToMidWordBreak(wordMeasurement, end, rect.width()); |
| (...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 | 1521 |
| 1492 if (style.getTextIndentType() == TextIndentHanging) | 1522 if (style.getTextIndentType() == TextIndentHanging) |
| 1493 indentText = indentText == IndentText ? DoNotIndentText : IndentText; | 1523 indentText = indentText == IndentText ? DoNotIndentText : IndentText; |
| 1494 | 1524 |
| 1495 return indentText; | 1525 return indentText; |
| 1496 } | 1526 } |
| 1497 | 1527 |
| 1498 } // namespace blink | 1528 } // namespace blink |
| 1499 | 1529 |
| 1500 #endif // BreakingContextInlineHeaders_h | 1530 #endif // BreakingContextInlineHeaders_h |
| OLD | NEW |