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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 , m_lineInfo(inLineInfo) | 65 , m_lineInfo(inLineInfo) |
66 , m_layoutTextInfo(inLayoutTextInfo) | 66 , m_layoutTextInfo(inLayoutTextInfo) |
67 , m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine) | 67 , m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine) |
68 , m_width(lineWidth) | 68 , m_width(lineWidth) |
69 , m_currWS(NORMAL) | 69 , m_currWS(NORMAL) |
70 , m_lastWS(NORMAL) | 70 , m_lastWS(NORMAL) |
71 , m_preservesNewline(false) | 71 , m_preservesNewline(false) |
72 , m_atStart(true) | 72 , m_atStart(true) |
73 , m_ignoringSpaces(false) | 73 , m_ignoringSpaces(false) |
74 , m_currentCharacterIsSpace(false) | 74 , m_currentCharacterIsSpace(false) |
75 , m_currentCharacterShouldCollapseIfPreWap(false) | 75 , m_currentCharacterShouldCollapseIfPreWrap(false) |
76 , m_appliedStartWidth(appliedStartWidth) | 76 , m_appliedStartWidth(appliedStartWidth) |
77 , m_includeEndWidth(true) | 77 , m_includeEndWidth(true) |
78 , m_autoWrap(false) | 78 , m_autoWrap(false) |
79 , m_autoWrapWasEverTrueOnLine(false) | 79 , m_autoWrapWasEverTrueOnLine(false) |
80 , m_floatsFitOnLine(true) | 80 , m_floatsFitOnLine(true) |
81 , m_collapseWhiteSpace(false) | 81 , m_collapseWhiteSpace(false) |
82 , m_startingNewParagraph(m_lineInfo.previousLineBrokeCleanly()) | 82 , m_startingNewParagraph(m_lineInfo.previousLineBrokeCleanly()) |
83 , m_allowImagesToBreak(!block.document().inQuirksMode() || !block.isTabl eCell() || !m_blockStyle->logicalWidth().isIntrinsicOrAuto()) | 83 , m_allowImagesToBreak(!block.document().inQuirksMode() || !block.isTabl eCell() || !m_blockStyle->logicalWidth().isIntrinsicOrAuto()) |
84 , m_atEnd(false) | 84 , m_atEnd(false) |
85 , m_lineMidpointState(resolver.midpointState()) | 85 , m_lineMidpointState(resolver.midpointState()) |
86 { | 86 { |
87 m_lineInfo.setPreviousLineBrokeCleanly(false); | 87 m_lineInfo.setPreviousLineBrokeCleanly(false); |
88 } | 88 } |
89 | 89 |
90 LayoutObject* currentObject() { return m_current.object(); } | 90 LayoutObject* currentObject() { return m_current.object(); } |
91 InlineIterator lineBreak() { return m_lineBreak; } | 91 InlineIterator lineBreak() { return m_lineBreak; } |
92 bool atEnd() { return m_atEnd; } | 92 bool atEnd() { return m_atEnd; } |
93 | 93 |
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); | |
105 bool canBreakAtWhitespace(bool breakWords, WordMeasurement&, bool stoppedIgn oringSpaces, bool& hyphenated, float charWidth, float& hyphenWidth, bool between Words, bool midWordBreak, bool breakAll, bool previousCharacterIsSpace, float la stWidthMeasurement, const LineLayoutText&, const Font&, bool applyWordSpacing, f loat wordSpacing); | |
106 bool trailingSpaceExceedsAvailableWidth(bool midWordBreak, const LineLayoutT ext&, WordMeasurement&, bool applyWordSpacing, bool wordSpacing, const Font&); | |
107 WordMeasurement& calculateWordWidth(WordMeasurements&, LineLayoutText&, floa t lastSpace, float& lastWidthMeasurement, float wordSpacingForWordMeasurement, c onst Font&, float wordTrailingSpaceWidth, UChar); | |
108 void stopIgnoringSpaces(unsigned& lastSpace); | |
104 void commitAndUpdateLineBreakIfNeeded(); | 109 void commitAndUpdateLineBreakIfNeeded(); |
105 InlineIterator handleEndOfLine(); | 110 InlineIterator handleEndOfLine(); |
106 | 111 |
107 void clearLineBreakIfFitsOnLine() | 112 void clearLineBreakIfFitsOnLine() |
108 { | 113 { |
109 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) | 114 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) |
110 m_lineBreak.clear(); | 115 m_lineBreak.clear(); |
111 } | 116 } |
112 | 117 |
113 private: | 118 private: |
(...skipping 20 matching lines...) Expand all Loading... | |
134 | 139 |
135 LineWidth m_width; | 140 LineWidth m_width; |
136 | 141 |
137 EWhiteSpace m_currWS; | 142 EWhiteSpace m_currWS; |
138 EWhiteSpace m_lastWS; | 143 EWhiteSpace m_lastWS; |
139 | 144 |
140 bool m_preservesNewline; | 145 bool m_preservesNewline; |
141 bool m_atStart; | 146 bool m_atStart; |
142 bool m_ignoringSpaces; | 147 bool m_ignoringSpaces; |
143 bool m_currentCharacterIsSpace; | 148 bool m_currentCharacterIsSpace; |
144 bool m_currentCharacterShouldCollapseIfPreWap; | 149 bool m_currentCharacterShouldCollapseIfPreWrap; |
145 bool m_appliedStartWidth; | 150 bool m_appliedStartWidth; |
146 bool m_includeEndWidth; | 151 bool m_includeEndWidth; |
147 bool m_autoWrap; | 152 bool m_autoWrap; |
148 bool m_autoWrapWasEverTrueOnLine; | 153 bool m_autoWrapWasEverTrueOnLine; |
149 bool m_floatsFitOnLine; | 154 bool m_floatsFitOnLine; |
150 bool m_collapseWhiteSpace; | 155 bool m_collapseWhiteSpace; |
151 bool m_startingNewParagraph; | 156 bool m_startingNewParagraph; |
152 bool m_allowImagesToBreak; | 157 bool m_allowImagesToBreak; |
153 bool m_atEnd; | 158 bool m_atEnd; |
154 | 159 |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 m_lineInfo.setEmpty(false, m_block, &m_width); | 447 m_lineInfo.setEmpty(false, m_block, &m_width); |
443 if (m_ignoringSpaces) { | 448 if (m_ignoringSpaces) { |
444 // If we are in a run of ignored spaces then ensure we get a linebox if lineboxes are eventually | 449 // If we are in a run of ignored spaces then ensure we get a linebox if lineboxes are eventually |
445 // created for the line... | 450 // created for the line... |
446 m_trailingObjects.clear(); | 451 m_trailingObjects.clear(); |
447 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, m_current.obj ect()); | 452 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, m_current.obj ect()); |
448 } else if (m_blockStyle->collapseWhiteSpace() && m_resolver.position().o bject() == m_current.object() | 453 } else if (m_blockStyle->collapseWhiteSpace() && m_resolver.position().o bject() == m_current.object() |
449 && shouldSkipWhitespaceAfterStartObject(m_block, m_current.object(), m_lineMidpointState)) { | 454 && shouldSkipWhitespaceAfterStartObject(m_block, m_current.object(), m_lineMidpointState)) { |
450 // If this object is at the start of the line, we need to behave lik e list markers and | 455 // If this object is at the start of the line, we need to behave lik e list markers and |
451 // start ignoring spaces. | 456 // start ignoring spaces. |
452 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = true; | 457 m_currentCharacterShouldCollapseIfPreWrap = m_currentCharacterIsSpac e = true; |
453 m_ignoringSpaces = true; | 458 m_ignoringSpaces = true; |
454 } else { | 459 } else { |
455 // If we are after a trailing space but aren't ignoring spaces yet t hen ensure we get a linebox | 460 // If we are after a trailing space but aren't ignoring spaces yet t hen ensure we get a linebox |
456 // if we encounter collapsible whitepace. | 461 // if we encounter collapsible whitepace. |
457 m_trailingObjects.appendObjectIfNeeded(m_current.object()); | 462 m_trailingObjects.appendObjectIfNeeded(m_current.object()); |
458 } | 463 } |
459 } | 464 } |
460 | 465 |
461 m_width.addUncommittedWidth((inlineLogicalWidthFromAncestorsIfNeeded(m_curre nt.object()) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBo x)).toFloat()); | 466 m_width.addUncommittedWidth((inlineLogicalWidthFromAncestorsIfNeeded(m_curre nt.object()) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBo x)).toFloat()); |
462 } | 467 } |
(...skipping 11 matching lines...) Expand all Loading... | |
474 && (!m_current.object().isRubyRun() || toLayoutRubyRun(m_current.object( ))->canBreakBefore(m_layoutTextInfo.m_lineBreakIterator))) { | 479 && (!m_current.object().isRubyRun() || toLayoutRubyRun(m_current.object( ))->canBreakBefore(m_layoutTextInfo.m_lineBreakIterator))) { |
475 m_width.commit(); | 480 m_width.commit(); |
476 m_lineBreak.moveToStartOf(m_current.object()); | 481 m_lineBreak.moveToStartOf(m_current.object()); |
477 } | 482 } |
478 | 483 |
479 if (m_ignoringSpaces) | 484 if (m_ignoringSpaces) |
480 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.objec t(), 0)); | 485 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.objec t(), 0)); |
481 | 486 |
482 m_lineInfo.setEmpty(false, m_block, &m_width); | 487 m_lineInfo.setEmpty(false, m_block, &m_width); |
483 m_ignoringSpaces = false; | 488 m_ignoringSpaces = false; |
484 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = false ; | 489 m_currentCharacterShouldCollapseIfPreWrap = m_currentCharacterIsSpace = fals e; |
485 m_trailingObjects.clear(); | 490 m_trailingObjects.clear(); |
486 | 491 |
487 // Optimize for a common case. If we can't find whitespace after the list | 492 // Optimize for a common case. If we can't find whitespace after the list |
488 // item, then this is all moot. | 493 // item, then this is all moot. |
489 LayoutUnit replacedLogicalWidth = m_block.logicalWidthForChild(replacedBox) + m_block.marginStartForChild(replacedBox) + m_block.marginEndForChild(replacedB ox) + inlineLogicalWidthFromAncestorsIfNeeded(m_current.object()); | 494 LayoutUnit replacedLogicalWidth = m_block.logicalWidthForChild(replacedBox) + m_block.marginStartForChild(replacedBox) + m_block.marginEndForChild(replacedB ox) + inlineLogicalWidthFromAncestorsIfNeeded(m_current.object()); |
490 if (m_current.object().isListMarker()) { | 495 if (m_current.object().isListMarker()) { |
491 if (m_blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfterStart Object(m_block, m_current.object(), m_lineMidpointState)) { | 496 if (m_blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfterStart Object(m_block, m_current.object(), m_lineMidpointState)) { |
492 // Like with inline flows, we start ignoring spaces to make sure tha t any | 497 // Like with inline flows, we start ignoring spaces to make sure tha t any |
493 // additional spaces we see will be discarded. | 498 // additional spaces we see will be discarded. |
494 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = true; | 499 m_currentCharacterShouldCollapseIfPreWrap = m_currentCharacterIsSpac e = true; |
495 m_ignoringSpaces = true; | 500 m_ignoringSpaces = true; |
496 } | 501 } |
497 if (LineLayoutListMarker(m_current.object()).isInside()) | 502 if (LineLayoutListMarker(m_current.object()).isInside()) |
498 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); | 503 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); |
499 } else { | 504 } else { |
500 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); | 505 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); |
501 } | 506 } |
502 if (m_current.object().isRubyRun()) | 507 if (m_current.object().isRubyRun()) |
503 m_width.applyOverhang(LineLayoutRubyRun(m_current.object()), m_lastObjec t, m_nextObject); | 508 m_width.applyOverhang(LineLayoutRubyRun(m_current.object()), m_lastObjec t, m_nextObject); |
504 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEM ENT CHARACTER) for replaced element. | 509 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEM ENT CHARACTER) for replaced element. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 return font.width(run, fallbackFonts, glyphBounds); | 543 return font.width(run, fallbackFonts, glyphBounds); |
539 } | 544 } |
540 | 545 |
541 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool & hyphenated) | 546 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool & hyphenated) |
542 { | 547 { |
543 if (!m_current.offset()) | 548 if (!m_current.offset()) |
544 m_appliedStartWidth = false; | 549 m_appliedStartWidth = false; |
545 | 550 |
546 LineLayoutText layoutText(m_current.object()); | 551 LineLayoutText layoutText(m_current.object()); |
547 | 552 |
548 bool isSVGText = layoutText.isSVGInlineText(); | |
549 | |
550 // If we have left a no-wrap inline and entered an autowrap inline while ign oring spaces | 553 // 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. | 554 // 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) { | 555 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { |
553 m_width.commit(); | 556 m_width.commit(); |
554 m_lineBreak.moveToStartOf(m_current.object()); | 557 m_lineBreak.moveToStartOf(m_current.object()); |
555 } | 558 } |
556 | 559 |
557 const ComputedStyle& style = layoutText.styleRef(m_lineInfo.isFirstLine()); | 560 const ComputedStyle& style = layoutText.styleRef(m_lineInfo.isFirstLine()); |
558 const Font& font = style.font(); | 561 const Font& font = style.font(); |
559 | 562 |
(...skipping 13 matching lines...) Expand all Loading... | |
573 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is CombineText() && LineLayoutTextCombine(layoutText).isCombined(); | 576 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && layoutText.is CombineText() && LineLayoutTextCombine(layoutText).isCombined(); |
574 | 577 |
575 // This is currently only used for word-break: break-all, specifically for t he case | 578 // 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 | 579 // 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. | 580 // 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 | 581 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html |
579 float widthMeasurementAtLastBreakOpportunity = 0; | 582 float widthMeasurementAtLastBreakOpportunity = 0; |
580 | 583 |
581 float hyphenWidth = 0; | 584 float hyphenWidth = 0; |
582 | 585 |
583 if (isSVGText) { | 586 if (layoutText.isSVGInlineText()) { |
584 breakWords = false; | 587 breakWords = false; |
585 breakAll = false; | 588 breakAll = false; |
586 keepAll = false; | 589 keepAll = false; |
587 } | 590 } |
588 | 591 |
589 if (layoutText.isWordBreak()) { | 592 if (layoutText.isWordBreak()) { |
590 m_width.commit(); | 593 m_width.commit(); |
591 m_lineBreak.moveToStartOf(m_current.object()); | 594 m_lineBreak.moveToStartOf(m_current.object()); |
592 ASSERT(m_current.offset() == layoutText.textLength()); | 595 ASSERT(m_current.offset() == layoutText.textLength()); |
593 } | 596 } |
594 | 597 |
595 if (m_layoutTextInfo.m_text != layoutText) { | 598 if (m_layoutTextInfo.m_text != layoutText) { |
596 m_layoutTextInfo.m_text = layoutText; | 599 m_layoutTextInfo.m_text = layoutText; |
597 m_layoutTextInfo.m_font = &font; | 600 m_layoutTextInfo.m_font = &font; |
598 m_layoutTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(layou tText.text(), style.locale()); | 601 m_layoutTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(layou tText.text(), style.locale()); |
599 } else if (m_layoutTextInfo.m_font != &font) { | 602 } else if (m_layoutTextInfo.m_font != &font) { |
600 m_layoutTextInfo.m_font = &font; | 603 m_layoutTextInfo.m_font = &font; |
601 } | 604 } |
602 | 605 |
603 // Non-zero only when kerning is enabled, in which case we measure | 606 // Non-zero only when kerning is enabled, in which case we measure |
604 // words with their trailing space, then subtract its width. | 607 // words with their trailing space, then subtract its width. |
605 float wordTrailingSpaceWidth = (font.fontDescription().typesettingFeatures() & Kerning) ? | 608 float wordTrailingSpaceWidth = (font.fontDescription().typesettingFeatures() & Kerning) ? |
606 font.width(constructTextRun(font, &spaceCharacter, 1, style, style.direc tion())) + wordSpacing | 609 font.width(constructTextRun(font, &spaceCharacter, 1, style, style.direc tion())) + wordSpacing |
607 : 0; | 610 : 0; |
608 | 611 |
609 UChar lastCharacter = m_layoutTextInfo.m_lineBreakIterator.lastCharacter(); | 612 UChar lastCharacter = m_layoutTextInfo.m_lineBreakIterator.lastCharacter(); |
610 UChar secondToLastCharacter = m_layoutTextInfo.m_lineBreakIterator.secondToL astCharacter(); | 613 UChar secondToLastCharacter = m_layoutTextInfo.m_lineBreakIterator.secondToL astCharacter(); |
611 for (; m_current.offset() < layoutText.textLength(); m_current.fastIncrement InTextNode()) { | 614 for (; m_current.offset() < layoutText.textLength(); m_current.fastIncrement InTextNode()) { |
612 bool previousCharacterIsSpace = m_currentCharacterIsSpace; | 615 bool previousCharacterIsSpace = m_currentCharacterIsSpace; |
613 bool previousCharacterShouldCollapseIfPreWap = m_currentCharacterShouldC ollapseIfPreWap; | 616 bool previousCharacterShouldCollapseIfPreWap = m_currentCharacterShouldC ollapseIfPreWrap; |
614 UChar c = m_current.current(); | 617 UChar c = m_current.current(); |
615 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = c == spaceCharacter || c == tabulationCharacter || (!m_preservesNewline && (c == newlineCharacter)); | 618 m_currentCharacterShouldCollapseIfPreWrap = m_currentCharacterIsSpace = c == spaceCharacter || c == tabulationCharacter || (!m_preservesNewline && (c == newlineCharacter)); |
616 | 619 |
617 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) | 620 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) |
618 m_lineInfo.setEmpty(false, m_block, &m_width); | 621 m_lineInfo.setEmpty(false, m_block, &m_width); |
619 | 622 |
620 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth) { | 623 if (c == softHyphenCharacter && m_autoWrap && !hyphenWidth) { |
621 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); | 624 hyphenWidth = layoutText.hyphenWidth(font, textDirectionFromUnicode( m_resolver.position().direction())); |
622 m_width.addUncommittedWidth(hyphenWidth); | 625 m_width.addUncommittedWidth(hyphenWidth); |
623 } | 626 } |
624 | 627 |
625 bool applyWordSpacing = false; | 628 bool applyWordSpacing = false; |
626 | 629 |
630 // Determine if we should try breaking in the middle of a word. | |
627 if (breakWords && !midWordBreak) { | 631 if (breakWords && !midWordBreak) { |
628 widthFromLastBreakingOpportunity += charWidth; | 632 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)); | 633 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); | 634 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(); | 635 midWordBreak = m_width.committedWidth() + widthFromLastBreakingOppor tunity + charWidth > m_width.availableWidth(); |
632 } | 636 } |
633 | 637 |
638 // Determine if we are in the whitespace between words. | |
634 int nextBreakablePosition = m_current.nextBreakablePosition(); | 639 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)); | 640 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); | 641 m_current.setNextBreakablePosition(nextBreakablePosition); |
637 | 642 |
638 if (betweenWords || midWordBreak) { | 643 // 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; | 644 if (!betweenWords && !midWordBreak) { |
640 if (m_ignoringSpaces) { | 645 if (m_ignoringSpaces) { |
641 lastSpaceWordSpacing = 0; | 646 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
642 if (!m_currentCharacterIsSpace) { | 647 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure ments.last().width) ? wordSpacing : 0; |
643 // Stop ignoring spaces and begin at this | 648 stopIgnoringSpaces(lastSpace); |
644 // new point. | |
645 m_ignoringSpaces = false; | |
646 wordSpacingForWordMeasurement = 0; | |
647 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces. | |
648 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_c urrent.object(), m_current.offset())); | |
649 stoppedIgnoringSpaces = true; | |
650 } else { | |
651 // Just keep ignoring these spaces. | |
652 nextCharacter(c, lastCharacter, secondToLastCharacter); | |
653 continue; | |
654 } | |
655 } | 649 } |
656 | 650 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCha racterIsSpace, previousCharacterShouldCollapseIfPreWap); |
657 wordMeasurements.grow(wordMeasurements.size() + 1); | 651 m_atStart = false; |
658 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 652 nextCharacter(c, lastCharacter, secondToLastCharacter); |
659 | 653 continue; |
660 wordMeasurement.layoutText = layoutText; | |
661 wordMeasurement.endOffset = m_current.offset(); | |
662 wordMeasurement.startOffset = lastSpace; | |
663 | |
664 float lastWidthMeasurement; | |
665 if (wordTrailingSpaceWidth && c == spaceCharacter) | |
666 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_curren t.offset() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpac eWidth; | |
667 else | |
668 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_curren t.offset() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wor dMeasurement.fallbackFonts, &wordMeasurement.glyphBounds); | |
669 | |
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 } | |
704 } | |
705 if (lineWasTooWide || !m_width.fitsOnLine()) { | |
706 if (m_lineBreak.atTextParagraphSeparator()) { | |
707 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | |
708 m_lineMidpointState.ensureCharacterGetsLineBox(m_cur rent); | |
709 m_lineBreak.increment(); | |
710 m_lineInfo.setPreviousLineBrokeCleanly(true); | |
711 wordMeasurement.endOffset = m_lineBreak.offset(); | |
712 } | |
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) | |
714 hyphenated = true; | |
715 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigne d)wordMeasurement.endOffset && !wordMeasurement.width) { | |
716 if (charWidth) { | |
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 } | |
735 } | |
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 } | 654 } |
792 | 655 |
793 if (isSVGText && m_current.offset()) { | 656 // If we're ignoring space and we're at a collapsible space such as a sp ace or tab, continue to the next character. |
794 // Force creation of new InlineBoxes for each absolute positioned ch aracter (those that start new text chunks). | 657 bool stoppedIgnoringSpaces = false; |
795 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk( m_current.offset())) | 658 if (m_ignoringSpaces && m_currentCharacterIsSpace) { |
796 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 659 lastSpaceWordSpacing = 0; |
660 // Just keep ignoring these spaces. | |
661 nextCharacter(c, lastCharacter, secondToLastCharacter); | |
662 continue; | |
797 } | 663 } |
798 | 664 |
799 if (prohibitBreakInside) { | 665 // So we're in the first whitespace after a word or in whitespace that w e don't collapse, which means we may have a breaking opportunity here. |
800 m_current.setNextBreakablePosition(layoutText.textLength()); | 666 |
801 prohibitBreakInside = false; | 667 // If we're here and we're ignoring spaces then the current character is n't a space, it's some of other form of whitespace. Stop ignoring spaces. |
668 if (m_ignoringSpaces) { | |
669 lastSpaceWordSpacing = 0; | |
670 wordSpacingForWordMeasurement = 0; | |
671 stoppedIgnoringSpaces = true; | |
672 stopIgnoringSpaces(lastSpace); | |
802 } | 673 } |
803 | 674 |
804 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { | 675 // Update our tally of the width since the last breakable position with the width of the word we're now at the end of. |
805 m_startOfIgnoredSpaces.setObject(m_current.object()); | 676 float lastWidthMeasurement; |
806 m_startOfIgnoredSpaces.setOffset(m_current.offset()); | 677 WordMeasurement& wordMeasurement = calculateWordWidth(wordMeasurements, layoutText, lastSpace, lastWidthMeasurement, wordSpacingForWordMeasurement, font , wordTrailingSpaceWidth, c); |
678 lastWidthMeasurement += lastSpaceWordSpacing; | |
679 m_width.addUncommittedWidth(lastWidthMeasurement); | |
680 | |
681 // We keep track of the total width contributed by trailing space as we often want to exclude it when determining | |
682 // if a run fits on a line. | |
683 if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharact erIsSpace && lastWidthMeasurement) | |
684 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); | |
685 | |
686 // If this is the end of the first word in run of text then make sure we apply the width from any leading inlines. | |
687 // For example: '<span style="margin-left: 5px;"><span style="margin-lef t: 10px;">FirstWord</span></span>' would | |
688 // apply a width of 15px from the two span ancestors. | |
689 if (!m_appliedStartWidth) { | |
690 m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded( m_current.object(), true, false).toFloat()); | |
691 m_appliedStartWidth = true; | |
807 } | 692 } |
808 | 693 |
809 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWa p) { | 694 // If we haven't hit a breakable position yet and already don't fit on t he line try to move below any floats. |
810 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) | 695 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) |
811 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_cur rent.nextBreakablePosition()); | 696 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
697 | |
698 // If there is a soft-break available at this whitespace position then t ake it. | |
699 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; | |
700 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpa ces, hyphenated, charWidth, hyphenWidth, betweenWords, midWordBreak, breakAll, p reviousCharacterIsSpace, lastWidthMeasurement, layoutText, font, applyWordSpacin g, wordSpacing)) | |
701 return false; | |
702 | |
703 // If there is a hard-break available at this whitespace position then t ake it. | |
704 if (c == newlineCharacter && m_preservesNewline) { | |
705 if (!stoppedIgnoringSpaces && m_current.offset()) | |
706 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | |
707 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current .nextBreakablePosition()); | |
708 m_lineBreak.increment(); | |
709 m_lineInfo.setPreviousLineBrokeCleanly(true); | |
710 return true; | |
812 } | 711 } |
813 | 712 |
814 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpac es) | 713 // Auto-wrapping text should not wrap in the middle of a word once it ha s had an |
815 m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.obj ect())); | 714 // opportunity to break after a word. |
816 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsS pace) | 715 if (m_autoWrap && betweenWords) { |
817 m_trailingObjects.clear(); | 716 m_width.commit(); |
717 widthFromLastBreakingOpportunity = 0; | |
718 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current .nextBreakablePosition()); | |
719 breakWords = false; | |
720 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; | |
721 } | |
818 | 722 |
723 // Remember this as a breakable position in case adding the end width fo rces a break. | |
724 if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (W TF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark _SpacingCombining))) { | |
725 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current .nextBreakablePosition()); | |
726 midWordBreak &= (breakWords || breakAll); | |
727 } | |
728 | |
729 if (betweenWords) { | |
730 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | |
731 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement .width) ? wordSpacing : 0; | |
732 lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.offse t() : lastSpace; | |
733 } | |
734 | |
735 // If we encounter a newline, or if we encounter a second space, we need to go ahead and break up this run and enter a mode where we start collapsing sp aces. | |
736 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { | |
737 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { | |
738 m_ignoringSpaces = true; | |
739 // We just entered a mode where we are ignoring spaces. Create a midpoint to terminate the run before the second space. | |
kojii
2015/12/08 08:02:10
nit: two spaces between "run" and "before".
| |
740 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces); | |
741 m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpoi ntState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); | |
742 } | |
743 } | |
744 | |
745 prepareForNextCharacter(layoutText, prohibitBreakInside, previousCharact erIsSpace, previousCharacterShouldCollapseIfPreWap); | |
819 m_atStart = false; | 746 m_atStart = false; |
820 nextCharacter(c, lastCharacter, secondToLastCharacter); | 747 nextCharacter(c, lastCharacter, secondToLastCharacter); |
821 } | 748 } |
822 | 749 |
823 m_layoutTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo LastCharacter); | 750 m_layoutTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo LastCharacter); |
824 | 751 |
825 wordMeasurements.grow(wordMeasurements.size() + 1); | 752 wordMeasurements.grow(wordMeasurements.size() + 1); |
826 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 753 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
827 wordMeasurement.layoutText = layoutText; | 754 wordMeasurement.layoutText = layoutText; |
828 | 755 |
(...skipping 23 matching lines...) Expand all Loading... | |
852 return true; | 779 return true; |
853 } | 780 } |
854 if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphenCharact er) { | 781 if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphenCharact er) { |
855 hyphenated = true; | 782 hyphenated = true; |
856 m_atEnd = true; | 783 m_atEnd = true; |
857 } | 784 } |
858 } | 785 } |
859 return false; | 786 return false; |
860 } | 787 } |
861 | 788 |
789 inline void BreakingContext::stopIgnoringSpaces(unsigned& lastSpace) | |
790 { | |
791 m_ignoringSpaces = false; | |
792 lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of t he ignored spaces. | |
793 m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset())); | |
794 } | |
795 | |
796 inline WordMeasurement& BreakingContext::calculateWordWidth(WordMeasurements& wo rdMeasurements, LineLayoutText& layoutText, float lastSpace, float& lastWidthMea surement, float wordSpacingForWordMeasurement, const Font& font, float wordTrail ingSpaceWidth, UChar c) | |
kojii
2015/12/08 08:02:10
Shouldn't lastSpace be unsigned rather than float?
| |
797 { | |
798 wordMeasurements.grow(wordMeasurements.size() + 1); | |
799 WordMeasurement& wordMeasurement = wordMeasurements.last(); | |
800 wordMeasurement.layoutText = layoutText; | |
801 wordMeasurement.endOffset = m_current.offset(); | |
802 wordMeasurement.startOffset = lastSpace; | |
803 | |
804 if (wordTrailingSpaceWidth && c == spaceCharacter) | |
805 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset () + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMea surement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpaceWidth; | |
806 else | |
807 lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset () - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasure ment.fallbackFonts, &wordMeasurement.glyphBounds); | |
808 | |
809 wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMeasurement ; | |
810 wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0); | |
811 return wordMeasurement; | |
812 } | |
813 | |
814 inline bool BreakingContext::trailingSpaceExceedsAvailableWidth(bool midWordBrea k, const LineLayoutText& layoutText, WordMeasurement& wordMeasurement, bool appl yWordSpacing, bool wordSpacing, const Font& font) | |
815 { | |
816 // If we break only after white-space, consider the current character | |
817 // as candidate width for this line. | |
818 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentStyle->bre akOnlyAfterWhiteSpace() && !midWordBreak) { | |
819 float charWidth = textWidth(layoutText, m_current.offset(), 1, font, m_w idth.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &word Measurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0); | |
820 // Check if line is too big even without the extra space | |
821 // at the end of the line. If it is not, do nothing. | |
822 // If the line needs the extra whitespace to be too long, | |
823 // then move the line break to the space and skip all | |
824 // additional whitespace. | |
825 if (!m_width.fitsOnLine(charWidth)) { | |
826 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current .nextBreakablePosition()); | |
827 skipTrailingWhitespace(m_lineBreak, m_lineInfo); | |
828 return true; | |
829 } | |
830 } | |
831 return false; | |
832 } | |
833 | |
834 inline bool BreakingContext::canBreakAtWhitespace(bool breakWords, WordMeasureme nt& wordMeasurement, bool stoppedIgnoringSpaces, bool& hyphenated, float charWid th, float& hyphenWidth, bool betweenWords, bool midWordBreak, bool breakAll, boo l previousCharacterIsSpace, float lastWidthMeasurement, const LineLayoutText& la youtText, const Font& font, bool applyWordSpacing, float wordSpacing) | |
835 { | |
836 if (!m_autoWrap && !breakWords) | |
837 return false; | |
838 | |
839 // If we break only after white-space, consider the current character | |
840 // as candidate width for this line. | |
841 if (trailingSpaceExceedsAvailableWidth(midWordBreak, layoutText, wordMeasure ment, applyWordSpacing, wordSpacing, font) || !m_width.fitsOnLine()) { | |
842 if (m_lineBreak.atTextParagraphSeparator()) { | |
843 if (!stoppedIgnoringSpaces && m_current.offset() > 0) | |
844 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | |
845 m_lineBreak.increment(); | |
846 m_lineInfo.setPreviousLineBrokeCleanly(true); | |
847 wordMeasurement.endOffset = m_lineBreak.offset(); | |
848 } | |
849 if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.object() .isText() && LineLayoutText(m_lineBreak.object()).textLength() && LineLayoutText (m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == softHyphenCharac ter) | |
850 hyphenated = true; | |
851 if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasur ement.endOffset && !wordMeasurement.width) { | |
852 if (charWidth) { | |
853 wordMeasurement.endOffset = m_lineBreak.offset(); | |
854 wordMeasurement.width = charWidth; | |
855 } | |
856 } | |
857 // Didn't fit. Jump to the end unless there's still an opportunity to co llapse whitespace. | |
858 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSp ace || !previousCharacterIsSpace) { | |
859 m_atEnd = true; | |
860 return true; | |
861 } | |
862 } else { | |
863 if (!betweenWords || (midWordBreak && !m_autoWrap) || (breakAll && !m_cu rrentCharacterIsSpace)) | |
864 m_width.addUncommittedWidth(-lastWidthMeasurement); | |
865 if (hyphenWidth) { | |
866 // Subtract the width of the soft hyphen out since we fit on a line. | |
867 m_width.addUncommittedWidth(-hyphenWidth); | |
868 hyphenWidth = 0; | |
869 } | |
870 } | |
871 return false; | |
872 } | |
873 | |
874 inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layou tText, bool& prohibitBreakInside, bool previousCharacterIsSpace, bool previousCh aracterShouldCollapseIfPreWap) | |
875 { | |
876 if (layoutText.isSVGInlineText() && m_current.offset()) { | |
877 // Force creation of new InlineBoxes for each absolute positioned charac ter (those that start new text chunks). | |
878 if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_cu rrent.offset())) | |
879 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | |
880 } | |
881 | |
882 if (prohibitBreakInside) { | |
883 m_current.setNextBreakablePosition(layoutText.textLength()); | |
884 prohibitBreakInside = false; | |
885 } | |
886 | |
887 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { | |
888 m_startOfIgnoredSpaces.setObject(m_current.object()); | |
889 m_startOfIgnoredSpaces.setOffset(m_current.offset()); | |
890 } | |
891 | |
892 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWap) { | |
893 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) | |
894 m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current .nextBreakablePosition()); | |
895 } | |
896 | |
897 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces) | |
898 m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.object( ))); | |
899 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace ) | |
900 m_trailingObjects.clear(); | |
901 } | |
902 | |
862 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() | 903 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded() |
863 { | 904 { |
864 bool checkForBreak = m_autoWrap; | 905 bool checkForBreak = m_autoWrap; |
865 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object( ) && m_currWS == NOWRAP) { | 906 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.object( ) && m_currWS == NOWRAP) { |
866 checkForBreak = true; | 907 checkForBreak = true; |
867 } else if (m_nextObject && m_current.object().isText() && m_nextObject.isTex t() && !m_nextObject.isBR() && (m_autoWrap || m_nextObject.style()->autoWrap())) { | 908 } 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) { | 909 if (m_autoWrap && m_currentCharacterIsSpace) { |
869 checkForBreak = true; | 910 checkForBreak = true; |
870 } else { | 911 } else { |
871 LineLayoutText nextText(m_nextObject); | 912 LineLayoutText nextText(m_nextObject); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
934 | 975 |
935 if (style.textIndentType() == TextIndentHanging) | 976 if (style.textIndentType() == TextIndentHanging) |
936 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In dentText; | 977 shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : In dentText; |
937 | 978 |
938 return shouldIndentText; | 979 return shouldIndentText; |
939 } | 980 } |
940 | 981 |
941 } | 982 } |
942 | 983 |
943 #endif // BreakingContextInlineHeaders_h | 984 #endif // BreakingContextInlineHeaders_h |
OLD | NEW |