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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 void initializeForCurrentObject(); | 94 void initializeForCurrentObject(); |
95 | 95 |
96 void increment(); | 96 void increment(); |
97 | 97 |
98 void handleBR(EClear&); | 98 void handleBR(EClear&); |
99 void handleOutOfFlowPositioned(Vector<LineLayoutBox>& positionedObjects); | 99 void handleOutOfFlowPositioned(Vector<LineLayoutBox>& positionedObjects); |
100 void handleFloat(); | 100 void handleFloat(); |
101 void handleEmptyInline(); | 101 void handleEmptyInline(); |
102 void handleReplaced(); | 102 void handleReplaced(); |
103 bool handleText(WordMeasurements&, bool& hyphenated); | 103 bool handleText(WordMeasurements&, bool& hyphenated); |
| 104 void prepareForNextCharacter(const LineLayoutText&, bool& prohibitBreakInsid
e, bool previousCharacterIsSpace, bool previousCharacterShouldCollapseIfPreWap); |
104 void commitAndUpdateLineBreakIfNeeded(); | 105 void commitAndUpdateLineBreakIfNeeded(); |
105 InlineIterator handleEndOfLine(); | 106 InlineIterator handleEndOfLine(); |
106 | 107 |
107 void clearLineBreakIfFitsOnLine() | 108 void clearLineBreakIfFitsOnLine() |
108 { | 109 { |
109 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) | 110 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) |
110 m_lineBreak.clear(); | 111 m_lineBreak.clear(); |
111 } | 112 } |
112 | 113 |
113 private: | 114 private: |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 return font.width(run, fallbackFonts, glyphBounds); | 539 return font.width(run, fallbackFonts, glyphBounds); |
539 } | 540 } |
540 | 541 |
541 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
& hyphenated) | 542 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
& hyphenated) |
542 { | 543 { |
543 if (!m_current.offset()) | 544 if (!m_current.offset()) |
544 m_appliedStartWidth = false; | 545 m_appliedStartWidth = false; |
545 | 546 |
546 LineLayoutText layoutText(m_current.object()); | 547 LineLayoutText layoutText(m_current.object()); |
547 | 548 |
548 bool isSVGText = layoutText.isSVGInlineText(); | |
549 | |
550 // If we have left a no-wrap inline and entered an autowrap inline while ign
oring spaces | 549 // If we have left a no-wrap inline and entered an autowrap inline while ign
oring spaces |
551 // then we need to mark the start of the autowrap inline as a potential line
break now. | 550 // then we need to mark the start of the autowrap inline as a potential line
break now. |
552 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { | 551 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { |
553 m_width.commit(); | 552 m_width.commit(); |
554 m_lineBreak.moveToStartOf(m_current.object()); | 553 m_lineBreak.moveToStartOf(m_current.object()); |
555 } | 554 } |
556 | 555 |
557 const ComputedStyle& style = layoutText.styleRef(m_lineInfo.isFirstLine()); | 556 const ComputedStyle& style = layoutText.styleRef(m_lineInfo.isFirstLine()); |
558 const Font& font = style.font(); | 557 const Font& font = style.font(); |
559 | 558 |
(...skipping 13 matching lines...) Expand all Loading... |
573 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is
CombineText() && LineLayoutTextCombine(layoutText).isCombined(); | 572 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is
CombineText() && LineLayoutTextCombine(layoutText).isCombined(); |
574 | 573 |
575 // This is currently only used for word-break: break-all, specifically for t
he case | 574 // This is currently only used for word-break: break-all, specifically for t
he case |
576 // where we have a break opportunity within a word, then a string of non-bre
akable | 575 // where we have a break opportunity within a word, then a string of non-bre
akable |
577 // content that ends up making our word wider than the current line. | 576 // content that ends up making our word wider than the current line. |
578 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html | 577 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html |
579 float widthMeasurementAtLastBreakOpportunity = 0; | 578 float widthMeasurementAtLastBreakOpportunity = 0; |
580 | 579 |
581 float hyphenWidth = 0; | 580 float hyphenWidth = 0; |
582 | 581 |
583 if (isSVGText) { | 582 if (layoutText.isSVGInlineText()) { |
584 breakWords = false; | 583 breakWords = false; |
585 breakAll = false; | 584 breakAll = false; |
586 keepAll = false; | 585 keepAll = false; |
587 } | 586 } |
588 | 587 |
589 if (layoutText.isWordBreak()) { | 588 if (layoutText.isWordBreak()) { |
590 m_width.commit(); | 589 m_width.commit(); |
591 m_lineBreak.moveToStartOf(m_current.object()); | 590 m_lineBreak.moveToStartOf(m_current.object()); |
592 ASSERT(m_current.offset() == layoutText.textLength()); | 591 ASSERT(m_current.offset() == layoutText.textLength()); |
593 } | 592 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 widthFromLastBreakingOpportunity += charWidth; | 627 widthFromLastBreakingOpportunity += charWidth; |
629 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current
.offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar
acterAt(m_current.offset() + 1)); | 628 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current
.offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedChar
acterAt(m_current.offset() + 1)); |
630 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs
BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak
ingOpportunity, m_collapseWhiteSpace); | 629 charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIs
BeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreak
ingOpportunity, m_collapseWhiteSpace); |
631 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor
tunity + charWidth > m_width.availableWidth(); | 630 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor
tunity + charWidth > m_width.availableWidth(); |
632 } | 631 } |
633 | 632 |
634 int nextBreakablePosition = m_current.nextBreakablePosition(); | 633 int nextBreakablePosition = m_current.nextBreakablePosition(); |
635 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt
art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next
BreakablePosition, breakAll ? LineBreakType::BreakAll : keepAll ? LineBreakType:
:KeepAll : LineBreakType::Normal)); | 634 bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atSt
art && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), next
BreakablePosition, breakAll ? LineBreakType::BreakAll : keepAll ? LineBreakType:
:KeepAll : LineBreakType::Normal)); |
636 m_current.setNextBreakablePosition(nextBreakablePosition); | 635 m_current.setNextBreakablePosition(nextBreakablePosition); |
637 | 636 |
638 if (betweenWords || midWordBreak) { | 637 // 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. |
639 bool stoppedIgnoringSpaces = false; | 638 if (!betweenWords && !midWordBreak) { |
640 if (m_ignoringSpaces) { | 639 if (m_ignoringSpaces) { |
641 lastSpaceWordSpacing = 0; | 640 // Stop ignoring spaces and begin at this |
642 if (!m_currentCharacterIsSpace) { | 641 // new point. |
643 // Stop ignoring spaces and begin at this | 642 m_ignoringSpaces = false; |
644 // new point. | 643 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
645 m_ignoringSpaces = false; | 644 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure
ments.last().width) ? wordSpacing : 0; |
646 wordSpacingForWordMeasurement = 0; | 645 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add
in any of the ignored spaces. |
647 lastSpace = m_current.offset(); // e.g., "Foo goo", don't
add in any of the ignored spaces. | 646 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_curre
nt.object(), m_current.offset())); |
648 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_c
urrent.object(), m_current.offset())); | 647 } |
649 stoppedIgnoringSpaces = true; | 648 |
650 } else { | 649 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCha
racterIsSpace, previousCharacterShouldCollapseIfPreWap); |
651 // Just keep ignoring these spaces. | 650 m_atStart = false; |
652 nextCharacter(c, lastCharacter, secondToLastCharacter); | 651 nextCharacter(c, lastCharacter, secondToLastCharacter); |
653 continue; | 652 continue; |
| 653 } |
| 654 |
| 655 // If we're ignoring space and we're at a collapsible space such as a sp
ace or tab, continue to the next character. |
| 656 bool stoppedIgnoringSpaces = false; |
| 657 if (m_ignoringSpaces) { |
| 658 lastSpaceWordSpacing = 0; |
| 659 if (!m_currentCharacterIsSpace) { |
| 660 // Stop ignoring spaces and begin at this |
| 661 // new point. |
| 662 m_ignoringSpaces = false; |
| 663 wordSpacingForWordMeasurement = 0; |
| 664 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add
in any of the ignored spaces. |
| 665 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_curre
nt.object(), m_current.offset())); |
| 666 stoppedIgnoringSpaces = true; |
| 667 } else { |
| 668 // Just keep ignoring these spaces. |
| 669 nextCharacter(c, lastCharacter, secondToLastCharacter); |
| 670 continue; |
| 671 } |
| 672 } |
| 673 |
| 674 // We're in the first whitespace after a word or in whitespace that we d
on't collapse, which means we may have a breaking opportunity here. |
| 675 wordMeasurements.grow(wordMeasurements.size() + 1); |
| 676 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
| 677 |
| 678 wordMeasurement.layoutText = layoutText; |
| 679 wordMeasurement.endOffset = m_current.offset(); |
| 680 wordMeasurement.startOffset = lastSpace; |
| 681 |
| 682 float lastWidthMeasurement; |
| 683 if (wordTrailingSpaceWidth && c == spaceCharacter) |
| 684 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.of
fset() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wor
dMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpaceWid
th; |
| 685 else |
| 686 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.of
fset() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMea
surement.fallbackFonts, &wordMeasurement.glyphBounds); |
| 687 |
| 688 wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMeasure
ment; |
| 689 wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0); |
| 690 lastWidthMeasurement += lastSpaceWordSpacing; |
| 691 m_width.addUncommittedWidth(lastWidthMeasurement); |
| 692 |
| 693 if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharact
erIsSpace && lastWidthMeasurement) |
| 694 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); |
| 695 |
| 696 if (!m_appliedStartWidth) { |
| 697 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded(
m_current.object(), true, false).toFloat()); |
| 698 m_appliedStartWidth = true; |
| 699 } |
| 700 |
| 701 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
| 702 |
| 703 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() &&
!widthMeasurementAtLastBreakOpportunity) |
| 704 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
| 705 |
| 706 if (m_autoWrap || breakWords) { |
| 707 // If we break only after white-space, consider the current characte
r |
| 708 // as candidate width for this line. |
| 709 bool lineWasTooWide = false; |
| 710 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentSt
yle->breakOnlyAfterWhiteSpace() && !midWordBreak) { |
| 711 float charWidth = textWidth(layoutText, m_current.offset(), 1, f
ont, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFont
s, &wordMeasurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0); |
| 712 // Check if line is too big even without the extra space |
| 713 // at the end of the line. If it is not, do nothing. |
| 714 // If the line needs the extra whitespace to be too long, |
| 715 // then move the line break to the space and skip all |
| 716 // additional whitespace. |
| 717 if (!m_width.fitsOnLine(charWidth)) { |
| 718 lineWasTooWide = true; |
| 719 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m
_current.nextBreakablePosition()); |
| 720 skipTrailingWhitespace(m_lineBreak, m_lineInfo); |
654 } | 721 } |
655 } | 722 } |
656 | 723 if (lineWasTooWide || !m_width.fitsOnLine()) { |
657 wordMeasurements.grow(wordMeasurements.size() + 1); | 724 if (m_lineBreak.atTextParagraphSeparator()) { |
658 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 725 if (!stoppedIgnoringSpaces && m_current.offset() > 0) |
659 | 726 m_lineMidpointState.ensureCharacterGetsLineBox(m_current
); |
660 wordMeasurement.layoutText = layoutText; | 727 m_lineBreak.increment(); |
661 wordMeasurement.endOffset = m_current.offset(); | 728 m_lineInfo.setPreviousLineBrokeCleanly(true); |
662 wordMeasurement.startOffset = lastSpace; | 729 wordMeasurement.endOffset = m_lineBreak.offset(); |
663 | 730 } |
664 float lastWidthMeasurement; | 731 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.
object().isText() && LineLayoutText(m_lineBreak.object()).textLength() && LineLa
youtText(m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == softHyph
enCharacter) |
665 if (wordTrailingSpaceWidth && c == spaceCharacter) | 732 hyphenated = true; |
666 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_curren
t.offset() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace,
&wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpac
eWidth; | 733 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wo
rdMeasurement.endOffset && !wordMeasurement.width) { |
667 else | 734 if (charWidth) { |
668 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_curren
t.offset() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wor
dMeasurement.fallbackFonts, &wordMeasurement.glyphBounds); | 735 wordMeasurement.endOffset = m_lineBreak.offset(); |
669 | 736 wordMeasurement.width = charWidth; |
670 wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMea
surement; | |
671 wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0); | |
672 lastWidthMeasurement += lastSpaceWordSpacing; | |
673 m_width.addUncommittedWidth(lastWidthMeasurement); | |
674 | |
675 if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCha
racterIsSpace && lastWidthMeasurement) | |
676 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); | |
677 | |
678 if (!m_appliedStartWidth) { | |
679 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNee
ded(m_current.object(), true, false).toFloat()); | |
680 m_appliedStartWidth = true; | |
681 } | |
682 | |
683 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; | |
684 | |
685 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine()
&& !widthMeasurementAtLastBreakOpportunity) | |
686 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | |
687 | |
688 if (m_autoWrap || breakWords) { | |
689 // If we break only after white-space, consider the current char
acter | |
690 // as candidate width for this line. | |
691 bool lineWasTooWide = false; | |
692 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_curre
ntStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) { | |
693 float charWidth = textWidth(layoutText, m_current.offset(),
1, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallback
Fonts, &wordMeasurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0); | |
694 // Check if line is too big even without the extra space | |
695 // at the end of the line. If it is not, do nothing. | |
696 // If the line needs the extra whitespace to be too long, | |
697 // then move the line break to the space and skip all | |
698 // additional whitespace. | |
699 if (!m_width.fitsOnLine(charWidth)) { | |
700 lineWasTooWide = true; | |
701 m_lineBreak.moveTo(m_current.object(), m_current.offset(
), m_current.nextBreakablePosition()); | |
702 skipTrailingWhitespace(m_lineBreak, m_lineInfo); | |
703 } | 737 } |
704 } | 738 } |
705 if (lineWasTooWide || !m_width.fitsOnLine()) { | 739 // Didn't fit. Jump to the end unless there's still an opportuni
ty to collapse whitespace. |
706 if (m_lineBreak.atTextParagraphSeparator()) { | 740 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentChara
cterIsSpace || !previousCharacterIsSpace) { |
707 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | 741 m_atEnd = true; |
708 m_lineMidpointState.ensureCharacterGetsLineBox(m_cur
rent); | 742 return false; |
709 m_lineBreak.increment(); | 743 } |
710 m_lineInfo.setPreviousLineBrokeCleanly(true); | 744 } else { |
711 wordMeasurement.endOffset = m_lineBreak.offset(); | 745 if (!betweenWords || (midWordBreak && !m_autoWrap) || (breakAll
&& !m_currentCharacterIsSpace)) |
712 } | 746 m_width.addUncommittedWidth(-lastWidthMeasurement); |
713 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBr
eak.object().isText() && LineLayoutText(m_lineBreak.object()).textLength() && Li
neLayoutText(m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == soft
HyphenCharacter) | 747 if (hyphenWidth) { |
714 hyphenated = true; | 748 // Subtract the width of the soft hyphen out since we fit on
a line. |
715 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigne
d)wordMeasurement.endOffset && !wordMeasurement.width) { | 749 m_width.addUncommittedWidth(-hyphenWidth); |
716 if (charWidth) { | 750 hyphenWidth = 0; |
717 wordMeasurement.endOffset = m_lineBreak.offset(); | |
718 wordMeasurement.width = charWidth; | |
719 } | |
720 } | |
721 // Didn't fit. Jump to the end unless there's still an oppor
tunity to collapse whitespace. | |
722 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentC
haracterIsSpace || !previousCharacterIsSpace) { | |
723 m_atEnd = true; | |
724 return false; | |
725 } | |
726 } else { | |
727 if (!betweenWords || (midWordBreak && !m_autoWrap) || (break
All && !m_currentCharacterIsSpace)) | |
728 m_width.addUncommittedWidth(-lastWidthMeasurement); | |
729 if (hyphenWidth) { | |
730 // Subtract the width of the soft hyphen out since we fi
t on a line. | |
731 m_width.addUncommittedWidth(-hyphenWidth); | |
732 hyphenWidth = 0; | |
733 } | |
734 } | 751 } |
735 } | 752 } |
736 | |
737 if (c == newlineCharacter && m_preservesNewline) { | |
738 if (!stoppedIgnoringSpaces && m_current.offset()) | |
739 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | |
740 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur
rent.nextBreakablePosition()); | |
741 m_lineBreak.increment(); | |
742 m_lineInfo.setPreviousLineBrokeCleanly(true); | |
743 return true; | |
744 } | |
745 | |
746 if (m_autoWrap && betweenWords) { | |
747 m_width.commit(); | |
748 widthFromLastBreakingOpportunity = 0; | |
749 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur
rent.nextBreakablePosition()); | |
750 // Auto-wrapping text should not wrap in the middle of a word on
ce it has had an | |
751 // opportunity to break after a word. | |
752 breakWords = false; | |
753 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; | |
754 } | |
755 | |
756 if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c)
& (WTF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::
Mark_SpacingCombining))) { | |
757 // Remember this as a breakable position in case | |
758 // adding the end width forces a break. | |
759 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur
rent.nextBreakablePosition()); | |
760 midWordBreak &= (breakWords || breakAll); | |
761 } | |
762 | |
763 if (betweenWords) { | |
764 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | |
765 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure
ment.width) ? wordSpacing : 0; | |
766 lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.o
ffset() : lastSpace; | |
767 } | |
768 | |
769 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { | |
770 // If we encounter a newline, or if we encounter a | |
771 // second space, we need to go ahead and break up this | |
772 // run and enter a mode where we start collapsing spaces. | |
773 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { | |
774 m_ignoringSpaces = true; | |
775 | |
776 // We just entered a mode where we are ignoring | |
777 // spaces. Create a midpoint to terminate the run | |
778 // before the second space. | |
779 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpac
es); | |
780 m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMi
dpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); | |
781 } | |
782 } | |
783 } else if (m_ignoringSpaces) { | |
784 // Stop ignoring spaces and begin at this | |
785 // new point. | |
786 m_ignoringSpaces = false; | |
787 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | |
788 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement
s.last().width) ? wordSpacing : 0; | |
789 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in
any of the ignored spaces. | |
790 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.o
bject(), m_current.offset())); | |
791 } | 753 } |
792 | 754 |
793 if (isSVGText && m_current.offset()) { | 755 if (c == newlineCharacter && m_preservesNewline) { |
794 // Force creation of new InlineBoxes for each absolute positioned ch
aracter (those that start new text chunks). | 756 if (!stoppedIgnoringSpaces && m_current.offset()) |
795 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(
m_current.offset())) | |
796 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 757 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
| 758 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
| 759 m_lineBreak.increment(); |
| 760 m_lineInfo.setPreviousLineBrokeCleanly(true); |
| 761 return true; |
797 } | 762 } |
798 | 763 |
799 if (prohibitBreakInside) { | 764 if (m_autoWrap && betweenWords) { |
800 m_current.setNextBreakablePosition(layoutText.textLength()); | 765 m_width.commit(); |
801 prohibitBreakInside = false; | 766 widthFromLastBreakingOpportunity = 0; |
| 767 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
| 768 // Auto-wrapping text should not wrap in the middle of a word once i
t has had an |
| 769 // opportunity to break after a word. |
| 770 breakWords = false; |
| 771 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; |
802 } | 772 } |
803 | 773 |
804 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { | 774 if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (W
TF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark
_SpacingCombining))) { |
805 m_startOfIgnoredSpaces.setObject(m_current.object()); | 775 // Remember this as a breakable position in case |
806 m_startOfIgnoredSpaces.setOffset(m_current.offset()); | 776 // adding the end width forces a break. |
| 777 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
| 778 midWordBreak &= (breakWords || breakAll); |
807 } | 779 } |
808 | 780 |
809 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWa
p) { | 781 if (betweenWords) { |
810 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) | 782 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
811 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur
rent.nextBreakablePosition()); | 783 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement
.width) ? wordSpacing : 0; |
| 784 lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.offse
t() : lastSpace; |
812 } | 785 } |
813 | 786 |
814 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpac
es) | 787 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { |
815 m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.obj
ect())); | 788 // If we encounter a newline, or if we encounter a |
816 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsS
pace) | 789 // second space, we need to go ahead and break up this |
817 m_trailingObjects.clear(); | 790 // run and enter a mode where we start collapsing spaces. |
| 791 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { |
| 792 m_ignoringSpaces = true; |
818 | 793 |
| 794 // We just entered a mode where we are ignoring |
| 795 // spaces. Create a midpoint to terminate the run |
| 796 // before the second space. |
| 797 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces); |
| 798 m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpoi
ntState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); |
| 799 } |
| 800 } |
| 801 |
| 802 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCharact
erIsSpace, previousCharacterShouldCollapseIfPreWap); |
819 m_atStart = false; | 803 m_atStart = false; |
820 nextCharacter(c, lastCharacter, secondToLastCharacter); | 804 nextCharacter(c, lastCharacter, secondToLastCharacter); |
821 } | 805 } |
822 | 806 |
823 m_layoutTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo
LastCharacter); | 807 m_layoutTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo
LastCharacter); |
824 | 808 |
825 wordMeasurements.grow(wordMeasurements.size() + 1); | 809 wordMeasurements.grow(wordMeasurements.size() + 1); |
826 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 810 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
827 wordMeasurement.layoutText = layoutText; | 811 wordMeasurement.layoutText = layoutText; |
828 | 812 |
(...skipping 23 matching lines...) Expand all Loading... |
852 return true; | 836 return true; |
853 } | 837 } |
854 if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphenCharact
er) { | 838 if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphenCharact
er) { |
855 hyphenated = true; | 839 hyphenated = true; |
856 m_atEnd = true; | 840 m_atEnd = true; |
857 } | 841 } |
858 } | 842 } |
859 return false; | 843 return false; |
860 } | 844 } |
861 | 845 |
| 846 inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layou
tText, bool& prohibitBreakInside, bool previousCharacterIsSpace, bool previousCh
aracterShouldCollapseIfPreWap) |
| 847 { |
| 848 if (layoutText.isSVGInlineText() && m_current.offset()) { |
| 849 // Force creation of new InlineBoxes for each absolute positioned charac
ter (those that start new text chunks). |
| 850 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_cu
rrent.offset())) |
| 851 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
| 852 } |
| 853 if (prohibitBreakInside) { |
| 854 m_current.setNextBreakablePosition(layoutText.textLength()); |
| 855 prohibitBreakInside = false; |
| 856 } |
| 857 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { |
| 858 m_startOfIgnoredSpaces.setObject(m_current.object()); |
| 859 m_startOfIgnoredSpaces.setOffset(m_current.offset()); |
| 860 } |
| 861 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWap) { |
| 862 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) |
| 863 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current
.nextBreakablePosition()); |
| 864 } |
| 865 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces) |
| 866 m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.object(
))); |
| 867 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace
) |
| 868 m_trailingObjects.clear(); |
| 869 } |
| 870 |
| 871 |
862 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() | 872 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() |
863 { | 873 { |
864 bool checkForBreak = m_autoWrap; | 874 bool checkForBreak = m_autoWrap; |
865 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object(
) && m_currWS == NOWRAP) { | 875 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object(
) && m_currWS == NOWRAP) { |
866 checkForBreak = true; | 876 checkForBreak = true; |
867 } else if (m_nextObject && m_current.object().isText() && m_nextObject.isTex
t() && !m_nextObject.isBR() && (m_autoWrap || m_nextObject.style()->autoWrap()))
{ | 877 } else if (m_nextObject && m_current.object().isText() && m_nextObject.isTex
t() && !m_nextObject.isBR() && (m_autoWrap || m_nextObject.style()->autoWrap()))
{ |
868 if (m_autoWrap && m_currentCharacterIsSpace) { | 878 if (m_autoWrap && m_currentCharacterIsSpace) { |
869 checkForBreak = true; | 879 checkForBreak = true; |
870 } else { | 880 } else { |
871 LineLayoutText nextText(m_nextObject); | 881 LineLayoutText nextText(m_nextObject); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 | 944 |
935 if (style.textIndentType() == TextIndentHanging) | 945 if (style.textIndentType() == TextIndentHanging) |
936 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In
dentText; | 946 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In
dentText; |
937 | 947 |
938 return shouldIndentText; | 948 return shouldIndentText; |
939 } | 949 } |
940 | 950 |
941 } | 951 } |
942 | 952 |
943 #endif // BreakingContextInlineHeaders_h | 953 #endif // BreakingContextInlineHeaders_h |
OLD | NEW |