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; |
} |