| 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. 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 11 matching lines...) Expand all Loading... |
| 22 */ | 22 */ |
| 23 | 23 |
| 24 #ifndef BreakingContextInlineHeaders_h | 24 #ifndef BreakingContextInlineHeaders_h |
| 25 #define BreakingContextInlineHeaders_h | 25 #define BreakingContextInlineHeaders_h |
| 26 | 26 |
| 27 #include "core/layout/Layer.h" | 27 #include "core/layout/Layer.h" |
| 28 #include "core/layout/LayoutInline.h" | 28 #include "core/layout/LayoutInline.h" |
| 29 #include "core/layout/LayoutListMarker.h" | 29 #include "core/layout/LayoutListMarker.h" |
| 30 #include "core/layout/LayoutObject.h" | 30 #include "core/layout/LayoutObject.h" |
| 31 #include "core/layout/LayoutRubyRun.h" | 31 #include "core/layout/LayoutRubyRun.h" |
| 32 #include "core/layout/LayoutTextCombine.h" |
| 32 #include "core/layout/TextRunConstructor.h" | 33 #include "core/layout/TextRunConstructor.h" |
| 33 #include "core/layout/line/InlineIterator.h" | 34 #include "core/layout/line/InlineIterator.h" |
| 34 #include "core/layout/line/InlineTextBox.h" | 35 #include "core/layout/line/InlineTextBox.h" |
| 35 #include "core/layout/line/LayoutTextInfo.h" | 36 #include "core/layout/line/LayoutTextInfo.h" |
| 36 #include "core/layout/line/LineBreaker.h" | 37 #include "core/layout/line/LineBreaker.h" |
| 37 #include "core/layout/line/LineInfo.h" | 38 #include "core/layout/line/LineInfo.h" |
| 38 #include "core/layout/line/LineWidth.h" | 39 #include "core/layout/line/LineWidth.h" |
| 39 #include "core/layout/line/TrailingObjects.h" | 40 #include "core/layout/line/TrailingObjects.h" |
| 40 #include "core/layout/line/WordMeasurement.h" | 41 #include "core/layout/line/WordMeasurement.h" |
| 41 #include "core/layout/svg/LayoutSVGInlineText.h" | 42 #include "core/layout/svg/LayoutSVGInlineText.h" |
| 42 #include "core/rendering/RenderCombineText.h" | |
| 43 #include "platform/text/TextBreakIterator.h" | 43 #include "platform/text/TextBreakIterator.h" |
| 44 | 44 |
| 45 namespace blink { | 45 namespace blink { |
| 46 | 46 |
| 47 // We don't let our line box tree for a single line get any deeper than this. | 47 // We don't let our line box tree for a single line get any deeper than this. |
| 48 const unsigned cMaxLineDepth = 200; | 48 const unsigned cMaxLineDepth = 200; |
| 49 | 49 |
| 50 class BreakingContext { | 50 class BreakingContext { |
| 51 public: | 51 public: |
| 52 BreakingContext(InlineBidiResolver& resolver, LineInfo& inLineInfo, LineWidt
h& lineWidth, LayoutTextInfo& inLayoutTextInfo, FloatingObject* inLastFloatFromP
reviousLine, bool appliedStartWidth, LayoutBlockFlow* block) | 52 BreakingContext(InlineBidiResolver& resolver, LineInfo& inLineInfo, LineWidt
h& lineWidth, LayoutTextInfo& inLayoutTextInfo, FloatingObject* inLastFloatFromP
reviousLine, bool appliedStartWidth, LayoutBlockFlow* block) |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 return child->marginStart() + child->paddingStart() + child->borderStart(); | 301 return child->marginStart() + child->paddingStart() + child->borderStart(); |
| 302 } | 302 } |
| 303 | 303 |
| 304 inline LayoutUnit borderPaddingMarginEnd(LayoutInline* child) | 304 inline LayoutUnit borderPaddingMarginEnd(LayoutInline* child) |
| 305 { | 305 { |
| 306 return child->marginEnd() + child->paddingEnd() + child->borderEnd(); | 306 return child->marginEnd() + child->paddingEnd() + child->borderEnd(); |
| 307 } | 307 } |
| 308 | 308 |
| 309 inline bool shouldAddBorderPaddingMargin(LayoutObject* child, bool &checkSide) | 309 inline bool shouldAddBorderPaddingMargin(LayoutObject* child, bool &checkSide) |
| 310 { | 310 { |
| 311 if (!child || (child->isText() && !toRenderText(child)->textLength())) | 311 if (!child || (child->isText() && !toLayoutText(child)->textLength())) |
| 312 return true; | 312 return true; |
| 313 checkSide = false; | 313 checkSide = false; |
| 314 return checkSide; | 314 return checkSide; |
| 315 } | 315 } |
| 316 | 316 |
| 317 inline LayoutUnit inlineLogicalWidth(LayoutObject* child, bool start = true, boo
l end = true) | 317 inline LayoutUnit inlineLogicalWidth(LayoutObject* child, bool start = true, boo
l end = true) |
| 318 { | 318 { |
| 319 unsigned lineDepth = 1; | 319 unsigned lineDepth = 1; |
| 320 LayoutUnit extraWidth = 0; | 320 LayoutUnit extraWidth = 0; |
| 321 LayoutObject* parent = child->parent(); | 321 LayoutObject* parent = child->parent(); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 } | 385 } |
| 386 | 386 |
| 387 // This is currently just used for list markers and inline flows that have line
boxes. Neither should | 387 // This is currently just used for list markers and inline flows that have line
boxes. Neither should |
| 388 // have an effect on whitespace at the start of the line. | 388 // have an effect on whitespace at the start of the line. |
| 389 inline bool shouldSkipWhitespaceAfterStartObject(LayoutBlockFlow* block, LayoutO
bject* o, LineMidpointState& lineMidpointState) | 389 inline bool shouldSkipWhitespaceAfterStartObject(LayoutBlockFlow* block, LayoutO
bject* o, LineMidpointState& lineMidpointState) |
| 390 { | 390 { |
| 391 LayoutObject* next = bidiNextSkippingEmptyInlines(block, o); | 391 LayoutObject* next = bidiNextSkippingEmptyInlines(block, o); |
| 392 while (next && next->isFloatingOrOutOfFlowPositioned()) | 392 while (next && next->isFloatingOrOutOfFlowPositioned()) |
| 393 next = bidiNextSkippingEmptyInlines(block, next); | 393 next = bidiNextSkippingEmptyInlines(block, next); |
| 394 | 394 |
| 395 if (next && !next->isBR() && next->isText() && toRenderText(next)->textLengt
h() > 0) { | 395 if (next && !next->isBR() && next->isText() && toLayoutText(next)->textLengt
h() > 0) { |
| 396 RenderText* nextText = toRenderText(next); | 396 LayoutText* nextText = toLayoutText(next); |
| 397 UChar nextChar = nextText->characterAt(0); | 397 UChar nextChar = nextText->characterAt(0); |
| 398 if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) { | 398 if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) { |
| 399 lineMidpointState.startIgnoringSpaces(InlineIterator(0, o, 0)); | 399 lineMidpointState.startIgnoringSpaces(InlineIterator(0, o, 0)); |
| 400 return true; | 400 return true; |
| 401 } | 401 } |
| 402 } | 402 } |
| 403 | 403 |
| 404 return false; | 404 return false; |
| 405 } | 405 } |
| 406 | 406 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 | 488 |
| 489 inline float firstPositiveWidth(const WordMeasurements& wordMeasurements) | 489 inline float firstPositiveWidth(const WordMeasurements& wordMeasurements) |
| 490 { | 490 { |
| 491 for (size_t i = 0; i < wordMeasurements.size(); ++i) { | 491 for (size_t i = 0; i < wordMeasurements.size(); ++i) { |
| 492 if (wordMeasurements[i].width > 0) | 492 if (wordMeasurements[i].width > 0) |
| 493 return wordMeasurements[i].width; | 493 return wordMeasurements[i].width; |
| 494 } | 494 } |
| 495 return 0; | 495 return 0; |
| 496 } | 496 } |
| 497 | 497 |
| 498 inline float measureHyphenWidth(RenderText* renderer, const Font& font, TextDire
ction textDirection) | 498 inline float measureHyphenWidth(LayoutText* renderer, const Font& font, TextDire
ction textDirection) |
| 499 { | 499 { |
| 500 const LayoutStyle& style = renderer->styleRef(); | 500 const LayoutStyle& style = renderer->styleRef(); |
| 501 return font.width(constructTextRun(renderer, font, | 501 return font.width(constructTextRun(renderer, font, |
| 502 style.hyphenString().string(), style, style.direction())); | 502 style.hyphenString().string(), style, style.direction())); |
| 503 } | 503 } |
| 504 | 504 |
| 505 ALWAYS_INLINE TextDirection textDirectionFromUnicode(WTF::Unicode::Direction dir
ection) | 505 ALWAYS_INLINE TextDirection textDirectionFromUnicode(WTF::Unicode::Direction dir
ection) |
| 506 { | 506 { |
| 507 return direction == WTF::Unicode::RightToLeft | 507 return direction == WTF::Unicode::RightToLeft |
| 508 || direction == WTF::Unicode::RightToLeftArabic ? RTL : LTR; | 508 || direction == WTF::Unicode::RightToLeftArabic ? RTL : LTR; |
| 509 } | 509 } |
| 510 | 510 |
| 511 ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, con
st Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<c
onst SimpleFontData*>* fallbackFonts = 0) | 511 ALWAYS_INLINE float textWidth(LayoutText* text, unsigned from, unsigned len, con
st Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<c
onst SimpleFontData*>* fallbackFonts = 0) |
| 512 { | 512 { |
| 513 GlyphOverflow glyphOverflow; | 513 GlyphOverflow glyphOverflow; |
| 514 if (isFixedPitch || (!from && len == text->textLength()) || text->style()->h
asTextCombine()) | 514 if (isFixedPitch || (!from && len == text->textLength()) || text->style()->h
asTextCombine()) |
| 515 return text->width(from, len, font, xPos, text->style()->direction(), fa
llbackFonts, &glyphOverflow); | 515 return text->width(from, len, font, xPos, text->style()->direction(), fa
llbackFonts, &glyphOverflow); |
| 516 | 516 |
| 517 TextRun run = constructTextRun(text, font, text, from, len, text->styleRef()
); | 517 TextRun run = constructTextRun(text, font, text, from, len, text->styleRef()
); |
| 518 run.setCodePath(text->canUseSimpleFontCodePath() ? TextRun::ForceSimple : Te
xtRun::ForceComplex); | 518 run.setCodePath(text->canUseSimpleFontCodePath() ? TextRun::ForceSimple : Te
xtRun::ForceComplex); |
| 519 run.setTabSize(!collapseWhiteSpace, text->style()->tabSize()); | 519 run.setTabSize(!collapseWhiteSpace, text->style()->tabSize()); |
| 520 run.setXPos(xPos); | 520 run.setXPos(xPos); |
| 521 return font.width(run, fallbackFonts, &glyphOverflow); | 521 return font.width(run, fallbackFonts, &glyphOverflow); |
| 522 } | 522 } |
| 523 | 523 |
| 524 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
& hyphenated) | 524 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
& hyphenated) |
| 525 { | 525 { |
| 526 if (!m_current.offset()) | 526 if (!m_current.offset()) |
| 527 m_appliedStartWidth = false; | 527 m_appliedStartWidth = false; |
| 528 | 528 |
| 529 RenderText* renderText = toRenderText(m_current.object()); | 529 LayoutText* renderText = toLayoutText(m_current.object()); |
| 530 | 530 |
| 531 bool isSVGText = renderText->isSVGInlineText(); | 531 bool isSVGText = renderText->isSVGInlineText(); |
| 532 | 532 |
| 533 // If we have left a no-wrap inline and entered an autowrap inline while ign
oring spaces | 533 // If we have left a no-wrap inline and entered an autowrap inline while ign
oring spaces |
| 534 // then we need to mark the start of the autowrap inline as a potential line
break now. | 534 // then we need to mark the start of the autowrap inline as a potential line
break now. |
| 535 if (m_autoWrap && !LayoutStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { | 535 if (m_autoWrap && !LayoutStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { |
| 536 m_width.commit(); | 536 m_width.commit(); |
| 537 m_lineBreak.moveToStartOf(m_current.object()); | 537 m_lineBreak.moveToStartOf(m_current.object()); |
| 538 } | 538 } |
| 539 | 539 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 } | 676 } |
| 677 } | 677 } |
| 678 if (lineWasTooWide || !m_width.fitsOnLine()) { | 678 if (lineWasTooWide || !m_width.fitsOnLine()) { |
| 679 if (m_lineBreak.atTextParagraphSeparator()) { | 679 if (m_lineBreak.atTextParagraphSeparator()) { |
| 680 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | 680 if (!stoppedIgnoringSpaces && m_current.offset() > 0) |
| 681 m_lineMidpointState.ensureCharacterGetsLineBox(m_cur
rent); | 681 m_lineMidpointState.ensureCharacterGetsLineBox(m_cur
rent); |
| 682 m_lineBreak.increment(); | 682 m_lineBreak.increment(); |
| 683 m_lineInfo.setPreviousLineBrokeCleanly(true); | 683 m_lineInfo.setPreviousLineBrokeCleanly(true); |
| 684 wordMeasurement.endOffset = m_lineBreak.offset(); | 684 wordMeasurement.endOffset = m_lineBreak.offset(); |
| 685 } | 685 } |
| 686 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBr
eak.object()->isText() && toRenderText(m_lineBreak.object())->textLength() && to
RenderText(m_lineBreak.object())->characterAt(m_lineBreak.offset() - 1) == softH
yphen) | 686 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBr
eak.object()->isText() && toLayoutText(m_lineBreak.object())->textLength() && to
LayoutText(m_lineBreak.object())->characterAt(m_lineBreak.offset() - 1) == softH
yphen) |
| 687 hyphenated = true; | 687 hyphenated = true; |
| 688 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigne
d)wordMeasurement.endOffset && !wordMeasurement.width) { | 688 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigne
d)wordMeasurement.endOffset && !wordMeasurement.width) { |
| 689 if (charWidth) { | 689 if (charWidth) { |
| 690 wordMeasurement.endOffset = m_lineBreak.offset(); | 690 wordMeasurement.endOffset = m_lineBreak.offset(); |
| 691 wordMeasurement.width = charWidth; | 691 wordMeasurement.width = charWidth; |
| 692 } | 692 } |
| 693 } | 693 } |
| 694 // Didn't fit. Jump to the end unless there's still an oppor
tunity to collapse whitespace. | 694 // Didn't fit. Jump to the end unless there's still an oppor
tunity to collapse whitespace. |
| 695 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentC
haracterIsSpace || !previousCharacterIsSpace) { | 695 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentC
haracterIsSpace || !previousCharacterIsSpace) { |
| 696 m_atEnd = true; | 696 m_atEnd = true; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 m_startOfIgnoredSpaces.setObject(m_current.object()); | 772 m_startOfIgnoredSpaces.setObject(m_current.object()); |
| 773 m_startOfIgnoredSpaces.setOffset(m_current.offset()); | 773 m_startOfIgnoredSpaces.setOffset(m_current.offset()); |
| 774 } | 774 } |
| 775 | 775 |
| 776 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWa
p) { | 776 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWa
p) { |
| 777 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) | 777 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) |
| 778 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur
rent.nextBreakablePosition()); | 778 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur
rent.nextBreakablePosition()); |
| 779 } | 779 } |
| 780 | 780 |
| 781 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpac
es) | 781 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpac
es) |
| 782 m_trailingObjects.setTrailingWhitespace(toRenderText(m_current.objec
t())); | 782 m_trailingObjects.setTrailingWhitespace(toLayoutText(m_current.objec
t())); |
| 783 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsS
pace) | 783 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsS
pace) |
| 784 m_trailingObjects.clear(); | 784 m_trailingObjects.clear(); |
| 785 | 785 |
| 786 m_atStart = false; | 786 m_atStart = false; |
| 787 nextCharacter(c, lastCharacter, secondToLastCharacter); | 787 nextCharacter(c, lastCharacter, secondToLastCharacter); |
| 788 } | 788 } |
| 789 | 789 |
| 790 m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo
LastCharacter); | 790 m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo
LastCharacter); |
| 791 | 791 |
| 792 wordMeasurements.grow(wordMeasurements.size() + 1); | 792 wordMeasurements.grow(wordMeasurements.size() + 1); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 819 | 819 |
| 820 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() | 820 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() |
| 821 { | 821 { |
| 822 bool checkForBreak = m_autoWrap; | 822 bool checkForBreak = m_autoWrap; |
| 823 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object(
) && m_currWS == NOWRAP) { | 823 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object(
) && m_currWS == NOWRAP) { |
| 824 checkForBreak = true; | 824 checkForBreak = true; |
| 825 } else if (m_nextObject && m_current.object()->isText() && m_nextObject->isT
ext() && !m_nextObject->isBR() && (m_autoWrap || m_nextObject->style()->autoWrap
())) { | 825 } else if (m_nextObject && m_current.object()->isText() && m_nextObject->isT
ext() && !m_nextObject->isBR() && (m_autoWrap || m_nextObject->style()->autoWrap
())) { |
| 826 if (m_autoWrap && m_currentCharacterIsSpace) { | 826 if (m_autoWrap && m_currentCharacterIsSpace) { |
| 827 checkForBreak = true; | 827 checkForBreak = true; |
| 828 } else { | 828 } else { |
| 829 RenderText* nextText = toRenderText(m_nextObject); | 829 LayoutText* nextText = toLayoutText(m_nextObject); |
| 830 if (nextText->textLength()) { | 830 if (nextText->textLength()) { |
| 831 UChar c = nextText->characterAt(0); | 831 UChar c = nextText->characterAt(0); |
| 832 // If the next item on the line is text, and if we did not end w
ith | 832 // If the next item on the line is text, and if we did not end w
ith |
| 833 // a space, then the next text run continues our word (and so it
needs to | 833 // a space, then the next text run continues our word (and so it
needs to |
| 834 // keep adding to the uncommitted width. Just update and continu
e. | 834 // keep adding to the uncommitted width. Just update and continu
e. |
| 835 checkForBreak = !m_currentCharacterIsSpace && (c == ' ' || c ==
'\t' || (c == '\n' && !m_nextObject->preservesNewline())); | 835 checkForBreak = !m_currentCharacterIsSpace && (c == ' ' || c ==
'\t' || (c == '\n' && !m_nextObject->preservesNewline())); |
| 836 } else if (nextText->isWordBreak()) { | 836 } else if (nextText->isWordBreak()) { |
| 837 checkForBreak = true; | 837 checkForBreak = true; |
| 838 } | 838 } |
| 839 | 839 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 | 891 |
| 892 if (style.textIndentType() == TextIndentHanging) | 892 if (style.textIndentType() == TextIndentHanging) |
| 893 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In
dentText; | 893 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In
dentText; |
| 894 | 894 |
| 895 return shouldIndentText; | 895 return shouldIndentText; |
| 896 } | 896 } |
| 897 | 897 |
| 898 } | 898 } |
| 899 | 899 |
| 900 #endif // BreakingContextInlineHeaders_h | 900 #endif // BreakingContextInlineHeaders_h |
| OLD | NEW |