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 |