Chromium Code Reviews| Index: Source/core/rendering/RenderBlock.cpp |
| diff --git a/Source/core/rendering/RenderBlock.cpp b/Source/core/rendering/RenderBlock.cpp |
| index e741c8de44b199f3453f59335b4e22abe7517fc6..f26c57f479a48bcc6675730bca7b122620857b42 100644 |
| --- a/Source/core/rendering/RenderBlock.cpp |
| +++ b/Source/core/rendering/RenderBlock.cpp |
| @@ -31,6 +31,7 @@ |
| #include "core/dom/Element.h" |
| #include "core/dom/OverflowEvent.h" |
| #include "core/dom/ShadowRoot.h" |
| +#include "core/dom/Text.h" |
| #include "core/dom/WebCoreMemoryInstrumentation.h" |
| #include "core/editing/Editor.h" |
| #include "core/editing/FrameSelection.h" |
| @@ -6620,6 +6621,31 @@ void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderO |
| } |
| } |
| +static inline unsigned whiteSpaceLength(PassRefPtr<StringImpl> oldText) |
|
esprehn
2013/05/06 20:43:58
Just take a String not a RefPtr<StringImpl>
|
| +{ |
| + unsigned length = 0; |
| + // Account for leading spaces and punctuation. |
| + while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[length])) |
| + length++; |
| + |
| + // Account for first letter. |
| + length++; |
| + |
| + // Keep looking for whitespace and allowed punctuation, but avoid |
| + // accumulating just whitespace into the :first-letter. |
| + for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLength) { |
| + UChar c = (*oldText)[scanLength]; |
| + |
| + if (!shouldSkipForFirstLetter(c)) |
| + break; |
| + |
| + if (isPunctuationForFirstLetter(c)) |
| + length = scanLength + 1; |
| + } |
| + |
| + return length; |
| +} |
| + |
| void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild) |
| { |
| RenderObject* firstLetterContainer = currentChild->parent(); |
| @@ -6642,26 +6668,8 @@ void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend |
| if (oldText && oldText->length() > 0) { |
| unsigned length = 0; |
| + length = whiteSpaceLength(oldText); |
| - // Account for leading spaces and punctuation. |
| - while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[length])) |
| - length++; |
| - |
| - // Account for first letter. |
| - length++; |
| - |
| - // Keep looking for whitespace and allowed punctuation, but avoid |
| - // accumulating just whitespace into the :first-letter. |
| - for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLength) { |
| - UChar c = (*oldText)[scanLength]; |
| - |
| - if (!shouldSkipForFirstLetter(c)) |
| - break; |
| - |
| - if (isPunctuationForFirstLetter(c)) |
| - length = scanLength + 1; |
| - } |
| - |
| // Construct a text fragment for the text after the first letter. |
| // This text fragment might be empty. |
| RenderTextFragment* remainingText = |
| @@ -6701,6 +6709,8 @@ void RenderBlock::updateFirstLetter() |
| // Drill into inlines looking for our first text child. |
| RenderObject* currChild = firstLetterBlock->firstChild(); |
| + RenderObject* firstLetter = currChild; |
| + |
| while (currChild) { |
| if (currChild->isText()) |
| break; |
| @@ -6728,6 +6738,35 @@ void RenderBlock::updateFirstLetter() |
| // If the child already has style, then it has already been created, so we just want |
| // to update it. |
| if (currChild->parent()->style()->styleType() == FIRST_LETTER) { |
| + RenderText* remainingText = toRenderText(currChild->parent()->nextSibling()); |
| + // When the first line is changed by adding a new text at its start, |
| + // the first letter has to be updated. |
| + if (toRenderBoxModelObject(firstLetter)->firstLetterRemainingText() != remainingText) { |
| + RenderText* firstLetterText = toRenderText(currChild); |
| + RefPtr<StringImpl> updatedTextImp = remainingText->originalText(); |
|
esprehn
2013/05/06 20:43:58
Just use String. A String is just a RefPtr to a St
|
| + ASSERT(updatedTextImp); |
|
esprehn
2013/05/06 20:43:58
This assert should be inside whiteSpaceLength
|
| + unsigned length = 0; |
| + if (updatedTextImp && updatedTextImp->length() > 0) |
|
esprehn
2013/05/06 20:43:58
This check should be inside whiteSpaceLength() and
|
| + length = whiteSpaceLength(updatedTextImp); |
| + |
| + firstLetterText->setText(updatedTextImp->substring(0, length)); |
| + remainingText->setText(updatedTextImp->substring(length)); |
| + |
| + RenderObject* oldRemainingText = currChild->parent()->nextSibling()->nextSibling(); |
|
esprehn
2013/05/06 20:43:58
This doesn't look safe at all. How do you know you
|
| + // Replace the previous remaining text with the original text. |
| + // because it doesn't have the first letter. |
| + if (oldRemainingText->isText()) { |
| + RefPtr<StringImpl> oldString = toText(oldRemainingText->node())->dataImpl(); |
|
esprehn
2013/05/06 20:43:58
This is going to crash if it's an anonymous text r
|
| + |
| + // Before calling setText, we need to set m_firstLetter to 0 in order not to delete it. |
| + if (toRenderText(oldRemainingText)->isTextFragment()) |
| + toRenderTextFragment(oldRemainingText)->setFirstLetter(0); |
| + |
| + toRenderText(oldRemainingText)->setText(oldString); |
| + } |
| + toRenderBoxModelObject(firstLetter)->setFirstLetterRemainingText(remainingText); |
| + } |
| + |
| updateFirstLetterStyle(firstLetterBlock, currChild); |
| return; |
| } |