| 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 unsigned length = string->length(); | 108 unsigned length = string->length(); |
| 109 const StringImpl& input = *string->impl(); | 109 const StringImpl& input = *string->impl(); |
| 110 | 110 |
| 111 if (length >= std::numeric_limits<unsigned>::max()) | 111 if (length >= std::numeric_limits<unsigned>::max()) |
| 112 CRASH(); | 112 CRASH(); |
| 113 | 113 |
| 114 StringBuffer<UChar> stringWithPrevious(length + 1); | 114 StringBuffer<UChar> stringWithPrevious(length + 1); |
| 115 stringWithPrevious[0] = | 115 stringWithPrevious[0] = |
| 116 previous == noBreakSpaceCharacter ? spaceCharacter : previous; | 116 previous == noBreakSpaceCharacter ? spaceCharacter : previous; |
| 117 for (unsigned i = 1; i < length + 1; i++) { | 117 for (unsigned i = 1; i < length + 1; i++) { |
| 118 // Replace   with a real space since ICU no longer treats   as a wor
d separator. | 118 // Replace   with a real space since ICU no longer treats   as a |
| 119 // word separator. |
| 119 if (input[i - 1] == noBreakSpaceCharacter) | 120 if (input[i - 1] == noBreakSpaceCharacter) |
| 120 stringWithPrevious[i] = spaceCharacter; | 121 stringWithPrevious[i] = spaceCharacter; |
| 121 else | 122 else |
| 122 stringWithPrevious[i] = input[i - 1]; | 123 stringWithPrevious[i] = input[i - 1]; |
| 123 } | 124 } |
| 124 | 125 |
| 125 TextBreakIterator* boundary = | 126 TextBreakIterator* boundary = |
| 126 wordBreakIterator(stringWithPrevious.characters(), length + 1); | 127 wordBreakIterator(stringWithPrevious.characters(), length + 1); |
| 127 if (!boundary) | 128 if (!boundary) |
| 128 return; | 129 return; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 152 m_containsReversedText(false), | 153 m_containsReversedText(false), |
| 153 m_knownToHaveNoOverflowAndNoFallbackFonts(false), | 154 m_knownToHaveNoOverflowAndNoFallbackFonts(false), |
| 154 m_minWidth(-1), | 155 m_minWidth(-1), |
| 155 m_maxWidth(-1), | 156 m_maxWidth(-1), |
| 156 m_firstLineMinWidth(0), | 157 m_firstLineMinWidth(0), |
| 157 m_lastLineLineMinWidth(0), | 158 m_lastLineLineMinWidth(0), |
| 158 m_text(std::move(str)), | 159 m_text(std::move(str)), |
| 159 m_firstTextBox(nullptr), | 160 m_firstTextBox(nullptr), |
| 160 m_lastTextBox(nullptr) { | 161 m_lastTextBox(nullptr) { |
| 161 ASSERT(m_text); | 162 ASSERT(m_text); |
| 162 // FIXME: Some clients of LayoutText (and subclasses) pass Document as node to
create anonymous layoutObject. | 163 // FIXME: Some clients of LayoutText (and subclasses) pass Document as node to |
| 164 // create anonymous layoutObject. |
| 163 // They should be switched to passing null and using setDocumentForAnonymous. | 165 // They should be switched to passing null and using setDocumentForAnonymous. |
| 164 if (node && node->isDocumentNode()) | 166 if (node && node->isDocumentNode()) |
| 165 setDocumentForAnonymous(toDocument(node)); | 167 setDocumentForAnonymous(toDocument(node)); |
| 166 | 168 |
| 167 m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath(); | 169 m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath(); |
| 168 setIsText(); | 170 setIsText(); |
| 169 | 171 |
| 170 view()->frameView()->incrementVisuallyNonEmptyCharacterCount(m_text.length()); | 172 view()->frameView()->incrementVisuallyNonEmptyCharacterCount(m_text.length()); |
| 171 } | 173 } |
| 172 | 174 |
| 173 #if ENABLE(ASSERT) | 175 #if ENABLE(ASSERT) |
| 174 | 176 |
| 175 LayoutText::~LayoutText() { | 177 LayoutText::~LayoutText() { |
| 176 ASSERT(!m_firstTextBox); | 178 ASSERT(!m_firstTextBox); |
| 177 ASSERT(!m_lastTextBox); | 179 ASSERT(!m_lastTextBox); |
| 178 } | 180 } |
| 179 | 181 |
| 180 #endif | 182 #endif |
| 181 | 183 |
| 182 bool LayoutText::isTextFragment() const { | 184 bool LayoutText::isTextFragment() const { |
| 183 return false; | 185 return false; |
| 184 } | 186 } |
| 185 | 187 |
| 186 bool LayoutText::isWordBreak() const { | 188 bool LayoutText::isWordBreak() const { |
| 187 return false; | 189 return false; |
| 188 } | 190 } |
| 189 | 191 |
| 190 void LayoutText::styleDidChange(StyleDifference diff, | 192 void LayoutText::styleDidChange(StyleDifference diff, |
| 191 const ComputedStyle* oldStyle) { | 193 const ComputedStyle* oldStyle) { |
| 192 // There is no need to ever schedule paint invalidations from a style change o
f a text run, since | 194 // There is no need to ever schedule paint invalidations from a style change |
| 193 // we already did this for the parent of the text run. | 195 // of a text run, since we already did this for the parent of the text run. |
| 194 // We do have to schedule layouts, though, since a style change can force us t
o | 196 // We do have to schedule layouts, though, since a style change can force us |
| 195 // need to relayout. | 197 // to need to relayout. |
| 196 if (diff.needsFullLayout()) { | 198 if (diff.needsFullLayout()) { |
| 197 setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::StyleChange); | 199 setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::StyleChange); |
| 198 m_knownToHaveNoOverflowAndNoFallbackFonts = false; | 200 m_knownToHaveNoOverflowAndNoFallbackFonts = false; |
| 199 } | 201 } |
| 200 | 202 |
| 201 const ComputedStyle& newStyle = styleRef(); | 203 const ComputedStyle& newStyle = styleRef(); |
| 202 ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE; | 204 ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE; |
| 203 ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE; | 205 ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE; |
| 204 if (oldTransform != newStyle.textTransform() || | 206 if (oldTransform != newStyle.textTransform() || |
| 205 oldSecurity != newStyle.textSecurity()) | 207 oldSecurity != newStyle.textSecurity()) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 | 300 |
| 299 PassRefPtr<StringImpl> LayoutText::originalText() const { | 301 PassRefPtr<StringImpl> LayoutText::originalText() const { |
| 300 Node* e = node(); | 302 Node* e = node(); |
| 301 return (e && e->isTextNode()) ? toText(e)->dataImpl() : 0; | 303 return (e && e->isTextNode()) ? toText(e)->dataImpl() : 0; |
| 302 } | 304 } |
| 303 | 305 |
| 304 String LayoutText::plainText() const { | 306 String LayoutText::plainText() const { |
| 305 if (node()) | 307 if (node()) |
| 306 return blink::plainText(EphemeralRange::rangeOfContents(*node())); | 308 return blink::plainText(EphemeralRange::rangeOfContents(*node())); |
| 307 | 309 |
| 308 // FIXME: this is just a stopgap until TextIterator is adapted to support gene
rated text. | 310 // FIXME: this is just a stopgap until TextIterator is adapted to support |
| 311 // generated text. |
| 309 StringBuilder plainTextBuilder; | 312 StringBuilder plainTextBuilder; |
| 310 for (InlineTextBox* textBox = firstTextBox(); textBox; | 313 for (InlineTextBox* textBox = firstTextBox(); textBox; |
| 311 textBox = textBox->nextTextBox()) { | 314 textBox = textBox->nextTextBox()) { |
| 312 String text = m_text.substring(textBox->start(), textBox->len()) | 315 String text = m_text.substring(textBox->start(), textBox->len()) |
| 313 .simplifyWhiteSpace(WTF::DoNotStripWhiteSpace); | 316 .simplifyWhiteSpace(WTF::DoNotStripWhiteSpace); |
| 314 plainTextBuilder.append(text); | 317 plainTextBuilder.append(text); |
| 315 if (textBox->nextTextBox() && | 318 if (textBox->nextTextBox() && |
| 316 textBox->nextTextBox()->start() > textBox->end() && text.length() && | 319 textBox->nextTextBox()->start() > textBox->end() && text.length() && |
| 317 !text.right(1).containsOnlyWhitespace()) | 320 !text.right(1).containsOnlyWhitespace()) |
| 318 plainTextBuilder.append(spaceCharacter); | 321 plainTextBuilder.append(spaceCharacter); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 347 } | 350 } |
| 348 return FloatRect(r); | 351 return FloatRect(r); |
| 349 } | 352 } |
| 350 return FloatRect(); | 353 return FloatRect(); |
| 351 } | 354 } |
| 352 | 355 |
| 353 void LayoutText::absoluteRectsForRange(Vector<IntRect>& rects, | 356 void LayoutText::absoluteRectsForRange(Vector<IntRect>& rects, |
| 354 unsigned start, | 357 unsigned start, |
| 355 unsigned end, | 358 unsigned end, |
| 356 bool useSelectionHeight) { | 359 bool useSelectionHeight) { |
| 357 // Work around signed/unsigned issues. This function takes unsigneds, and is o
ften passed UINT_MAX | 360 // Work around signed/unsigned issues. This function takes unsigneds, and is |
| 358 // to mean "all the way to the end". InlineTextBox coordinates are unsigneds,
so changing this | 361 // often passed UINT_MAX to mean "all the way to the end". InlineTextBox |
| 359 // function to take ints causes various internal mismatches. But selectionRect
takes ints, and | 362 // coordinates are unsigneds, so changing this function to take ints causes |
| 360 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to
take unsigneds, but | 363 // various internal mismatches. But selectionRect takes ints, and passing |
| 361 // that would cause many ripple effects, so for now we'll just clamp our unsig
ned parameters to INT_MAX. | 364 // UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take |
| 365 // unsigneds, but that would cause many ripple effects, so for now we'll just |
| 366 // clamp our unsigned parameters to INT_MAX. |
| 362 ASSERT(end == UINT_MAX || end <= INT_MAX); | 367 ASSERT(end == UINT_MAX || end <= INT_MAX); |
| 363 ASSERT(start <= INT_MAX); | 368 ASSERT(start <= INT_MAX); |
| 364 start = std::min(start, static_cast<unsigned>(INT_MAX)); | 369 start = std::min(start, static_cast<unsigned>(INT_MAX)); |
| 365 end = std::min(end, static_cast<unsigned>(INT_MAX)); | 370 end = std::min(end, static_cast<unsigned>(INT_MAX)); |
| 366 | 371 |
| 367 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 372 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 368 // Note: box->end() returns the index of the last character, not the index p
ast it | 373 // Note: box->end() returns the index of the last character, not the index |
| 374 // past it |
| 369 if (start <= box->start() && box->end() < end) { | 375 if (start <= box->start() && box->end() < end) { |
| 370 FloatRect r(box->calculateBoundaries()); | 376 FloatRect r(box->calculateBoundaries()); |
| 371 if (useSelectionHeight) { | 377 if (useSelectionHeight) { |
| 372 LayoutRect selectionRect = box->localSelectionRect(start, end); | 378 LayoutRect selectionRect = box->localSelectionRect(start, end); |
| 373 if (box->isHorizontal()) { | 379 if (box->isHorizontal()) { |
| 374 r.setHeight(selectionRect.height().toFloat()); | 380 r.setHeight(selectionRect.height().toFloat()); |
| 375 r.setY(selectionRect.y().toFloat()); | 381 r.setY(selectionRect.y().toFloat()); |
| 376 } else { | 382 } else { |
| 377 r.setWidth(selectionRect.width().toFloat()); | 383 r.setWidth(selectionRect.width().toFloat()); |
| 378 r.setX(selectionRect.x().toFloat()); | 384 r.setX(selectionRect.x().toFloat()); |
| 379 } | 385 } |
| 380 } | 386 } |
| 381 rects.append(localToAbsoluteQuad(r).enclosingBoundingBox()); | 387 rects.append(localToAbsoluteQuad(r).enclosingBoundingBox()); |
| 382 } else { | 388 } else { |
| 383 // FIXME: This code is wrong. It's converting local to absolute twice. htt
p://webkit.org/b/65722 | 389 // FIXME: This code is wrong. It's converting local to absolute twice. |
| 390 // http://webkit.org/b/65722 |
| 384 FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHeight); | 391 FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHeight); |
| 385 if (!rect.isZero()) | 392 if (!rect.isZero()) |
| 386 rects.append(localToAbsoluteQuad(rect).enclosingBoundingBox()); | 393 rects.append(localToAbsoluteQuad(rect).enclosingBoundingBox()); |
| 387 } | 394 } |
| 388 } | 395 } |
| 389 } | 396 } |
| 390 | 397 |
| 391 static IntRect ellipsisRectForBox(InlineTextBox* box, | 398 static IntRect ellipsisRectForBox(InlineTextBox* box, |
| 392 unsigned startPos, | 399 unsigned startPos, |
| 393 unsigned endPos) { | 400 unsigned endPos) { |
| 394 if (!box) | 401 if (!box) |
| 395 return IntRect(); | 402 return IntRect(); |
| 396 | 403 |
| 397 unsigned short truncation = box->truncation(); | 404 unsigned short truncation = box->truncation(); |
| 398 if (truncation == cNoTruncation) | 405 if (truncation == cNoTruncation) |
| 399 return IntRect(); | 406 return IntRect(); |
| 400 | 407 |
| 401 IntRect rect; | 408 IntRect rect; |
| 402 if (EllipsisBox* ellipsis = box->root().ellipsisBox()) { | 409 if (EllipsisBox* ellipsis = box->root().ellipsisBox()) { |
| 403 int ellipsisStartPosition = std::max<int>(startPos - box->start(), 0); | 410 int ellipsisStartPosition = std::max<int>(startPos - box->start(), 0); |
| 404 int ellipsisEndPosition = std::min<int>(endPos - box->start(), box->len()); | 411 int ellipsisEndPosition = std::min<int>(endPos - box->start(), box->len()); |
| 405 | 412 |
| 406 // The ellipsis should be considered to be selected if the end of | 413 // The ellipsis should be considered to be selected if the end of the |
| 407 // the selection is past the beginning of the truncation and the | 414 // selection is past the beginning of the truncation and the beginning of |
| 408 // beginning of the selection is before or at the beginning of the truncatio
n. | 415 // the selection is before or at the beginning of the truncation. |
| 409 if (ellipsisEndPosition >= truncation && | 416 if (ellipsisEndPosition >= truncation && |
| 410 ellipsisStartPosition <= truncation) | 417 ellipsisStartPosition <= truncation) |
| 411 return ellipsis->selectionRect(); | 418 return ellipsis->selectionRect(); |
| 412 } | 419 } |
| 413 | 420 |
| 414 return IntRect(); | 421 return IntRect(); |
| 415 } | 422 } |
| 416 | 423 |
| 417 void LayoutText::quads(Vector<FloatQuad>& quads, | 424 void LayoutText::quads(Vector<FloatQuad>& quads, |
| 418 ClippingOption option, | 425 ClippingOption option, |
| 419 LocalOrAbsoluteOption localOrAbsolute) const { | 426 LocalOrAbsoluteOption localOrAbsolute) const { |
| 420 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 427 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 421 FloatRect boundaries(box->calculateBoundaries()); | 428 FloatRect boundaries(box->calculateBoundaries()); |
| 422 | 429 |
| 423 // Shorten the width of this text box if it ends in an ellipsis. | 430 // Shorten the width of this text box if it ends in an ellipsis. |
| 424 // FIXME: ellipsisRectForBox should switch to return FloatRect soon with the
subpixellayout branch. | 431 // FIXME: ellipsisRectForBox should switch to return FloatRect soon with the |
| 432 // subpixellayout branch. |
| 425 IntRect ellipsisRect = (option == ClipToEllipsis) | 433 IntRect ellipsisRect = (option == ClipToEllipsis) |
| 426 ? ellipsisRectForBox(box, 0, textLength()) | 434 ? ellipsisRectForBox(box, 0, textLength()) |
| 427 : IntRect(); | 435 : IntRect(); |
| 428 if (!ellipsisRect.isEmpty()) { | 436 if (!ellipsisRect.isEmpty()) { |
| 429 if (style()->isHorizontalWritingMode()) | 437 if (style()->isHorizontalWritingMode()) |
| 430 boundaries.setWidth(ellipsisRect.maxX() - boundaries.x()); | 438 boundaries.setWidth(ellipsisRect.maxX() - boundaries.x()); |
| 431 else | 439 else |
| 432 boundaries.setHeight(ellipsisRect.maxY() - boundaries.y()); | 440 boundaries.setHeight(ellipsisRect.maxY() - boundaries.y()); |
| 433 } | 441 } |
| 434 if (localOrAbsolute == AbsoluteQuads) | 442 if (localOrAbsolute == AbsoluteQuads) |
| 435 quads.append(localToAbsoluteQuad(boundaries)); | 443 quads.append(localToAbsoluteQuad(boundaries)); |
| 436 else | 444 else |
| 437 quads.append(boundaries); | 445 quads.append(boundaries); |
| 438 } | 446 } |
| 439 } | 447 } |
| 440 | 448 |
| 441 void LayoutText::absoluteQuads(Vector<FloatQuad>& quads) const { | 449 void LayoutText::absoluteQuads(Vector<FloatQuad>& quads) const { |
| 442 this->quads(quads, NoClipping, AbsoluteQuads); | 450 this->quads(quads, NoClipping, AbsoluteQuads); |
| 443 } | 451 } |
| 444 | 452 |
| 445 void LayoutText::absoluteQuadsForRange(Vector<FloatQuad>& quads, | 453 void LayoutText::absoluteQuadsForRange(Vector<FloatQuad>& quads, |
| 446 unsigned start, | 454 unsigned start, |
| 447 unsigned end, | 455 unsigned end, |
| 448 bool useSelectionHeight) { | 456 bool useSelectionHeight) { |
| 449 // Work around signed/unsigned issues. This function takes unsigneds, and is o
ften passed UINT_MAX | 457 // Work around signed/unsigned issues. This function takes unsigneds, and is |
| 450 // to mean "all the way to the end". InlineTextBox coordinates are unsigneds,
so changing this | 458 // often passed UINT_MAX to mean "all the way to the end". InlineTextBox |
| 451 // function to take ints causes various internal mismatches. But selectionRect
takes ints, and | 459 // coordinates are unsigneds, so changing this function to take ints causes |
| 452 // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to
take unsigneds, but | 460 // various internal mismatches. But selectionRect takes ints, and passing |
| 453 // that would cause many ripple effects, so for now we'll just clamp our unsig
ned parameters to INT_MAX. | 461 // UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take |
| 462 // unsigneds, but that would cause many ripple effects, so for now we'll just |
| 463 // clamp our unsigned parameters to INT_MAX. |
| 454 ASSERT(end == UINT_MAX || end <= INT_MAX); | 464 ASSERT(end == UINT_MAX || end <= INT_MAX); |
| 455 ASSERT(start <= INT_MAX); | 465 ASSERT(start <= INT_MAX); |
| 456 start = std::min(start, static_cast<unsigned>(INT_MAX)); | 466 start = std::min(start, static_cast<unsigned>(INT_MAX)); |
| 457 end = std::min(end, static_cast<unsigned>(INT_MAX)); | 467 end = std::min(end, static_cast<unsigned>(INT_MAX)); |
| 458 | 468 |
| 459 const unsigned caretMinOffset = static_cast<unsigned>(this->caretMinOffset()); | 469 const unsigned caretMinOffset = static_cast<unsigned>(this->caretMinOffset()); |
| 460 const unsigned caretMaxOffset = static_cast<unsigned>(this->caretMaxOffset()); | 470 const unsigned caretMaxOffset = static_cast<unsigned>(this->caretMaxOffset()); |
| 461 | 471 |
| 462 // Narrows |start| and |end| into |caretMinOffset| and |careMaxOffset| | 472 // Narrows |start| and |end| into |caretMinOffset| and |careMaxOffset| |
| 463 // to ignore unrendered leading and trailing whitespaces. | 473 // to ignore unrendered leading and trailing whitespaces. |
| 464 start = std::min(std::max(caretMinOffset, start), caretMaxOffset); | 474 start = std::min(std::max(caretMinOffset, start), caretMaxOffset); |
| 465 end = std::min(std::max(caretMinOffset, end), caretMaxOffset); | 475 end = std::min(std::max(caretMinOffset, end), caretMaxOffset); |
| 466 | 476 |
| 467 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 477 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 468 // Note: box->end() returns the index of the last character, not the index p
ast it | 478 // Note: box->end() returns the index of the last character, not the index |
| 479 // past it |
| 469 if (start <= box->start() && box->end() < end) { | 480 if (start <= box->start() && box->end() < end) { |
| 470 LayoutRect r(box->calculateBoundaries()); | 481 LayoutRect r(box->calculateBoundaries()); |
| 471 if (useSelectionHeight) { | 482 if (useSelectionHeight) { |
| 472 LayoutRect selectionRect = box->localSelectionRect(start, end); | 483 LayoutRect selectionRect = box->localSelectionRect(start, end); |
| 473 if (box->isHorizontal()) { | 484 if (box->isHorizontal()) { |
| 474 r.setHeight(selectionRect.height()); | 485 r.setHeight(selectionRect.height()); |
| 475 r.setY(selectionRect.y()); | 486 r.setY(selectionRect.y()); |
| 476 } else { | 487 } else { |
| 477 r.setWidth(selectionRect.width()); | 488 r.setWidth(selectionRect.width()); |
| 478 r.setX(selectionRect.x()); | 489 r.setX(selectionRect.x()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 501 AlwaysUpstream, | 512 AlwaysUpstream, |
| 502 UpstreamIfPositionIsNotAtStart | 513 UpstreamIfPositionIsNotAtStart |
| 503 }; | 514 }; |
| 504 | 515 |
| 505 static bool lineDirectionPointFitsInBox( | 516 static bool lineDirectionPointFitsInBox( |
| 506 int pointLineDirection, | 517 int pointLineDirection, |
| 507 InlineTextBox* box, | 518 InlineTextBox* box, |
| 508 ShouldAffinityBeDownstream& shouldAffinityBeDownstream) { | 519 ShouldAffinityBeDownstream& shouldAffinityBeDownstream) { |
| 509 shouldAffinityBeDownstream = AlwaysDownstream; | 520 shouldAffinityBeDownstream = AlwaysDownstream; |
| 510 | 521 |
| 511 // the x coordinate is equal to the left edge of this box | 522 // the x coordinate is equal to the left edge of this box the affinity must be |
| 512 // the affinity must be downstream so the position doesn't jump back to the pr
evious line | 523 // downstream so the position doesn't jump back to the previous line except |
| 513 // except when box is the first box in the line | 524 // when box is the first box in the line |
| 514 if (pointLineDirection <= box->logicalLeft()) { | 525 if (pointLineDirection <= box->logicalLeft()) { |
| 515 shouldAffinityBeDownstream = !box->prevLeafChild() | 526 shouldAffinityBeDownstream = !box->prevLeafChild() |
| 516 ? UpstreamIfPositionIsNotAtStart | 527 ? UpstreamIfPositionIsNotAtStart |
| 517 : AlwaysDownstream; | 528 : AlwaysDownstream; |
| 518 return true; | 529 return true; |
| 519 } | 530 } |
| 520 | 531 |
| 521 // and the x coordinate is to the left of the right edge of this box | 532 // and the x coordinate is to the left of the right edge of this box |
| 522 // check to see if position goes in this box | 533 // check to see if position goes in this box |
| 523 if (pointLineDirection < box->logicalRight()) { | 534 if (pointLineDirection < box->logicalRight()) { |
| 524 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart; | 535 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart; |
| 525 return true; | 536 return true; |
| 526 } | 537 } |
| 527 | 538 |
| 528 // box is first on line | 539 // box is first on line |
| 529 // and the x coordinate is to the left of the first text box left edge | 540 // and the x coordinate is to the left of the first text box left edge |
| 530 if (!box->prevLeafChildIgnoringLineBreak() && | 541 if (!box->prevLeafChildIgnoringLineBreak() && |
| 531 pointLineDirection < box->logicalLeft()) | 542 pointLineDirection < box->logicalLeft()) |
| 532 return true; | 543 return true; |
| 533 | 544 |
| 534 if (!box->nextLeafChildIgnoringLineBreak()) { | 545 if (!box->nextLeafChildIgnoringLineBreak()) { |
| 535 // box is last on line | 546 // box is last on line and the x coordinate is to the right of the last text |
| 536 // and the x coordinate is to the right of the last text box right edge | 547 // box right edge generate VisiblePosition, use TextAffinity::Upstream |
| 537 // generate VisiblePosition, use TextAffinity::Upstream affinity if possible | 548 // affinity if possible |
| 538 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart; | 549 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart; |
| 539 return true; | 550 return true; |
| 540 } | 551 } |
| 541 | 552 |
| 542 return false; | 553 return false; |
| 543 } | 554 } |
| 544 | 555 |
| 545 static PositionWithAffinity createPositionWithAffinityForBox( | 556 static PositionWithAffinity createPositionWithAffinityForBox( |
| 546 const InlineBox* box, | 557 const InlineBox* box, |
| 547 int offset, | 558 int offset, |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 break; | 775 break; |
| 765 case JUSTIFY: | 776 case JUSTIFY: |
| 766 case TASTART: | 777 case TASTART: |
| 767 rightAligned = !cbStyle.isLeftToRightDirection(); | 778 rightAligned = !cbStyle.isLeftToRightDirection(); |
| 768 break; | 779 break; |
| 769 case TAEND: | 780 case TAEND: |
| 770 rightAligned = cbStyle.isLeftToRightDirection(); | 781 rightAligned = cbStyle.isLeftToRightDirection(); |
| 771 break; | 782 break; |
| 772 } | 783 } |
| 773 | 784 |
| 774 // for unicode-bidi: plaintext, use inlineBoxBidiLevel() to test the correct d
irection for the cursor. | 785 // for unicode-bidi: plaintext, use inlineBoxBidiLevel() to test the correct |
| 786 // direction for the cursor. |
| 775 if (rightAligned && style()->unicodeBidi() == Plaintext) { | 787 if (rightAligned && style()->unicodeBidi() == Plaintext) { |
| 776 if (inlineBox->bidiLevel() % 2 != 1) | 788 if (inlineBox->bidiLevel() % 2 != 1) |
| 777 rightAligned = false; | 789 rightAligned = false; |
| 778 } | 790 } |
| 779 | 791 |
| 780 if (rightAligned) { | 792 if (rightAligned) { |
| 781 left = std::max(left, leftEdge); | 793 left = std::max(left, leftEdge); |
| 782 left = std::min(left, rootRight - caretWidth()); | 794 left = std::min(left, rootRight - caretWidth()); |
| 783 } else { | 795 } else { |
| 784 left = std::min(left, rightEdge - caretWidthRightOfOffset); | 796 left = std::min(left, rightEdge - caretWidthRightOfOffset); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 bool& hasBreakableChar, | 843 bool& hasBreakableChar, |
| 832 bool& hasBreak, | 844 bool& hasBreak, |
| 833 LayoutUnit& firstLineMaxWidth, | 845 LayoutUnit& firstLineMaxWidth, |
| 834 LayoutUnit& lastLineMaxWidth, | 846 LayoutUnit& lastLineMaxWidth, |
| 835 LayoutUnit& minWidth, | 847 LayoutUnit& minWidth, |
| 836 LayoutUnit& maxWidth, | 848 LayoutUnit& maxWidth, |
| 837 bool& stripFrontSpaces, | 849 bool& stripFrontSpaces, |
| 838 TextDirection direction) { | 850 TextDirection direction) { |
| 839 float floatMinWidth = 0.0f, floatMaxWidth = 0.0f; | 851 float floatMinWidth = 0.0f, floatMaxWidth = 0.0f; |
| 840 | 852 |
| 841 // Convert leadWidth to a float here, to avoid multiple implict conversions be
low. | 853 // Convert leadWidth to a float here, to avoid multiple implict conversions |
| 854 // below. |
| 842 float leadWidth = leadWidthLayoutUnit.toFloat(); | 855 float leadWidth = leadWidthLayoutUnit.toFloat(); |
| 843 | 856 |
| 844 bool collapseWhiteSpace = style()->collapseWhiteSpace(); | 857 bool collapseWhiteSpace = style()->collapseWhiteSpace(); |
| 845 if (!collapseWhiteSpace) | 858 if (!collapseWhiteSpace) |
| 846 stripFrontSpaces = false; | 859 stripFrontSpaces = false; |
| 847 | 860 |
| 848 if (m_hasTab || preferredLogicalWidthsDirty()) | 861 if (m_hasTab || preferredLogicalWidthsDirty()) |
| 849 computePreferredLogicalWidths(leadWidth); | 862 computePreferredLogicalWidths(leadWidth); |
| 850 | 863 |
| 851 hasBreakableStart = !stripFrontSpaces && m_hasBreakableStart; | 864 hasBreakableStart = !stripFrontSpaces && m_hasBreakableStart; |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 } | 1161 } |
| 1149 } | 1162 } |
| 1150 | 1163 |
| 1151 // Terminate word boundary at bidi run boundary. | 1164 // Terminate word boundary at bidi run boundary. |
| 1152 if (run) | 1165 if (run) |
| 1153 j = std::min(j, run->stop() + 1); | 1166 j = std::min(j, run->stop() + 1); |
| 1154 int wordLen = j - i; | 1167 int wordLen = j - i; |
| 1155 if (wordLen) { | 1168 if (wordLen) { |
| 1156 bool isSpace = (j < len) && c == spaceCharacter; | 1169 bool isSpace = (j < len) && c == spaceCharacter; |
| 1157 | 1170 |
| 1158 // Non-zero only when kerning is enabled, in which case we measure words w
ith their trailing | 1171 // Non-zero only when kerning is enabled, in which case we measure words |
| 1159 // space, then subtract its width. | 1172 // with their trailing space, then subtract its width. |
| 1160 float wordTrailingSpaceWidth = 0; | 1173 float wordTrailingSpaceWidth = 0; |
| 1161 if (isSpace && | 1174 if (isSpace && |
| 1162 (f.getFontDescription().getTypesettingFeatures() & Kerning)) { | 1175 (f.getFontDescription().getTypesettingFeatures() & Kerning)) { |
| 1163 ASSERT(textDirection >= 0 && textDirection <= 1); | 1176 ASSERT(textDirection >= 0 && textDirection <= 1); |
| 1164 if (!cachedWordTrailingSpaceWidth[textDirection]) | 1177 if (!cachedWordTrailingSpaceWidth[textDirection]) |
| 1165 cachedWordTrailingSpaceWidth[textDirection] = | 1178 cachedWordTrailingSpaceWidth[textDirection] = |
| 1166 f.width(constructTextRun(f, &spaceCharacter, 1, styleToUse, | 1179 f.width(constructTextRun(f, &spaceCharacter, 1, styleToUse, |
| 1167 textDirection)) + | 1180 textDirection)) + |
| 1168 wordSpacing; | 1181 wordSpacing; |
| 1169 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirection]; | 1182 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirection]; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 f, lastWordBoundary, j - lastWordBoundary, leadWidth, | 1229 f, lastWordBoundary, j - lastWordBoundary, leadWidth, |
| 1217 currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); | 1230 currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); |
| 1218 lastWordBoundary = j; | 1231 lastWordBoundary = j; |
| 1219 } | 1232 } |
| 1220 | 1233 |
| 1221 bool isCollapsibleWhiteSpace = | 1234 bool isCollapsibleWhiteSpace = |
| 1222 (j < len) && styleToUse.isCollapsibleWhiteSpace(c); | 1235 (j < len) && styleToUse.isCollapsibleWhiteSpace(c); |
| 1223 if (j < len && styleToUse.autoWrap()) | 1236 if (j < len && styleToUse.autoWrap()) |
| 1224 m_hasBreakableChar = true; | 1237 m_hasBreakableChar = true; |
| 1225 | 1238 |
| 1226 // Add in wordSpacing to our currMaxWidth, but not if this is the last wor
d on a line or the | 1239 // Add in wordSpacing to our currMaxWidth, but not if this is the last |
| 1240 // word on a line or the |
| 1227 // last word in the run. | 1241 // last word in the run. |
| 1228 if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && | 1242 if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && |
| 1229 !containsOnlyWhitespace(j, len - j)) | 1243 !containsOnlyWhitespace(j, len - j)) |
| 1230 currMaxWidth += wordSpacing; | 1244 currMaxWidth += wordSpacing; |
| 1231 | 1245 |
| 1232 if (firstWord) { | 1246 if (firstWord) { |
| 1233 firstWord = false; | 1247 firstWord = false; |
| 1234 // If the first character in the run is breakable, then we consider ours
elves to have a beginning | 1248 // If the first character in the run is breakable, then we consider |
| 1235 // minimum width of 0, since a break could occur right before our run st
arts, preventing us from ever | 1249 // ourselves to have a beginning minimum width of 0, since a break could |
| 1236 // being appended to a previous text run when considering the total mini
mum width of the containing block. | 1250 // occur right before our run starts, preventing us from ever being |
| 1251 // appended to a previous text run when considering the total minimum |
| 1252 // width of the containing block. |
| 1237 if (hasBreak) | 1253 if (hasBreak) |
| 1238 m_hasBreakableChar = true; | 1254 m_hasBreakableChar = true; |
| 1239 m_firstLineMinWidth = hasBreak ? 0 : currMinWidth; | 1255 m_firstLineMinWidth = hasBreak ? 0 : currMinWidth; |
| 1240 } | 1256 } |
| 1241 m_lastLineLineMinWidth = currMinWidth; | 1257 m_lastLineLineMinWidth = currMinWidth; |
| 1242 | 1258 |
| 1243 if (currMinWidth > m_minWidth) | 1259 if (currMinWidth > m_minWidth) |
| 1244 m_minWidth = currMinWidth; | 1260 m_minWidth = currMinWidth; |
| 1245 currMinWidth = 0; | 1261 currMinWidth = 0; |
| 1246 | 1262 |
| 1247 i += wordLen - 1; | 1263 i += wordLen - 1; |
| 1248 } else { | 1264 } else { |
| 1249 // Nowrap can never be broken, so don't bother setting the | 1265 // Nowrap can never be broken, so don't bother setting the breakable |
| 1250 // breakable character boolean. Pre can only be broken if we encounter a n
ewline. | 1266 // character boolean. Pre can only be broken if we encounter a newline. |
| 1251 if (style()->autoWrap() || isNewline) | 1267 if (style()->autoWrap() || isNewline) |
| 1252 m_hasBreakableChar = true; | 1268 m_hasBreakableChar = true; |
| 1253 | 1269 |
| 1254 if (currMinWidth > m_minWidth) | 1270 if (currMinWidth > m_minWidth) |
| 1255 m_minWidth = currMinWidth; | 1271 m_minWidth = currMinWidth; |
| 1256 currMinWidth = 0; | 1272 currMinWidth = 0; |
| 1257 | 1273 |
| 1258 if (isNewline) { // Only set if preserveNewline was true and we saw a new
line. | 1274 // Only set if preserveNewline was true and we saw a newline. |
| 1275 if (isNewline) { |
| 1259 if (firstLine) { | 1276 if (firstLine) { |
| 1260 firstLine = false; | 1277 firstLine = false; |
| 1261 leadWidth = 0; | 1278 leadWidth = 0; |
| 1262 if (!styleToUse.autoWrap()) | 1279 if (!styleToUse.autoWrap()) |
| 1263 m_firstLineMinWidth = currMaxWidth; | 1280 m_firstLineMinWidth = currMaxWidth; |
| 1264 } | 1281 } |
| 1265 | 1282 |
| 1266 if (currMaxWidth > m_maxWidth) | 1283 if (currMaxWidth > m_maxWidth) |
| 1267 m_maxWidth = currMaxWidth; | 1284 m_maxWidth = currMaxWidth; |
| 1268 currMaxWidth = 0; | 1285 currMaxWidth = 0; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 if (!style()->isCollapsibleWhiteSpace(characters16()[i])) | 1341 if (!style()->isCollapsibleWhiteSpace(characters16()[i])) |
| 1325 return false; | 1342 return false; |
| 1326 } | 1343 } |
| 1327 return true; | 1344 return true; |
| 1328 } | 1345 } |
| 1329 | 1346 |
| 1330 bool LayoutText::isRenderedCharacter(int offsetInNode) const { | 1347 bool LayoutText::isRenderedCharacter(int offsetInNode) const { |
| 1331 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { | 1348 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { |
| 1332 if (offsetInNode < static_cast<int>(box->start()) && | 1349 if (offsetInNode < static_cast<int>(box->start()) && |
| 1333 !containsReversedText()) { | 1350 !containsReversedText()) { |
| 1334 // The offset we're looking for is before this node | 1351 // The offset we're looking for is before this node this means the offset |
| 1335 // this means the offset must be in content that is | 1352 // must be in content that is not laid out. Return false. |
| 1336 // not laid out. Return false. | |
| 1337 return false; | 1353 return false; |
| 1338 } | 1354 } |
| 1339 if (offsetInNode >= static_cast<int>(box->start()) && | 1355 if (offsetInNode >= static_cast<int>(box->start()) && |
| 1340 offsetInNode < static_cast<int>(box->start() + box->len())) | 1356 offsetInNode < static_cast<int>(box->start() + box->len())) |
| 1341 return true; | 1357 return true; |
| 1342 } | 1358 } |
| 1343 | 1359 |
| 1344 return false; | 1360 return false; |
| 1345 } | 1361 } |
| 1346 | 1362 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 unsigned oldLen = textLength(); | 1431 unsigned oldLen = textLength(); |
| 1416 unsigned newLen = text->length(); | 1432 unsigned newLen = text->length(); |
| 1417 int delta = newLen - oldLen; | 1433 int delta = newLen - oldLen; |
| 1418 unsigned end = len ? offset + len - 1 : offset; | 1434 unsigned end = len ? offset + len - 1 : offset; |
| 1419 | 1435 |
| 1420 RootInlineBox* firstRootBox = nullptr; | 1436 RootInlineBox* firstRootBox = nullptr; |
| 1421 RootInlineBox* lastRootBox = nullptr; | 1437 RootInlineBox* lastRootBox = nullptr; |
| 1422 | 1438 |
| 1423 bool dirtiedLines = false; | 1439 bool dirtiedLines = false; |
| 1424 | 1440 |
| 1425 // Dirty all text boxes that include characters in between offset and offset+l
en. | 1441 // Dirty all text boxes that include characters in between offset and |
| 1442 // offset+len. |
| 1426 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) { | 1443 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) { |
| 1427 // FIXME: This shouldn't rely on the end of a dirty line box. See https://bu
gs.webkit.org/show_bug.cgi?id=97264 | 1444 // FIXME: This shouldn't rely on the end of a dirty line box. See |
| 1445 // https://bugs.webkit.org/show_bug.cgi?id=97264 |
| 1428 // Text run is entirely before the affected range. | 1446 // Text run is entirely before the affected range. |
| 1429 if (curr->end() < offset) | 1447 if (curr->end() < offset) |
| 1430 continue; | 1448 continue; |
| 1431 | 1449 |
| 1432 // Text run is entirely after the affected range. | 1450 // Text run is entirely after the affected range. |
| 1433 if (curr->start() > end) { | 1451 if (curr->start() > end) { |
| 1434 curr->offsetRun(delta); | 1452 curr->offsetRun(delta); |
| 1435 RootInlineBox* root = &curr->root(); | 1453 RootInlineBox* root = &curr->root(); |
| 1436 if (!firstRootBox) { | 1454 if (!firstRootBox) { |
| 1437 firstRootBox = root; | 1455 firstRootBox = root; |
| 1438 // The affected area was in between two runs. Go ahead and mark the root
box of | 1456 // The affected area was in between two runs. Go ahead and mark the root |
| 1439 // the run after the affected area as dirty. | 1457 // box of the run after the affected area as dirty. |
| 1440 firstRootBox->markDirty(); | 1458 firstRootBox->markDirty(); |
| 1441 dirtiedLines = true; | 1459 dirtiedLines = true; |
| 1442 } | 1460 } |
| 1443 lastRootBox = root; | 1461 lastRootBox = root; |
| 1444 } else if (curr->end() >= offset && curr->end() <= end) { | 1462 } else if (curr->end() >= offset && curr->end() <= end) { |
| 1445 // Text run overlaps with the left end of the affected range. | 1463 // Text run overlaps with the left end of the affected range. |
| 1446 curr->dirtyLineBoxes(); | 1464 curr->dirtyLineBoxes(); |
| 1447 dirtiedLines = true; | 1465 dirtiedLines = true; |
| 1448 } else if (curr->start() <= offset && curr->end() >= end) { | 1466 } else if (curr->start() <= offset && curr->end() >= end) { |
| 1449 // Text run subsumes the affected range. | 1467 // Text run subsumes the affected range. |
| 1450 curr->dirtyLineBoxes(); | 1468 curr->dirtyLineBoxes(); |
| 1451 dirtiedLines = true; | 1469 dirtiedLines = true; |
| 1452 } else if (curr->start() <= end && curr->end() >= end) { | 1470 } else if (curr->start() <= end && curr->end() >= end) { |
| 1453 // Text run overlaps with right end of the affected range. | 1471 // Text run overlaps with right end of the affected range. |
| 1454 curr->dirtyLineBoxes(); | 1472 curr->dirtyLineBoxes(); |
| 1455 dirtiedLines = true; | 1473 dirtiedLines = true; |
| 1456 } | 1474 } |
| 1457 } | 1475 } |
| 1458 | 1476 |
| 1459 // Now we have to walk all of the clean lines and adjust their cached line bre
ak information | 1477 // Now we have to walk all of the clean lines and adjust their cached line |
| 1460 // to reflect our updated offsets. | 1478 // break information to reflect our updated offsets. |
| 1461 if (lastRootBox) | 1479 if (lastRootBox) |
| 1462 lastRootBox = lastRootBox->nextRootBox(); | 1480 lastRootBox = lastRootBox->nextRootBox(); |
| 1463 if (firstRootBox) { | 1481 if (firstRootBox) { |
| 1464 RootInlineBox* prev = firstRootBox->prevRootBox(); | 1482 RootInlineBox* prev = firstRootBox->prevRootBox(); |
| 1465 if (prev) | 1483 if (prev) |
| 1466 firstRootBox = prev; | 1484 firstRootBox = prev; |
| 1467 } else if (lastTextBox()) { | 1485 } else if (lastTextBox()) { |
| 1468 ASSERT(!lastRootBox); | 1486 ASSERT(!lastRootBox); |
| 1469 firstRootBox = &lastTextBox()->root(); | 1487 firstRootBox = &lastTextBox()->root(); |
| 1470 firstRootBox->markDirty(); | 1488 firstRootBox->markDirty(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 lastTypedCharacterOffsetToReveal = | 1601 lastTypedCharacterOffsetToReveal = |
| 1584 secureTextTimer->lastTypedCharacterOffset(); | 1602 secureTextTimer->lastTypedCharacterOffset(); |
| 1585 if (lastTypedCharacterOffsetToReveal >= 0) | 1603 if (lastTypedCharacterOffsetToReveal >= 0) |
| 1586 revealedText = m_text[lastTypedCharacterOffsetToReveal]; | 1604 revealedText = m_text[lastTypedCharacterOffsetToReveal]; |
| 1587 } | 1605 } |
| 1588 | 1606 |
| 1589 m_text.fill(mask); | 1607 m_text.fill(mask); |
| 1590 if (lastTypedCharacterOffsetToReveal >= 0) { | 1608 if (lastTypedCharacterOffsetToReveal >= 0) { |
| 1591 m_text.replace(lastTypedCharacterOffsetToReveal, 1, | 1609 m_text.replace(lastTypedCharacterOffsetToReveal, 1, |
| 1592 String(&revealedText, 1)); | 1610 String(&revealedText, 1)); |
| 1593 // m_text may be updated later before timer fires. We invalidate the lastTyp
edCharacterOffset to avoid inconsistency. | 1611 // m_text may be updated later before timer fires. We invalidate the |
| 1612 // lastTypedCharacterOffset to avoid inconsistency. |
| 1594 secureTextTimer->invalidate(); | 1613 secureTextTimer->invalidate(); |
| 1595 } | 1614 } |
| 1596 } | 1615 } |
| 1597 | 1616 |
| 1598 void LayoutText::setText(PassRefPtr<StringImpl> text, bool force) { | 1617 void LayoutText::setText(PassRefPtr<StringImpl> text, bool force) { |
| 1599 ASSERT(text); | 1618 ASSERT(text); |
| 1600 | 1619 |
| 1601 if (!force && equal(m_text.impl(), text.get())) | 1620 if (!force && equal(m_text.impl(), text.get())) |
| 1602 return; | 1621 return; |
| 1603 | 1622 |
| 1604 setTextInternal(std::move(text)); | 1623 setTextInternal(std::move(text)); |
| 1605 // If preferredLogicalWidthsDirty() of an orphan child is true, LayoutObjectCh
ildList:: | 1624 // If preferredLogicalWidthsDirty() of an orphan child is true, |
| 1606 // insertChildNode() fails to set true to owner. To avoid that, we call | 1625 // LayoutObjectChildList::insertChildNode() fails to set true to owner. |
| 1607 // setNeedsLayoutAndPrefWidthsRecalc() only if this LayoutText has parent. | 1626 // To avoid that, we call setNeedsLayoutAndPrefWidthsRecalc() only if this |
| 1627 // LayoutText has parent. |
| 1608 if (parent()) | 1628 if (parent()) |
| 1609 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 1629 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
| 1610 LayoutInvalidationReason::TextChanged); | 1630 LayoutInvalidationReason::TextChanged); |
| 1611 m_knownToHaveNoOverflowAndNoFallbackFonts = false; | 1631 m_knownToHaveNoOverflowAndNoFallbackFonts = false; |
| 1612 | 1632 |
| 1613 if (AXObjectCache* cache = document().existingAXObjectCache()) | 1633 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 1614 cache->textChanged(this); | 1634 cache->textChanged(this); |
| 1615 } | 1635 } |
| 1616 | 1636 |
| 1617 void LayoutText::dirtyOrDeleteLineBoxesIfNeeded(bool fullLayout) { | 1637 void LayoutText::dirtyOrDeleteLineBoxesIfNeeded(bool fullLayout) { |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1921 LayoutRect rect = LayoutRect( | 1941 LayoutRect rect = LayoutRect( |
| 1922 IntRect(firstRunX(), firstRunY(), linesBox.width(), linesBox.height())); | 1942 IntRect(firstRunX(), firstRunY(), linesBox.width(), linesBox.height())); |
| 1923 LayoutBlock* block = containingBlock(); | 1943 LayoutBlock* block = containingBlock(); |
| 1924 if (block && hasTextBoxes()) | 1944 if (block && hasTextBoxes()) |
| 1925 block->adjustChildDebugRect(rect); | 1945 block->adjustChildDebugRect(rect); |
| 1926 | 1946 |
| 1927 return rect; | 1947 return rect; |
| 1928 } | 1948 } |
| 1929 | 1949 |
| 1930 } // namespace blink | 1950 } // namespace blink |
| OLD | NEW |