| OLD | NEW |
| 1 /* | 1 /* |
| 2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2000 Dirk Mueller (mueller@kde.org) | 3 * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
| 6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) | 6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 plainTextBuilder.append(text); | 315 plainTextBuilder.append(text); |
| 316 if (textBox->nextTextBox() && textBox->nextTextBox()->start() > textBox-
>end() && text.length() && !text.right(1).containsOnlyWhitespace()) | 316 if (textBox->nextTextBox() && textBox->nextTextBox()->start() > textBox-
>end() && text.length() && !text.right(1).containsOnlyWhitespace()) |
| 317 plainTextBuilder.append(spaceCharacter); | 317 plainTextBuilder.append(spaceCharacter); |
| 318 } | 318 } |
| 319 return plainTextBuilder.toString(); | 319 return plainTextBuilder.toString(); |
| 320 } | 320 } |
| 321 | 321 |
| 322 void LayoutText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
latedOffset) const | 322 void LayoutText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
latedOffset) const |
| 323 { | 323 { |
| 324 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) | 324 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) |
| 325 rects.append(enclosingIntRect(FloatRect(FloatPoint(accumulatedOffset) +
box->topLeft().toFloatPoint(), box->size().toFloatSize()))); | 325 rects.append(enclosingIntRect(LayoutRect(LayoutPoint(accumulatedOffset)
+ box->topLeft(), box->size()))); |
| 326 } | 326 } |
| 327 | 327 |
| 328 static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigne
d end, bool useSelectionHeight) | 328 static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigne
d end, bool useSelectionHeight) |
| 329 { | 329 { |
| 330 unsigned realEnd = std::min(box->end() + 1, end); | 330 unsigned realEnd = std::min(box->end() + 1, end); |
| 331 LayoutRect r = box->localSelectionRect(start, realEnd); | 331 LayoutRect r = box->localSelectionRect(start, realEnd); |
| 332 if (r.height()) { | 332 if (r.height()) { |
| 333 if (!useSelectionHeight) { | 333 if (!useSelectionHeight) { |
| 334 // Change the height and y position (or width and x for vertical tex
t) | 334 // Change the height and y position (or width and x for vertical tex
t) |
| 335 // because selectionRect uses selection-specific values. | 335 // because selectionRect uses selection-specific values. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 354 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but | 354 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but |
| 355 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. | 355 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. |
| 356 ASSERT(end == UINT_MAX || end <= INT_MAX); | 356 ASSERT(end == UINT_MAX || end <= INT_MAX); |
| 357 ASSERT(start <= INT_MAX); | 357 ASSERT(start <= INT_MAX); |
| 358 start = std::min(start, static_cast<unsigned>(INT_MAX)); | 358 start = std::min(start, static_cast<unsigned>(INT_MAX)); |
| 359 end = std::min(end, static_cast<unsigned>(INT_MAX)); | 359 end = std::min(end, static_cast<unsigned>(INT_MAX)); |
| 360 | 360 |
| 361 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 361 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 362 // Note: box->end() returns the index of the last character, not the ind
ex past it | 362 // Note: box->end() returns the index of the last character, not the ind
ex past it |
| 363 if (start <= box->start() && box->end() < end) { | 363 if (start <= box->start() && box->end() < end) { |
| 364 FloatRect r = box->calculateBoundaries().toFloatRect(); | 364 FloatRect r(box->calculateBoundaries()); |
| 365 if (useSelectionHeight) { | 365 if (useSelectionHeight) { |
| 366 LayoutRect selectionRect = box->localSelectionRect(start, end); | 366 LayoutRect selectionRect = box->localSelectionRect(start, end); |
| 367 if (box->isHorizontal()) { | 367 if (box->isHorizontal()) { |
| 368 r.setHeight(selectionRect.height().toFloat()); | 368 r.setHeight(selectionRect.height().toFloat()); |
| 369 r.setY(selectionRect.y().toFloat()); | 369 r.setY(selectionRect.y().toFloat()); |
| 370 } else { | 370 } else { |
| 371 r.setWidth(selectionRect.width().toFloat()); | 371 r.setWidth(selectionRect.width().toFloat()); |
| 372 r.setX(selectionRect.x().toFloat()); | 372 r.setX(selectionRect.x().toFloat()); |
| 373 } | 373 } |
| 374 } | 374 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 402 if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= trunca
tion) | 402 if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= trunca
tion) |
| 403 return ellipsis->selectionRect(); | 403 return ellipsis->selectionRect(); |
| 404 } | 404 } |
| 405 | 405 |
| 406 return IntRect(); | 406 return IntRect(); |
| 407 } | 407 } |
| 408 | 408 |
| 409 void LayoutText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed, Clippin
gOption option) const | 409 void LayoutText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed, Clippin
gOption option) const |
| 410 { | 410 { |
| 411 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 411 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 412 FloatRect boundaries = box->calculateBoundaries().toFloatRect(); | 412 FloatRect boundaries(box->calculateBoundaries()); |
| 413 | 413 |
| 414 // Shorten the width of this text box if it ends in an ellipsis. | 414 // Shorten the width of this text box if it ends in an ellipsis. |
| 415 // FIXME: ellipsisRectForBox should switch to return FloatRect soon with
the subpixellayout branch. | 415 // FIXME: ellipsisRectForBox should switch to return FloatRect soon with
the subpixellayout branch. |
| 416 IntRect ellipsisRect = (option == ClipToEllipsis) ? ellipsisRectForBox(b
ox, 0, textLength()) : IntRect(); | 416 IntRect ellipsisRect = (option == ClipToEllipsis) ? ellipsisRectForBox(b
ox, 0, textLength()) : IntRect(); |
| 417 if (!ellipsisRect.isEmpty()) { | 417 if (!ellipsisRect.isEmpty()) { |
| 418 if (style()->isHorizontalWritingMode()) | 418 if (style()->isHorizontalWritingMode()) |
| 419 boundaries.setWidth(ellipsisRect.maxX() - boundaries.x()); | 419 boundaries.setWidth(ellipsisRect.maxX() - boundaries.x()); |
| 420 else | 420 else |
| 421 boundaries.setHeight(ellipsisRect.maxY() - boundaries.y()); | 421 boundaries.setHeight(ellipsisRect.maxY() - boundaries.y()); |
| 422 } | 422 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 437 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but | 437 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but |
| 438 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. | 438 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. |
| 439 ASSERT(end == UINT_MAX || end <= INT_MAX); | 439 ASSERT(end == UINT_MAX || end <= INT_MAX); |
| 440 ASSERT(start <= INT_MAX); | 440 ASSERT(start <= INT_MAX); |
| 441 start = std::min(start, static_cast<unsigned>(INT_MAX)); | 441 start = std::min(start, static_cast<unsigned>(INT_MAX)); |
| 442 end = std::min(end, static_cast<unsigned>(INT_MAX)); | 442 end = std::min(end, static_cast<unsigned>(INT_MAX)); |
| 443 | 443 |
| 444 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 444 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 445 // Note: box->end() returns the index of the last character, not the ind
ex past it | 445 // Note: box->end() returns the index of the last character, not the ind
ex past it |
| 446 if (start <= box->start() && box->end() < end) { | 446 if (start <= box->start() && box->end() < end) { |
| 447 FloatRect r = box->calculateBoundaries().toFloatRect(); | 447 LayoutRect r(box->calculateBoundaries()); |
| 448 if (useSelectionHeight) { | 448 if (useSelectionHeight) { |
| 449 LayoutRect selectionRect = box->localSelectionRect(start, end); | 449 LayoutRect selectionRect = box->localSelectionRect(start, end); |
| 450 if (box->isHorizontal()) { | 450 if (box->isHorizontal()) { |
| 451 r.setHeight(selectionRect.height().toFloat()); | 451 r.setHeight(selectionRect.height()); |
| 452 r.setY(selectionRect.y().toFloat()); | 452 r.setY(selectionRect.y()); |
| 453 } else { | 453 } else { |
| 454 r.setWidth(selectionRect.width().toFloat()); | 454 r.setWidth(selectionRect.width()); |
| 455 r.setX(selectionRect.x().toFloat()); | 455 r.setX(selectionRect.x()); |
| 456 } | 456 } |
| 457 } | 457 } |
| 458 quads.append(localToAbsoluteQuad(r, 0, wasFixed)); | 458 quads.append(localToAbsoluteQuad(FloatRect(r), 0, wasFixed)); |
| 459 } else { | 459 } else { |
| 460 FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHe
ight); | 460 FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHe
ight); |
| 461 if (!rect.isZero()) | 461 if (!rect.isZero()) |
| 462 quads.append(localToAbsoluteQuad(rect, 0, wasFixed)); | 462 quads.append(localToAbsoluteQuad(rect, 0, wasFixed)); |
| 463 } | 463 } |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPo
sitionIsNotAtStart }; | 467 enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPo
sitionIsNotAtStart }; |
| 468 | 468 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 ASSERT(inlineBox->isInlineTextBox()); | 638 ASSERT(inlineBox->isInlineTextBox()); |
| 639 if (!inlineBox->isInlineTextBox()) | 639 if (!inlineBox->isInlineTextBox()) |
| 640 return LayoutRect(); | 640 return LayoutRect(); |
| 641 | 641 |
| 642 InlineTextBox* box = toInlineTextBox(inlineBox); | 642 InlineTextBox* box = toInlineTextBox(inlineBox); |
| 643 | 643 |
| 644 int height = box->root().selectionHeight(); | 644 int height = box->root().selectionHeight(); |
| 645 int top = box->root().selectionTop(); | 645 int top = box->root().selectionTop(); |
| 646 | 646 |
| 647 // Go ahead and round left to snap it to the nearest pixel. | 647 // Go ahead and round left to snap it to the nearest pixel. |
| 648 float left = box->positionForOffset(caretOffset); | 648 LayoutUnit left = box->positionForOffset(caretOffset); |
| 649 | 649 |
| 650 // Distribute the caret's width to either side of the offset. | 650 // Distribute the caret's width to either side of the offset. |
| 651 int caretWidthLeftOfOffset = caretWidth / 2; | 651 LayoutUnit caretWidthLeftOfOffset = caretWidth() / 2; |
| 652 left -= caretWidthLeftOfOffset; | 652 left -= caretWidthLeftOfOffset; |
| 653 int caretWidthRightOfOffset = caretWidth - caretWidthLeftOfOffset; | 653 LayoutUnit caretWidthRightOfOffset = caretWidth() - caretWidthLeftOfOffset; |
| 654 | 654 |
| 655 left = roundf(left); | 655 left = left.round(); |
| 656 | 656 |
| 657 float rootLeft = box->root().logicalLeft(); | 657 LayoutUnit rootLeft = box->root().logicalLeft(); |
| 658 float rootRight = box->root().logicalRight(); | 658 LayoutUnit rootRight = box->root().logicalRight(); |
| 659 | 659 |
| 660 // FIXME: should we use the width of the root inline box or the | 660 // FIXME: should we use the width of the root inline box or the |
| 661 // width of the containing block for this? | 661 // width of the containing block for this? |
| 662 if (extraWidthToEndOfLine) | 662 if (extraWidthToEndOfLine) |
| 663 *extraWidthToEndOfLine = (box->root().logicalWidth() + rootLeft) - (left
+ 1); | 663 *extraWidthToEndOfLine = (box->root().logicalWidth() + rootLeft) - (left
+ 1); |
| 664 | 664 |
| 665 LayoutBlock* cb = containingBlock(); | 665 LayoutBlock* cb = containingBlock(); |
| 666 const ComputedStyle& cbStyle = cb->styleRef(); | 666 const ComputedStyle& cbStyle = cb->styleRef(); |
| 667 | 667 |
| 668 float leftEdge; | 668 LayoutUnit leftEdge; |
| 669 float rightEdge; | 669 LayoutUnit rightEdge; |
| 670 leftEdge = std::min<float>(0, rootLeft); | 670 leftEdge = std::min(LayoutUnit(), rootLeft); |
| 671 rightEdge = std::max<float>(cb->logicalWidth().toFloat(), rootRight); | 671 rightEdge = std::max(cb->logicalWidth(), rootRight); |
| 672 | 672 |
| 673 bool rightAligned = false; | 673 bool rightAligned = false; |
| 674 switch (cbStyle.textAlign()) { | 674 switch (cbStyle.textAlign()) { |
| 675 case RIGHT: | 675 case RIGHT: |
| 676 case WEBKIT_RIGHT: | 676 case WEBKIT_RIGHT: |
| 677 rightAligned = true; | 677 rightAligned = true; |
| 678 break; | 678 break; |
| 679 case LEFT: | 679 case LEFT: |
| 680 case WEBKIT_LEFT: | 680 case WEBKIT_LEFT: |
| 681 case CENTER: | 681 case CENTER: |
| 682 case WEBKIT_CENTER: | 682 case WEBKIT_CENTER: |
| 683 break; | 683 break; |
| 684 case JUSTIFY: | 684 case JUSTIFY: |
| 685 case TASTART: | 685 case TASTART: |
| 686 rightAligned = !cbStyle.isLeftToRightDirection(); | 686 rightAligned = !cbStyle.isLeftToRightDirection(); |
| 687 break; | 687 break; |
| 688 case TAEND: | 688 case TAEND: |
| 689 rightAligned = cbStyle.isLeftToRightDirection(); | 689 rightAligned = cbStyle.isLeftToRightDirection(); |
| 690 break; | 690 break; |
| 691 } | 691 } |
| 692 | 692 |
| 693 // for unicode-bidi: plaintext, use inlineBoxBidiLevel() to test the correct
direction for the cursor. | 693 // for unicode-bidi: plaintext, use inlineBoxBidiLevel() to test the correct
direction for the cursor. |
| 694 if (rightAligned && style()->unicodeBidi() == Plaintext) { | 694 if (rightAligned && style()->unicodeBidi() == Plaintext) { |
| 695 if (inlineBox->bidiLevel()%2 != 1) | 695 if (inlineBox->bidiLevel()%2 != 1) |
| 696 rightAligned = false; | 696 rightAligned = false; |
| 697 } | 697 } |
| 698 | 698 |
| 699 if (rightAligned) { | 699 if (rightAligned) { |
| 700 left = std::max(left, leftEdge); | 700 left = std::max(left, leftEdge); |
| 701 left = std::min(left, rootRight - caretWidth); | 701 left = std::min(left, rootRight - caretWidth()); |
| 702 } else { | 702 } else { |
| 703 left = std::min(left, rightEdge - caretWidthRightOfOffset); | 703 left = std::min(left, rightEdge - caretWidthRightOfOffset); |
| 704 left = std::max(left, rootLeft); | 704 left = std::max(left, rootLeft); |
| 705 } | 705 } |
| 706 | 706 |
| 707 return LayoutRect(style()->isHorizontalWritingMode() ? IntRect(left, top, ca
retWidth, height) : IntRect(top, left, height, caretWidth)); | 707 return LayoutRect(style()->isHorizontalWritingMode() ? IntRect(left, top, ca
retWidth(), height) : IntRect(top, left, height, caretWidth())); |
| 708 } | 708 } |
| 709 | 709 |
| 710 ALWAYS_INLINE float LayoutText::widthFromCache(const Font& f, int start, int len
, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallb
ackFonts, GlyphOverflow* glyphOverflow) const | 710 ALWAYS_INLINE float LayoutText::widthFromCache(const Font& f, int start, int len
, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallb
ackFonts, GlyphOverflow* glyphOverflow) const |
| 711 { | 711 { |
| 712 if (style()->hasTextCombine() && isCombineText()) { | 712 if (style()->hasTextCombine() && isCombineText()) { |
| 713 const LayoutTextCombine* combineText = toLayoutTextCombine(this); | 713 const LayoutTextCombine* combineText = toLayoutTextCombine(this); |
| 714 if (combineText->isCombined()) | 714 if (combineText->isCombined()) |
| 715 return combineText->combinedTextWidth(f); | 715 return combineText->combinedTextWidth(f); |
| 716 } | 716 } |
| 717 | 717 |
| 718 TextRun run = constructTextRun(const_cast<LayoutText*>(this), f, this, start
, len, styleRef(), textDirection); | 718 TextRun run = constructTextRun(const_cast<LayoutText*>(this), f, this, start
, len, styleRef(), textDirection); |
| 719 run.setCharactersLength(textLength() - start); | 719 run.setCharactersLength(textLength() - start); |
| 720 ASSERT(run.charactersLength() >= run.length()); | 720 ASSERT(run.charactersLength() >= run.length()); |
| 721 run.setCodePath(canUseSimpleFontCodePath() ? TextRun::ForceSimple : TextRun:
:ForceComplex); | 721 run.setCodePath(canUseSimpleFontCodePath() ? TextRun::ForceSimple : TextRun:
:ForceComplex); |
| 722 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); | 722 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); |
| 723 run.setXPos(xPos); | 723 run.setXPos(xPos); |
| 724 return f.width(run, fallbackFonts, glyphOverflow); | 724 return f.width(run, fallbackFonts, glyphOverflow); |
| 725 } | 725 } |
| 726 | 726 |
| 727 void LayoutText::trimmedPrefWidths(FloatWillBeLayoutUnit leadWidth, | 727 void LayoutText::trimmedPrefWidths(LayoutUnit leadWidthLayoutUnit, |
| 728 FloatWillBeLayoutUnit& firstLineMinWidth, bool& hasBreakableStart, | 728 LayoutUnit& firstLineMinWidth, bool& hasBreakableStart, |
| 729 FloatWillBeLayoutUnit& lastLineMinWidth, bool& hasBreakableEnd, | 729 LayoutUnit& lastLineMinWidth, bool& hasBreakableEnd, |
| 730 bool& hasBreakableChar, bool& hasBreak, | 730 bool& hasBreakableChar, bool& hasBreak, |
| 731 FloatWillBeLayoutUnit& firstLineMaxWidth, FloatWillBeLayoutUnit& lastLineMax
Width, | 731 LayoutUnit& firstLineMaxWidth, LayoutUnit& lastLineMaxWidth, |
| 732 FloatWillBeLayoutUnit& minWidth, FloatWillBeLayoutUnit& maxWidth, bool& stri
pFrontSpaces, | 732 LayoutUnit& minWidth, LayoutUnit& maxWidth, bool& stripFrontSpaces, |
| 733 TextDirection direction) | 733 TextDirection direction) |
| 734 { | 734 { |
| 735 float floatMinWidth = 0.0f, floatMaxWidth = 0.0f; | 735 float floatMinWidth = 0.0f, floatMaxWidth = 0.0f; |
| 736 | 736 |
| 737 // Convert leadWidth to a float here, to avoid multiple implict conversions
below. |
| 738 float leadWidth = leadWidthLayoutUnit.toFloat(); |
| 739 |
| 737 bool collapseWhiteSpace = style()->collapseWhiteSpace(); | 740 bool collapseWhiteSpace = style()->collapseWhiteSpace(); |
| 738 if (!collapseWhiteSpace) | 741 if (!collapseWhiteSpace) |
| 739 stripFrontSpaces = false; | 742 stripFrontSpaces = false; |
| 740 | 743 |
| 741 if (m_hasTab || preferredLogicalWidthsDirty()) | 744 if (m_hasTab || preferredLogicalWidthsDirty()) |
| 742 computePreferredLogicalWidths(leadWidth); | 745 computePreferredLogicalWidths(leadWidth); |
| 743 | 746 |
| 744 hasBreakableStart = !stripFrontSpaces && m_hasBreakableStart; | 747 hasBreakableStart = !stripFrontSpaces && m_hasBreakableStart; |
| 745 hasBreakableEnd = m_hasBreakableEnd; | 748 hasBreakableEnd = m_hasBreakableEnd; |
| 746 | 749 |
| 747 int len = textLength(); | 750 int len = textLength(); |
| 748 | 751 |
| 749 if (!len || (stripFrontSpaces && text().impl()->containsOnlyWhitespace())) { | 752 if (!len || (stripFrontSpaces && text().impl()->containsOnlyWhitespace())) { |
| 750 firstLineMinWidth = FloatWillBeLayoutUnit(); | 753 firstLineMinWidth = LayoutUnit(); |
| 751 lastLineMinWidth = FloatWillBeLayoutUnit(); | 754 lastLineMinWidth = LayoutUnit(); |
| 752 firstLineMaxWidth = FloatWillBeLayoutUnit(); | 755 firstLineMaxWidth = LayoutUnit(); |
| 753 lastLineMaxWidth = FloatWillBeLayoutUnit(); | 756 lastLineMaxWidth = LayoutUnit(); |
| 754 minWidth = FloatWillBeLayoutUnit(); | 757 minWidth = LayoutUnit(); |
| 755 maxWidth = FloatWillBeLayoutUnit(); | 758 maxWidth = LayoutUnit(); |
| 756 hasBreak = false; | 759 hasBreak = false; |
| 757 return; | 760 return; |
| 758 } | 761 } |
| 759 | 762 |
| 760 floatMinWidth = m_minWidth; | 763 floatMinWidth = m_minWidth; |
| 761 floatMaxWidth = m_maxWidth; | 764 floatMaxWidth = m_maxWidth; |
| 762 | 765 |
| 763 firstLineMinWidth = m_firstLineMinWidth; | 766 firstLineMinWidth = m_firstLineMinWidth; |
| 764 lastLineMinWidth = m_lastLineLineMinWidth; | 767 lastLineMinWidth = m_lastLineLineMinWidth; |
| 765 | 768 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 794 lastLineMaxWidth = floatMaxWidth; | 797 lastLineMaxWidth = floatMaxWidth; |
| 795 for (int i = 0; i < len; i++) { | 798 for (int i = 0; i < len; i++) { |
| 796 int linelen = 0; | 799 int linelen = 0; |
| 797 while (i + linelen < len && text[i + linelen] != newlineCharacter) | 800 while (i + linelen < len && text[i + linelen] != newlineCharacter) |
| 798 linelen++; | 801 linelen++; |
| 799 | 802 |
| 800 if (linelen) { | 803 if (linelen) { |
| 801 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, direction, 0, 0); | 804 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, direction, 0, 0); |
| 802 if (firstLine) { | 805 if (firstLine) { |
| 803 firstLine = false; | 806 firstLine = false; |
| 804 leadWidth = FloatWillBeLayoutUnit(); | 807 leadWidth = 0.f; |
| 805 firstLineMaxWidth = lastLineMaxWidth; | 808 firstLineMaxWidth = lastLineMaxWidth; |
| 806 } | 809 } |
| 807 i += linelen; | 810 i += linelen; |
| 808 } else if (firstLine) { | 811 } else if (firstLine) { |
| 809 firstLineMaxWidth = FloatWillBeLayoutUnit(); | 812 firstLineMaxWidth = LayoutUnit(); |
| 810 firstLine = false; | 813 firstLine = false; |
| 811 leadWidth = FloatWillBeLayoutUnit(); | 814 leadWidth = 0.f; |
| 812 } | 815 } |
| 813 | 816 |
| 814 if (i == len - 1) { | 817 if (i == len - 1) { |
| 815 // A <pre> run that ends with a newline, as in, e.g., | 818 // A <pre> run that ends with a newline, as in, e.g., |
| 816 // <pre>Some text\n\n<span>More text</pre> | 819 // <pre>Some text\n\n<span>More text</pre> |
| 817 lastLineMaxWidth = FloatWillBeLayoutUnit(); | 820 lastLineMaxWidth = LayoutUnit(); |
| 818 } | 821 } |
| 819 } | 822 } |
| 820 } | 823 } |
| 821 | 824 |
| 822 minWidth = LayoutUnit::fromFloatCeil(floatMinWidth); | 825 minWidth = LayoutUnit::fromFloatCeil(floatMinWidth); |
| 823 maxWidth = LayoutUnit::fromFloatCeil(floatMaxWidth); | 826 maxWidth = LayoutUnit::fromFloatCeil(floatMaxWidth); |
| 824 } | 827 } |
| 825 | 828 |
| 826 float LayoutText::minLogicalWidth() const | 829 float LayoutText::minLogicalWidth() const |
| 827 { | 830 { |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 m_lastTextBox = s->prevTextBox(); | 1453 m_lastTextBox = s->prevTextBox(); |
| 1451 else | 1454 else |
| 1452 s->nextTextBox()->setPreviousTextBox(s->prevTextBox()); | 1455 s->nextTextBox()->setPreviousTextBox(s->prevTextBox()); |
| 1453 s->destroy(); | 1456 s->destroy(); |
| 1454 return; | 1457 return; |
| 1455 } | 1458 } |
| 1456 | 1459 |
| 1457 m_containsReversedText |= !s->isLeftToRightDirection(); | 1460 m_containsReversedText |= !s->isLeftToRightDirection(); |
| 1458 } | 1461 } |
| 1459 | 1462 |
| 1460 float LayoutText::width(unsigned from, unsigned len, float xPos, TextDirection t
extDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, Gly
phOverflow* glyphOverflow) const | 1463 float LayoutText::width(unsigned from, unsigned len, LayoutUnit xPos, TextDirect
ion textDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts
, GlyphOverflow* glyphOverflow) const |
| 1461 { | 1464 { |
| 1462 if (from >= textLength()) | 1465 if (from >= textLength()) |
| 1463 return 0; | 1466 return 0; |
| 1464 | 1467 |
| 1465 if (from + len > textLength()) | 1468 if (from + len > textLength()) |
| 1466 len = textLength() - from; | 1469 len = textLength() - from; |
| 1467 | 1470 |
| 1468 return width(from, len, style(firstLine)->font(), xPos, textDirection, fallb
ackFonts, glyphOverflow); | 1471 return width(from, len, style(firstLine)->font(), xPos, textDirection, fallb
ackFonts, glyphOverflow); |
| 1469 } | 1472 } |
| 1470 | 1473 |
| 1471 float LayoutText::width(unsigned from, unsigned len, const Font& f, float xPos,
TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, Glyp
hOverflow* glyphOverflow) const | 1474 float LayoutText::width(unsigned from, unsigned len, const Font& f, LayoutUnit x
Pos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts,
GlyphOverflow* glyphOverflow) const |
| 1472 { | 1475 { |
| 1473 ASSERT(from + len <= textLength()); | 1476 ASSERT(from + len <= textLength()); |
| 1474 if (!textLength()) | 1477 if (!textLength()) |
| 1475 return 0; | 1478 return 0; |
| 1476 | 1479 |
| 1477 float w; | 1480 float w; |
| 1478 if (&f == &style()->font()) { | 1481 if (&f == &style()->font()) { |
| 1479 if (!style()->preserveNewline() && !from && len == textLength() && (!gly
phOverflow || !glyphOverflow->computeBounds)) { | 1482 if (!style()->preserveNewline() && !from && len == textLength() && (!gly
phOverflow || !glyphOverflow->computeBounds)) { |
| 1480 if (fallbackFonts) { | 1483 if (fallbackFonts) { |
| 1481 ASSERT(glyphOverflow); | 1484 ASSERT(glyphOverflow); |
| 1482 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAnd
NoFallbackFonts) { | 1485 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAnd
NoFallbackFonts) { |
| 1483 const_cast<LayoutText*>(this)->computePreferredLogicalWidths
(0, *fallbackFonts, *glyphOverflow); | 1486 const_cast<LayoutText*>(this)->computePreferredLogicalWidths
(0, *fallbackFonts, *glyphOverflow); |
| 1484 // We shouldn't change our mind once we "know". | 1487 // We shouldn't change our mind once we "know". |
| 1485 ASSERT(!m_knownToHaveNoOverflowAndNoFallbackFonts | 1488 ASSERT(!m_knownToHaveNoOverflowAndNoFallbackFonts |
| 1486 || (fallbackFonts->isEmpty() && glyphOverflow->isZero())
); | 1489 || (fallbackFonts->isEmpty() && glyphOverflow->isZero())
); |
| 1487 m_knownToHaveNoOverflowAndNoFallbackFonts = fallbackFonts->i
sEmpty() && glyphOverflow->isZero(); | 1490 m_knownToHaveNoOverflowAndNoFallbackFonts = fallbackFonts->i
sEmpty() && glyphOverflow->isZero(); |
| 1488 } | 1491 } |
| 1489 w = m_maxWidth; | 1492 w = m_maxWidth; |
| 1490 } else { | 1493 } else { |
| 1491 w = maxLogicalWidth(); | 1494 w = maxLogicalWidth(); |
| 1492 } | 1495 } |
| 1493 } else { | 1496 } else { |
| 1494 w = widthFromCache(f, from, len, xPos, textDirection, fallbackFonts,
glyphOverflow); | 1497 w = widthFromCache(f, from, len, xPos.toFloat(), textDirection, fall
backFonts, glyphOverflow); |
| 1495 } | 1498 } |
| 1496 } else { | 1499 } else { |
| 1497 TextRun run = constructTextRun(const_cast<LayoutText*>(this), f, this, f
rom, len, styleRef(), textDirection); | 1500 TextRun run = constructTextRun(const_cast<LayoutText*>(this), f, this, f
rom, len, styleRef(), textDirection); |
| 1498 run.setCharactersLength(textLength() - from); | 1501 run.setCharactersLength(textLength() - from); |
| 1499 ASSERT(run.charactersLength() >= run.length()); | 1502 ASSERT(run.charactersLength() >= run.length()); |
| 1500 | 1503 |
| 1501 run.setCodePath(canUseSimpleFontCodePath() ? TextRun::ForceSimple : Text
Run::ForceComplex); | 1504 run.setCodePath(canUseSimpleFontCodePath() ? TextRun::ForceSimple : Text
Run::ForceComplex); |
| 1502 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); | 1505 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); |
| 1503 run.setXPos(xPos); | 1506 run.setXPos(xPos.toFloat()); |
| 1504 w = f.width(run, fallbackFonts, glyphOverflow); | 1507 w = f.width(run, fallbackFonts, glyphOverflow); |
| 1505 } | 1508 } |
| 1506 | 1509 |
| 1507 return w; | 1510 return w; |
| 1508 } | 1511 } |
| 1509 | 1512 |
| 1510 IntRect LayoutText::linesBoundingBox() const | 1513 IntRect LayoutText::linesBoundingBox() const |
| 1511 { | 1514 { |
| 1512 IntRect result; | 1515 IntRect result; |
| 1513 | 1516 |
| 1514 ASSERT(!firstTextBox() == !lastTextBox()); // Either both are null or both e
xist. | 1517 ASSERT(!firstTextBox() == !lastTextBox()); // Either both are null or both e
xist. |
| 1515 if (firstTextBox() && lastTextBox()) { | 1518 if (firstTextBox() && lastTextBox()) { |
| 1516 // Return the width of the minimal left side and the maximal right side. | 1519 // Return the width of the minimal left side and the maximal right side. |
| 1517 float logicalLeftSide = 0; | 1520 float logicalLeftSide = 0; |
| 1518 float logicalRightSide = 0; | 1521 float logicalRightSide = 0; |
| 1519 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBo
x()) { | 1522 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBo
x()) { |
| 1520 if (curr == firstTextBox() || curr->logicalLeft() < logicalLeftSide) | 1523 if (curr == firstTextBox() || curr->logicalLeft() < logicalLeftSide) |
| 1521 logicalLeftSide = curr->logicalLeft(); | 1524 logicalLeftSide = curr->logicalLeft().toFloat(); |
| 1522 if (curr == firstTextBox() || curr->logicalRight() > logicalRightSid
e) | 1525 if (curr == firstTextBox() || curr->logicalRight() > logicalRightSid
e) |
| 1523 logicalRightSide = curr->logicalRight(); | 1526 logicalRightSide = curr->logicalRight().toFloat(); |
| 1524 } | 1527 } |
| 1525 | 1528 |
| 1526 bool isHorizontal = style()->isHorizontalWritingMode(); | 1529 bool isHorizontal = style()->isHorizontalWritingMode(); |
| 1527 | 1530 |
| 1528 float x = isHorizontal ? logicalLeftSide : firstTextBox()->x().toFloat()
; | 1531 float x = isHorizontal ? logicalLeftSide : firstTextBox()->x().toFloat()
; |
| 1529 float y = isHorizontal ? firstTextBox()->y().toFloat() : logicalLeftSide
; | 1532 float y = isHorizontal ? firstTextBox()->y().toFloat() : logicalLeftSide
; |
| 1530 float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastTe
xtBox()->logicalBottom() - x; | 1533 float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastTe
xtBox()->logicalBottom() - x; |
| 1531 float height = isHorizontal ? lastTextBox()->logicalBottom() - y : logic
alRightSide - logicalLeftSide; | 1534 float height = isHorizontal ? lastTextBox()->logicalBottom() - y : logic
alRightSide - logicalLeftSide; |
| 1532 result = enclosingIntRect(FloatRect(x, y, width, height)); | 1535 result = enclosingIntRect(FloatRect(x, y, width, height)); |
| 1533 } | 1536 } |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1855 } | 1858 } |
| 1856 | 1859 |
| 1857 void LayoutText::invalidateDisplayItemClients(const LayoutBoxModelObject& paintI
nvalidationContainer) const | 1860 void LayoutText::invalidateDisplayItemClients(const LayoutBoxModelObject& paintI
nvalidationContainer) const |
| 1858 { | 1861 { |
| 1859 LayoutObject::invalidateDisplayItemClients(paintInvalidationContainer); | 1862 LayoutObject::invalidateDisplayItemClients(paintInvalidationContainer); |
| 1860 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) | 1863 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) |
| 1861 paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*box); | 1864 paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*box); |
| 1862 } | 1865 } |
| 1863 | 1866 |
| 1864 } // namespace blink | 1867 } // namespace blink |
| OLD | NEW |