| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include "platform/fonts/Character.h" | 42 #include "platform/fonts/Character.h" |
| 43 #include "platform/fonts/FontCache.h" | 43 #include "platform/fonts/FontCache.h" |
| 44 #include "platform/geometry/FloatQuad.h" | 44 #include "platform/geometry/FloatQuad.h" |
| 45 #include "platform/text/BidiResolver.h" | 45 #include "platform/text/BidiResolver.h" |
| 46 #include "platform/text/TextBreakIterator.h" | 46 #include "platform/text/TextBreakIterator.h" |
| 47 #include "platform/text/TextRunIterator.h" | 47 #include "platform/text/TextRunIterator.h" |
| 48 #include "wtf/text/StringBuffer.h" | 48 #include "wtf/text/StringBuffer.h" |
| 49 #include "wtf/text/StringBuilder.h" | 49 #include "wtf/text/StringBuilder.h" |
| 50 #include "wtf/unicode/CharacterNames.h" | 50 #include "wtf/unicode/CharacterNames.h" |
| 51 | 51 |
| 52 using namespace std; | |
| 53 using namespace WTF; | 52 using namespace WTF; |
| 54 using namespace Unicode; | 53 using namespace Unicode; |
| 55 | 54 |
| 56 namespace WebCore { | 55 namespace WebCore { |
| 57 | 56 |
| 58 struct SameSizeAsRenderText : public RenderObject { | 57 struct SameSizeAsRenderText : public RenderObject { |
| 59 uint32_t bitfields : 16; | 58 uint32_t bitfields : 16; |
| 60 float widths[4]; | 59 float widths[4]; |
| 61 String text; | 60 String text; |
| 62 void* pointers[2]; | 61 void* pointers[2]; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 }; | 96 }; |
| 98 | 97 |
| 99 static void makeCapitalized(String* string, UChar previous) | 98 static void makeCapitalized(String* string, UChar previous) |
| 100 { | 99 { |
| 101 if (string->isNull()) | 100 if (string->isNull()) |
| 102 return; | 101 return; |
| 103 | 102 |
| 104 unsigned length = string->length(); | 103 unsigned length = string->length(); |
| 105 const StringImpl& input = *string->impl(); | 104 const StringImpl& input = *string->impl(); |
| 106 | 105 |
| 107 if (length >= numeric_limits<unsigned>::max()) | 106 if (length >= std::numeric_limits<unsigned>::max()) |
| 108 CRASH(); | 107 CRASH(); |
| 109 | 108 |
| 110 StringBuffer<UChar> stringWithPrevious(length + 1); | 109 StringBuffer<UChar> stringWithPrevious(length + 1); |
| 111 stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; | 110 stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; |
| 112 for (unsigned i = 1; i < length + 1; i++) { | 111 for (unsigned i = 1; i < length + 1; i++) { |
| 113 // Replace   with a real space since ICU no longer treats   as a
word separator. | 112 // Replace   with a real space since ICU no longer treats   as a
word separator. |
| 114 if (input[i - 1] == noBreakSpace) | 113 if (input[i - 1] == noBreakSpace) |
| 115 stringWithPrevious[i] = ' '; | 114 stringWithPrevious[i] = ' '; |
| 116 else | 115 else |
| 117 stringWithPrevious[i] = input[i - 1]; | 116 stringWithPrevious[i] = input[i - 1]; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 } | 323 } |
| 325 | 324 |
| 326 void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
latedOffset) const | 325 void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
latedOffset) const |
| 327 { | 326 { |
| 328 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) | 327 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) |
| 329 rects.append(enclosingIntRect(FloatRect(accumulatedOffset + box->topLeft
(), box->size()))); | 328 rects.append(enclosingIntRect(FloatRect(accumulatedOffset + box->topLeft
(), box->size()))); |
| 330 } | 329 } |
| 331 | 330 |
| 332 static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigne
d end, bool useSelectionHeight) | 331 static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigne
d end, bool useSelectionHeight) |
| 333 { | 332 { |
| 334 unsigned realEnd = min(box->end() + 1, end); | 333 unsigned realEnd = std::min(box->end() + 1, end); |
| 335 LayoutRect r = box->localSelectionRect(start, realEnd); | 334 LayoutRect r = box->localSelectionRect(start, realEnd); |
| 336 if (r.height()) { | 335 if (r.height()) { |
| 337 if (!useSelectionHeight) { | 336 if (!useSelectionHeight) { |
| 338 // Change the height and y position (or width and x for vertical tex
t) | 337 // Change the height and y position (or width and x for vertical tex
t) |
| 339 // because selectionRect uses selection-specific values. | 338 // because selectionRect uses selection-specific values. |
| 340 if (box->isHorizontal()) { | 339 if (box->isHorizontal()) { |
| 341 r.setHeight(box->height()); | 340 r.setHeight(box->height()); |
| 342 r.setY(box->y()); | 341 r.setY(box->y()); |
| 343 } else { | 342 } else { |
| 344 r.setWidth(box->width()); | 343 r.setWidth(box->width()); |
| 345 r.setX(box->x()); | 344 r.setX(box->x()); |
| 346 } | 345 } |
| 347 } | 346 } |
| 348 return FloatRect(r); | 347 return FloatRect(r); |
| 349 } | 348 } |
| 350 return FloatRect(); | 349 return FloatRect(); |
| 351 } | 350 } |
| 352 | 351 |
| 353 void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, u
nsigned end, bool useSelectionHeight, bool* wasFixed) | 352 void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, u
nsigned end, bool useSelectionHeight, bool* wasFixed) |
| 354 { | 353 { |
| 355 // Work around signed/unsigned issues. This function takes unsigneds, and is
often passed UINT_MAX | 354 // Work around signed/unsigned issues. This function takes unsigneds, and is
often passed UINT_MAX |
| 356 // to mean "all the way to the end". InlineTextBox coordinates are unsigneds
, so changing this | 355 // to mean "all the way to the end". InlineTextBox coordinates are unsigneds
, so changing this |
| 357 // function to take ints causes various internal mismatches. But selectionRe
ct takes ints, and | 356 // function to take ints causes various internal mismatches. But selectionRe
ct takes ints, and |
| 358 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but | 357 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but |
| 359 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. | 358 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. |
| 360 ASSERT(end == UINT_MAX || end <= INT_MAX); | 359 ASSERT(end == UINT_MAX || end <= INT_MAX); |
| 361 ASSERT(start <= INT_MAX); | 360 ASSERT(start <= INT_MAX); |
| 362 start = min(start, static_cast<unsigned>(INT_MAX)); | 361 start = std::min(start, static_cast<unsigned>(INT_MAX)); |
| 363 end = min(end, static_cast<unsigned>(INT_MAX)); | 362 end = std::min(end, static_cast<unsigned>(INT_MAX)); |
| 364 | 363 |
| 365 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 364 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 366 // Note: box->end() returns the index of the last character, not the ind
ex past it | 365 // Note: box->end() returns the index of the last character, not the ind
ex past it |
| 367 if (start <= box->start() && box->end() < end) { | 366 if (start <= box->start() && box->end() < end) { |
| 368 FloatRect r = box->calculateBoundaries(); | 367 FloatRect r = box->calculateBoundaries(); |
| 369 if (useSelectionHeight) { | 368 if (useSelectionHeight) { |
| 370 LayoutRect selectionRect = box->localSelectionRect(start, end); | 369 LayoutRect selectionRect = box->localSelectionRect(start, end); |
| 371 if (box->isHorizontal()) { | 370 if (box->isHorizontal()) { |
| 372 r.setHeight(selectionRect.height().toFloat()); | 371 r.setHeight(selectionRect.height().toFloat()); |
| 373 r.setY(selectionRect.y().toFloat()); | 372 r.setY(selectionRect.y().toFloat()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 390 { | 389 { |
| 391 if (!box) | 390 if (!box) |
| 392 return IntRect(); | 391 return IntRect(); |
| 393 | 392 |
| 394 unsigned short truncation = box->truncation(); | 393 unsigned short truncation = box->truncation(); |
| 395 if (truncation == cNoTruncation) | 394 if (truncation == cNoTruncation) |
| 396 return IntRect(); | 395 return IntRect(); |
| 397 | 396 |
| 398 IntRect rect; | 397 IntRect rect; |
| 399 if (EllipsisBox* ellipsis = box->root().ellipsisBox()) { | 398 if (EllipsisBox* ellipsis = box->root().ellipsisBox()) { |
| 400 int ellipsisStartPosition = max<int>(startPos - box->start(), 0); | 399 int ellipsisStartPosition = std::max<int>(startPos - box->start(), 0); |
| 401 int ellipsisEndPosition = min<int>(endPos - box->start(), box->len()); | 400 int ellipsisEndPosition = std::min<int>(endPos - box->start(), box->len(
)); |
| 402 | 401 |
| 403 // The ellipsis should be considered to be selected if the end of | 402 // The ellipsis should be considered to be selected if the end of |
| 404 // the selection is past the beginning of the truncation and the | 403 // the selection is past the beginning of the truncation and the |
| 405 // beginning of the selection is before or at the beginning of the trunc
ation. | 404 // beginning of the selection is before or at the beginning of the trunc
ation. |
| 406 if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= trunca
tion) | 405 if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= trunca
tion) |
| 407 return ellipsis->selectionRect(); | 406 return ellipsis->selectionRect(); |
| 408 } | 407 } |
| 409 | 408 |
| 410 return IntRect(); | 409 return IntRect(); |
| 411 } | 410 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 435 | 434 |
| 436 void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start,
unsigned end, bool useSelectionHeight, bool* wasFixed) | 435 void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start,
unsigned end, bool useSelectionHeight, bool* wasFixed) |
| 437 { | 436 { |
| 438 // Work around signed/unsigned issues. This function takes unsigneds, and is
often passed UINT_MAX | 437 // Work around signed/unsigned issues. This function takes unsigneds, and is
often passed UINT_MAX |
| 439 // to mean "all the way to the end". InlineTextBox coordinates are unsigneds
, so changing this | 438 // to mean "all the way to the end". InlineTextBox coordinates are unsigneds
, so changing this |
| 440 // function to take ints causes various internal mismatches. But selectionRe
ct takes ints, and | 439 // function to take ints causes various internal mismatches. But selectionRe
ct takes ints, and |
| 441 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but | 440 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect
to take unsigneds, but |
| 442 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. | 441 // that would cause many ripple effects, so for now we'll just clamp our uns
igned parameters to INT_MAX. |
| 443 ASSERT(end == UINT_MAX || end <= INT_MAX); | 442 ASSERT(end == UINT_MAX || end <= INT_MAX); |
| 444 ASSERT(start <= INT_MAX); | 443 ASSERT(start <= INT_MAX); |
| 445 start = min(start, static_cast<unsigned>(INT_MAX)); | 444 start = std::min(start, static_cast<unsigned>(INT_MAX)); |
| 446 end = min(end, static_cast<unsigned>(INT_MAX)); | 445 end = std::min(end, static_cast<unsigned>(INT_MAX)); |
| 447 | 446 |
| 448 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 447 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 449 // Note: box->end() returns the index of the last character, not the ind
ex past it | 448 // Note: box->end() returns the index of the last character, not the ind
ex past it |
| 450 if (start <= box->start() && box->end() < end) { | 449 if (start <= box->start() && box->end() < end) { |
| 451 FloatRect r = box->calculateBoundaries(); | 450 FloatRect r = box->calculateBoundaries(); |
| 452 if (useSelectionHeight) { | 451 if (useSelectionHeight) { |
| 453 LayoutRect selectionRect = box->localSelectionRect(start, end); | 452 LayoutRect selectionRect = box->localSelectionRect(start, end); |
| 454 if (box->isHorizontal()) { | 453 if (box->isHorizontal()) { |
| 455 r.setHeight(selectionRect.height().toFloat()); | 454 r.setHeight(selectionRect.height().toFloat()); |
| 456 r.setY(selectionRect.y().toFloat()); | 455 r.setY(selectionRect.y().toFloat()); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 LayoutUnit pointLineDirection = firstTextBox()->isHorizontal() ? point.x() :
point.y(); | 603 LayoutUnit pointLineDirection = firstTextBox()->isHorizontal() ? point.x() :
point.y(); |
| 605 LayoutUnit pointBlockDirection = firstTextBox()->isHorizontal() ? point.y()
: point.x(); | 604 LayoutUnit pointBlockDirection = firstTextBox()->isHorizontal() ? point.y()
: point.x(); |
| 606 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); | 605 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); |
| 607 | 606 |
| 608 InlineTextBox* lastBox = 0; | 607 InlineTextBox* lastBox = 0; |
| 609 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 608 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 610 if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild()
&& !box->nextLeafChild()->isLineBreak()) | 609 if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild()
&& !box->nextLeafChild()->isLineBreak()) |
| 611 box = box->nextTextBox(); | 610 box = box->nextTextBox(); |
| 612 | 611 |
| 613 RootInlineBox& rootBox = box->root(); | 612 RootInlineBox& rootBox = box->root(); |
| 614 LayoutUnit top = min(rootBox.selectionTop(), rootBox.lineTop()); | 613 LayoutUnit top = std::min(rootBox.selectionTop(), rootBox.lineTop()); |
| 615 if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirecti
on == top)) { | 614 if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirecti
on == top)) { |
| 616 LayoutUnit bottom = rootBox.selectionBottom(); | 615 LayoutUnit bottom = rootBox.selectionBottom(); |
| 617 if (rootBox.nextRootBox()) | 616 if (rootBox.nextRootBox()) |
| 618 bottom = min(bottom, rootBox.nextRootBox()->lineTop()); | 617 bottom = std::min(bottom, rootBox.nextRootBox()->lineTop()); |
| 619 | 618 |
| 620 if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockD
irection == bottom)) { | 619 if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockD
irection == bottom)) { |
| 621 ShouldAffinityBeDownstream shouldAffinityBeDownstream; | 620 ShouldAffinityBeDownstream shouldAffinityBeDownstream; |
| 622 if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldA
ffinityBeDownstream)) | 621 if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldA
ffinityBeDownstream)) |
| 623 return createPositionWithAffinityForBoxAfterAdjustingOffsetF
orBiDi(box, box->offsetForPosition(pointLineDirection.toFloat()), shouldAffinity
BeDownstream); | 622 return createPositionWithAffinityForBoxAfterAdjustingOffsetF
orBiDi(box, box->offsetForPosition(pointLineDirection.toFloat()), shouldAffinity
BeDownstream); |
| 624 } | 623 } |
| 625 } | 624 } |
| 626 lastBox = box; | 625 lastBox = box; |
| 627 } | 626 } |
| 628 | 627 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 // FIXME: should we use the width of the root inline box or the | 663 // FIXME: should we use the width of the root inline box or the |
| 665 // width of the containing block for this? | 664 // width of the containing block for this? |
| 666 if (extraWidthToEndOfLine) | 665 if (extraWidthToEndOfLine) |
| 667 *extraWidthToEndOfLine = (box->root().logicalWidth() + rootLeft) - (left
+ 1); | 666 *extraWidthToEndOfLine = (box->root().logicalWidth() + rootLeft) - (left
+ 1); |
| 668 | 667 |
| 669 RenderBlock* cb = containingBlock(); | 668 RenderBlock* cb = containingBlock(); |
| 670 RenderStyle* cbStyle = cb->style(); | 669 RenderStyle* cbStyle = cb->style(); |
| 671 | 670 |
| 672 float leftEdge; | 671 float leftEdge; |
| 673 float rightEdge; | 672 float rightEdge; |
| 674 leftEdge = min<float>(0, rootLeft); | 673 leftEdge = std::min<float>(0, rootLeft); |
| 675 rightEdge = max<float>(cb->logicalWidth().toFloat(), rootRight); | 674 rightEdge = std::max<float>(cb->logicalWidth().toFloat(), rootRight); |
| 676 | 675 |
| 677 bool rightAligned = false; | 676 bool rightAligned = false; |
| 678 switch (cbStyle->textAlign()) { | 677 switch (cbStyle->textAlign()) { |
| 679 case RIGHT: | 678 case RIGHT: |
| 680 case WEBKIT_RIGHT: | 679 case WEBKIT_RIGHT: |
| 681 rightAligned = true; | 680 rightAligned = true; |
| 682 break; | 681 break; |
| 683 case LEFT: | 682 case LEFT: |
| 684 case WEBKIT_LEFT: | 683 case WEBKIT_LEFT: |
| 685 case CENTER: | 684 case CENTER: |
| 686 case WEBKIT_CENTER: | 685 case WEBKIT_CENTER: |
| 687 break; | 686 break; |
| 688 case JUSTIFY: | 687 case JUSTIFY: |
| 689 case TASTART: | 688 case TASTART: |
| 690 rightAligned = !cbStyle->isLeftToRightDirection(); | 689 rightAligned = !cbStyle->isLeftToRightDirection(); |
| 691 break; | 690 break; |
| 692 case TAEND: | 691 case TAEND: |
| 693 rightAligned = cbStyle->isLeftToRightDirection(); | 692 rightAligned = cbStyle->isLeftToRightDirection(); |
| 694 break; | 693 break; |
| 695 } | 694 } |
| 696 | 695 |
| 697 if (rightAligned) { | 696 if (rightAligned) { |
| 698 left = max(left, leftEdge); | 697 left = std::max(left, leftEdge); |
| 699 left = min(left, rootRight - caretWidth); | 698 left = std::min(left, rootRight - caretWidth); |
| 700 } else { | 699 } else { |
| 701 left = min(left, rightEdge - caretWidthRightOfOffset); | 700 left = std::min(left, rightEdge - caretWidthRightOfOffset); |
| 702 left = max(left, rootLeft); | 701 left = std::max(left, rootLeft); |
| 703 } | 702 } |
| 704 | 703 |
| 705 return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, h
eight) : IntRect(top, left, height, caretWidth); | 704 return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, h
eight) : IntRect(top, left, height, caretWidth); |
| 706 } | 705 } |
| 707 | 706 |
| 708 ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallb
ackFonts, GlyphOverflow* glyphOverflow) const | 707 ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallb
ackFonts, GlyphOverflow* glyphOverflow) const |
| 709 { | 708 { |
| 710 if (style()->hasTextCombine() && isCombineText()) { | 709 if (style()->hasTextCombine() && isCombineText()) { |
| 711 const RenderCombineText* combineText = toRenderCombineText(this); | 710 const RenderCombineText* combineText = toRenderCombineText(this); |
| 712 if (combineText->isCombined()) | 711 if (combineText->isCombined()) |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j -
1) != softHyphen) | 1007 if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j -
1) != softHyphen) |
| 1009 break; | 1008 break; |
| 1010 if (breakAll) { | 1009 if (breakAll) { |
| 1011 betweenWords = false; | 1010 betweenWords = false; |
| 1012 break; | 1011 break; |
| 1013 } | 1012 } |
| 1014 } | 1013 } |
| 1015 | 1014 |
| 1016 // Terminate word boundary at bidi run boundary. | 1015 // Terminate word boundary at bidi run boundary. |
| 1017 if (run) | 1016 if (run) |
| 1018 j = min(j, run->stop() + 1); | 1017 j = std::min(j, run->stop() + 1); |
| 1019 int wordLen = j - i; | 1018 int wordLen = j - i; |
| 1020 if (wordLen) { | 1019 if (wordLen) { |
| 1021 bool isSpace = (j < len) && c == ' '; | 1020 bool isSpace = (j < len) && c == ' '; |
| 1022 | 1021 |
| 1023 // Non-zero only when kerning is enabled, in which case we measure w
ords with their trailing | 1022 // Non-zero only when kerning is enabled, in which case we measure w
ords with their trailing |
| 1024 // space, then subtract its width. | 1023 // space, then subtract its width. |
| 1025 float wordTrailingSpaceWidth = 0; | 1024 float wordTrailingSpaceWidth = 0; |
| 1026 if (isSpace && (f.fontDescription().typesettingFeatures() & Kerning)
) { | 1025 if (isSpace && (f.fontDescription().typesettingFeatures() & Kerning)
) { |
| 1027 ASSERT(textDirection >=0 && textDirection <= 1); | 1026 ASSERT(textDirection >=0 && textDirection <= 1); |
| 1028 if (!cachedWordTrailingSpaceWidth[textDirection]) | 1027 if (!cachedWordTrailingSpaceWidth[textDirection]) |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 } | 1112 } |
| 1114 if (run) | 1113 if (run) |
| 1115 bidiResolver.runs().deleteRuns(); | 1114 bidiResolver.runs().deleteRuns(); |
| 1116 | 1115 |
| 1117 if (firstGlyphLeftOverflow > 0) | 1116 if (firstGlyphLeftOverflow > 0) |
| 1118 glyphOverflow.left = firstGlyphLeftOverflow; | 1117 glyphOverflow.left = firstGlyphLeftOverflow; |
| 1119 | 1118 |
| 1120 if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord)) | 1119 if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord)) |
| 1121 currMaxWidth += wordSpacing; | 1120 currMaxWidth += wordSpacing; |
| 1122 | 1121 |
| 1123 m_minWidth = max(currMinWidth, m_minWidth); | 1122 m_minWidth = std::max(currMinWidth, m_minWidth); |
| 1124 m_maxWidth = max(currMaxWidth, m_maxWidth); | 1123 m_maxWidth = std::max(currMaxWidth, m_maxWidth); |
| 1125 | 1124 |
| 1126 if (!styleToUse->autoWrap()) | 1125 if (!styleToUse->autoWrap()) |
| 1127 m_minWidth = m_maxWidth; | 1126 m_minWidth = m_maxWidth; |
| 1128 | 1127 |
| 1129 if (styleToUse->whiteSpace() == PRE) { | 1128 if (styleToUse->whiteSpace() == PRE) { |
| 1130 if (firstLine) | 1129 if (firstLine) |
| 1131 m_firstLineMinWidth = m_maxWidth; | 1130 m_firstLineMinWidth = m_maxWidth; |
| 1132 m_lastLineLineMinWidth = currMaxWidth; | 1131 m_lastLineLineMinWidth = currMaxWidth; |
| 1133 } | 1132 } |
| 1134 | 1133 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 LayoutRect RenderText::linesVisualOverflowBoundingBox() const | 1548 LayoutRect RenderText::linesVisualOverflowBoundingBox() const |
| 1550 { | 1549 { |
| 1551 if (!firstTextBox()) | 1550 if (!firstTextBox()) |
| 1552 return LayoutRect(); | 1551 return LayoutRect(); |
| 1553 | 1552 |
| 1554 // Return the width of the minimal left side and the maximal right side. | 1553 // Return the width of the minimal left side and the maximal right side. |
| 1555 LayoutUnit logicalLeftSide = LayoutUnit::max(); | 1554 LayoutUnit logicalLeftSide = LayoutUnit::max(); |
| 1556 LayoutUnit logicalRightSide = LayoutUnit::min(); | 1555 LayoutUnit logicalRightSide = LayoutUnit::min(); |
| 1557 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox())
{ | 1556 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox())
{ |
| 1558 LayoutRect logicalVisualOverflow = curr->logicalOverflowRect(); | 1557 LayoutRect logicalVisualOverflow = curr->logicalOverflowRect(); |
| 1559 logicalLeftSide = min(logicalLeftSide, logicalVisualOverflow.x()); | 1558 logicalLeftSide = std::min(logicalLeftSide, logicalVisualOverflow.x()); |
| 1560 logicalRightSide = max(logicalRightSide, logicalVisualOverflow.maxX()); | 1559 logicalRightSide = std::max(logicalRightSide, logicalVisualOverflow.maxX
()); |
| 1561 } | 1560 } |
| 1562 | 1561 |
| 1563 LayoutUnit logicalTop = firstTextBox()->logicalTopVisualOverflow(); | 1562 LayoutUnit logicalTop = firstTextBox()->logicalTopVisualOverflow(); |
| 1564 LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide; | 1563 LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide; |
| 1565 LayoutUnit logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - lo
gicalTop; | 1564 LayoutUnit logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - lo
gicalTop; |
| 1566 | 1565 |
| 1567 LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight); | 1566 LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight); |
| 1568 if (!style()->isHorizontalWritingMode()) | 1567 if (!style()->isHorizontalWritingMode()) |
| 1569 rect = rect.transposedRect(); | 1568 rect = rect.transposedRect(); |
| 1570 return rect; | 1569 return rect; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1632 return rect; | 1631 return rect; |
| 1633 } | 1632 } |
| 1634 | 1633 |
| 1635 int RenderText::caretMinOffset() const | 1634 int RenderText::caretMinOffset() const |
| 1636 { | 1635 { |
| 1637 InlineTextBox* box = firstTextBox(); | 1636 InlineTextBox* box = firstTextBox(); |
| 1638 if (!box) | 1637 if (!box) |
| 1639 return 0; | 1638 return 0; |
| 1640 int minOffset = box->start(); | 1639 int minOffset = box->start(); |
| 1641 for (box = box->nextTextBox(); box; box = box->nextTextBox()) | 1640 for (box = box->nextTextBox(); box; box = box->nextTextBox()) |
| 1642 minOffset = min<int>(minOffset, box->start()); | 1641 minOffset = std::min<int>(minOffset, box->start()); |
| 1643 return minOffset; | 1642 return minOffset; |
| 1644 } | 1643 } |
| 1645 | 1644 |
| 1646 int RenderText::caretMaxOffset() const | 1645 int RenderText::caretMaxOffset() const |
| 1647 { | 1646 { |
| 1648 InlineTextBox* box = lastTextBox(); | 1647 InlineTextBox* box = lastTextBox(); |
| 1649 if (!lastTextBox()) | 1648 if (!lastTextBox()) |
| 1650 return textLength(); | 1649 return textLength(); |
| 1651 | 1650 |
| 1652 int maxOffset = box->start() + box->len(); | 1651 int maxOffset = box->start() + box->len(); |
| 1653 for (box = box->prevTextBox(); box; box = box->prevTextBox()) | 1652 for (box = box->prevTextBox(); box; box = box->prevTextBox()) |
| 1654 maxOffset = max<int>(maxOffset, box->start() + box->len()); | 1653 maxOffset = std::max<int>(maxOffset, box->start() + box->len()); |
| 1655 return maxOffset; | 1654 return maxOffset; |
| 1656 } | 1655 } |
| 1657 | 1656 |
| 1658 unsigned RenderText::renderedTextLength() const | 1657 unsigned RenderText::renderedTextLength() const |
| 1659 { | 1658 { |
| 1660 int l = 0; | 1659 int l = 0; |
| 1661 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) | 1660 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) |
| 1662 l += box->len(); | 1661 l += box->len(); |
| 1663 return l; | 1662 return l; |
| 1664 } | 1663 } |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1869 } | 1868 } |
| 1870 secureTextTimer->restartWithNewText(lastTypedCharacterOffset); | 1869 secureTextTimer->restartWithNewText(lastTypedCharacterOffset); |
| 1871 } | 1870 } |
| 1872 | 1871 |
| 1873 PassRefPtr<AbstractInlineTextBox> RenderText::firstAbstractInlineTextBox() | 1872 PassRefPtr<AbstractInlineTextBox> RenderText::firstAbstractInlineTextBox() |
| 1874 { | 1873 { |
| 1875 return AbstractInlineTextBox::getOrCreate(this, m_firstTextBox); | 1874 return AbstractInlineTextBox::getOrCreate(this, m_firstTextBox); |
| 1876 } | 1875 } |
| 1877 | 1876 |
| 1878 } // namespace WebCore | 1877 } // namespace WebCore |
| OLD | NEW |