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

Unified Diff: Source/core/editing/TextIterator.cpp

Issue 672953002: Convert first letter into a pseudo element. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 1 month 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 | « Source/core/dom/RenderTreeBuilder.cpp ('k') | Source/core/inspector/InspectorCSSAgent.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/editing/TextIterator.cpp
diff --git a/Source/core/editing/TextIterator.cpp b/Source/core/editing/TextIterator.cpp
index 7220a76da1c57feddbd673e2f47d8b210b3bb4b6..1d48170e7aa3272f8888b8d105b82f80d9d9a487 100644
--- a/Source/core/editing/TextIterator.cpp
+++ b/Source/core/editing/TextIterator.cpp
@@ -30,6 +30,7 @@
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/HTMLNames.h"
#include "core/dom/Document.h"
+#include "core/dom/FirstLetterPseudoElement.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/VisiblePosition.h"
@@ -678,80 +679,83 @@ bool TextIterator::handleTextNode()
void TextIterator::handleTextBox()
{
RenderText* renderer = m_firstLetterText ? m_firstLetterText.get() : toRenderText(m_node->renderer());
+
if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) {
m_textBox = 0;
- return;
- }
- String str = renderer->text();
- unsigned start = m_offset;
- unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : INT_MAX;
- while (m_textBox) {
- unsigned textBoxStart = m_textBox->start();
- unsigned runStart = std::max(textBoxStart, start);
-
- // Check for collapsed space at the start of this run.
- InlineTextBox* firstTextBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox();
- bool needSpace = m_lastTextNodeEndedWithCollapsedSpace
- || (m_textBox == firstTextBox && textBoxStart == runStart && runStart > 0);
- if (needSpace && !renderer->style()->isCollapsibleWhiteSpace(m_lastCharacter) && m_lastCharacter) {
- if (m_lastTextNode == m_node && runStart > 0 && str[runStart - 1] == ' ') {
- unsigned spaceRunStart = runStart - 1;
- while (spaceRunStart > 0 && str[spaceRunStart - 1] == ' ')
- --spaceRunStart;
- emitText(m_node, renderer, spaceRunStart, spaceRunStart + 1);
- } else {
- emitCharacter(space, m_node, 0, runStart, runStart);
+ } else {
+ String str = renderer->text();
+ unsigned start = m_offset;
+ unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : INT_MAX;
+ while (m_textBox) {
+ unsigned textBoxStart = m_textBox->start();
+ unsigned runStart = std::max(textBoxStart, start);
+
+ // Check for collapsed space at the start of this run.
+ InlineTextBox* firstTextBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox();
+ bool needSpace = m_lastTextNodeEndedWithCollapsedSpace
+ || (m_textBox == firstTextBox && textBoxStart == runStart && runStart > 0);
+ if (needSpace && !renderer->style()->isCollapsibleWhiteSpace(m_lastCharacter) && m_lastCharacter) {
+ if (m_lastTextNode == m_node && runStart > 0 && str[runStart - 1] == ' ') {
+ unsigned spaceRunStart = runStart - 1;
+ while (spaceRunStart > 0 && str[spaceRunStart - 1] == ' ')
+ --spaceRunStart;
+ emitText(m_node, renderer, spaceRunStart, spaceRunStart + 1);
+ } else {
+ emitCharacter(space, m_node, 0, runStart, runStart);
+ }
+ return;
}
- return;
- }
- unsigned textBoxEnd = textBoxStart + m_textBox->len();
- unsigned runEnd = std::min(textBoxEnd, end);
-
- // Determine what the next text box will be, but don't advance yet
- InlineTextBox* nextTextBox = nullptr;
- if (renderer->containsReversedText()) {
- if (m_sortedTextBoxesPosition + 1 < m_sortedTextBoxes.size())
- nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition + 1];
- } else {
- nextTextBox = m_textBox->nextTextBox();
- }
- ASSERT(!nextTextBox || nextTextBox->renderer() == renderer);
-
- if (runStart < runEnd) {
- // Handle either a single newline character (which becomes a space),
- // or a run of characters that does not include a newline.
- // This effectively translates newlines to spaces without copying the text.
- if (str[runStart] == '\n') {
- emitCharacter(space, m_node, 0, runStart, runStart + 1);
- m_offset = runStart + 1;
+ unsigned textBoxEnd = textBoxStart + m_textBox->len();
+ unsigned runEnd = std::min(textBoxEnd, end);
+
+ // Determine what the next text box will be, but don't advance yet
+ InlineTextBox* nextTextBox = nullptr;
+ if (renderer->containsReversedText()) {
+ if (m_sortedTextBoxesPosition + 1 < m_sortedTextBoxes.size())
+ nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition + 1];
} else {
- size_t subrunEnd = str.find('\n', runStart);
- if (subrunEnd == kNotFound || subrunEnd > runEnd)
- subrunEnd = runEnd;
-
- m_offset = subrunEnd;
- emitText(m_node, renderer, runStart, subrunEnd);
+ nextTextBox = m_textBox->nextTextBox();
}
+ ASSERT(!nextTextBox || nextTextBox->renderer() == renderer);
+
+ if (runStart < runEnd) {
+ // Handle either a single newline character (which becomes a space),
+ // or a run of characters that does not include a newline.
+ // This effectively translates newlines to spaces without copying the text.
+ if (str[runStart] == '\n') {
+ emitCharacter(space, m_node, 0, runStart, runStart + 1);
+ m_offset = runStart + 1;
+ } else {
+ size_t subrunEnd = str.find('\n', runStart);
+ if (subrunEnd == kNotFound || subrunEnd > runEnd)
+ subrunEnd = runEnd;
- // If we are doing a subrun that doesn't go to the end of the text box,
- // come back again to finish handling this text box; don't advance to the next one.
- if (static_cast<unsigned>(m_positionEndOffset) < textBoxEnd)
- return;
+ m_offset = subrunEnd;
+ emitText(m_node, renderer, runStart, subrunEnd);
+ }
- // Advance and return
- unsigned nextRunStart = nextTextBox ? nextTextBox->start() : str.length();
- if (nextRunStart > runEnd)
- m_lastTextNodeEndedWithCollapsedSpace = true; // collapsed space between runs or at the end
+ // If we are doing a subrun that doesn't go to the end of the text box,
+ // come back again to finish handling this text box; don't advance to the next one.
+ if (static_cast<unsigned>(m_positionEndOffset) < textBoxEnd)
+ return;
+
+ // Advance and return
+ unsigned nextRunStart = nextTextBox ? nextTextBox->start() : str.length();
+ if (nextRunStart > runEnd)
+ m_lastTextNodeEndedWithCollapsedSpace = true; // collapsed space between runs or at the end
+
+ m_textBox = nextTextBox;
+ if (renderer->containsReversedText())
+ ++m_sortedTextBoxesPosition;
+ return;
+ }
+ // Advance and continue
m_textBox = nextTextBox;
if (renderer->containsReversedText())
++m_sortedTextBoxesPosition;
- return;
}
- // Advance and continue
- m_textBox = nextTextBox;
- if (renderer->containsReversedText())
- ++m_sortedTextBoxesPosition;
}
+
if (!m_textBox && m_remainingTextBox) {
m_textBox = m_remainingTextBox;
m_remainingTextBox = 0;
@@ -761,34 +765,28 @@ void TextIterator::handleTextBox()
}
}
-static inline RenderText* firstRenderTextInFirstLetter(RenderBoxModelObject* firstLetter)
-{
- if (!firstLetter)
- return 0;
-
- // FIXME: Should this check descendent objects?
- for (RenderObject* current = firstLetter->slowFirstChild(); current; current = current->nextSibling()) {
- if (current->isText())
- return toRenderText(current);
- }
- return 0;
-}
-
void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer)
{
- if (renderer->firstLetter()) {
- RenderBoxModelObject* r = renderer->firstLetter();
- if (r->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility)
- return;
- if (RenderText* firstLetter = firstRenderTextInFirstLetter(r)) {
- m_handledFirstLetter = true;
- m_remainingTextBox = m_textBox;
- m_textBox = firstLetter->firstTextBox();
- m_sortedTextBoxes.clear();
- m_firstLetterText = firstLetter;
- }
- }
m_handledFirstLetter = true;
+
+ if (!renderer->isRemainingTextRenderer())
+ return;
+
+ FirstLetterPseudoElement* firstLetterElement = renderer->firstLetterPseudoElement();
+ if (!firstLetterElement)
+ return;
+
+ RenderObject* pseudoRenderer = firstLetterElement->renderer();
+ if (pseudoRenderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility)
+ return;
+
+ RenderObject* firstLetter = pseudoRenderer->slowFirstChild();
+ ASSERT(firstLetter);
+
+ m_remainingTextBox = m_textBox;
+ m_textBox = toRenderText(firstLetter)->firstTextBox();
+ m_sortedTextBoxes.clear();
+ m_firstLetterText = toRenderText(firstLetter);
}
bool TextIterator::handleReplacedElement()
@@ -850,12 +848,16 @@ bool TextIterator::hasVisibleTextNode(RenderText* renderer)
{
if (renderer->style()->visibility() == VISIBLE)
return true;
- if (renderer->isTextFragment()) {
- RenderTextFragment* fragment = toRenderTextFragment(renderer);
- if (fragment->firstLetter() && fragment->firstLetter()->style()->visibility() == VISIBLE)
- return true;
- }
- return false;
+
+ if (!renderer->isTextFragment())
+ return false;
+
+ RenderTextFragment* fragment = toRenderTextFragment(renderer);
+ if (!fragment->isRemainingTextRenderer())
+ return false;
+
+ RenderObject* pseudoElementRenderer = fragment->firstLetterPseudoElement()->renderer();
+ return pseudoElementRenderer && pseudoElementRenderer->style()->visibility() == VISIBLE;
}
static bool shouldEmitTabBeforeNode(Node* node)
@@ -1528,7 +1530,14 @@ RenderText* SimplifiedBackwardsTextIterator::handleFirstLetter(int& startOffset,
m_shouldHandleFirstLetter = false;
offsetInNode = 0;
- RenderText* firstLetterRenderer = firstRenderTextInFirstLetter(fragment->firstLetter());
+
+ ASSERT(fragment->isRemainingTextRenderer());
+ ASSERT(fragment->firstLetterPseudoElement());
+
+ RenderObject* pseudoElementRenderer = fragment->firstLetterPseudoElement()->renderer();
+ ASSERT(pseudoElementRenderer);
+ ASSERT(pseudoElementRenderer->slowFirstChild());
+ RenderText* firstLetterRenderer = toRenderText(pseudoElementRenderer->slowFirstChild());
m_offset = firstLetterRenderer->caretMaxOffset();
m_offset += collapsedSpaceLength(firstLetterRenderer, m_offset);
« no previous file with comments | « Source/core/dom/RenderTreeBuilder.cpp ('k') | Source/core/inspector/InspectorCSSAgent.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698