Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1263)

Unified Diff: Source/core/rendering/RenderBlock.cpp

Issue 14113040: Update the first letter when the first line is changed by adding a new text at its start. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@first-letter-rendering-issue
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698