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 |