https://bugs.webkit.org/show_bug.cgi?id=68939
Reviewed by Darin Adler.
Simplified ReplaceSelectionCommand::positionAtStartOfInsertedContent.
This change revealed a bug in removeUnrenderedTextNodesAtEnds that text nodes without any visible
text at ends are not removed when it has a render object. Fixed the bug by checking the length of
the rendered text. (Tested by editing/pasteboard/pasting-word-in-div-extra-line.html)
This further revealed that caretMaxRenderedOffset doesn't return an offset and caretMaxRenderedOffset
on InlineBox, InlineTextBox, RenderObject, RenderBR, RenderPlaced are never called. To address this
issue, renamed caretMaxRenderedOffset to renderedTextLength for RenderText and removed the rest.
* dom/Position.cpp:
(WebCore::Position::rendersInDifferentPosition):
* editing/ReplaceSelectionCommand.cpp:
(WebCore::nodeHasVisibleRenderText): Added.
(WebCore::ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds): Calls nodeHasVisibleRenderText.
(WebCore::ReplaceSelectionCommand::positionAtStartOfInsertedContent): Simplified.
* editing/visible_units.cpp:
(WebCore::startOfParagraph): Calls renderedTextLength.
(WebCore::endOfParagraph): Ditto.
* rendering/InlineBox.cpp: Removed caretMaxRenderedOffset.
* rendering/InlineBox.h: Ditto.
* rendering/InlineTextBox.cpp: Ditto.
* rendering/InlineTextBox.h: Ditto.
* rendering/RenderBR.cpp: Ditto.
* rendering/RenderBR.h: Ditto.
* rendering/RenderObject.cpp: Ditto.
* rendering/RenderObject.h: Ditto.
* rendering/RenderReplaced.cpp: Ditto.
* rendering/RenderReplaced.h: Ditto.
* rendering/RenderText.cpp:
(WebCore::RenderText::renderedTextLength): Renamed from caretMaxRenderedOffset.
* rendering/RenderText.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96187
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-09-27 Ryosuke Niwa <rniwa@webkit.org>
+
+ Simplify ReplaceSelectionCommand::positionAtStartOfInsertedContent
+ https://bugs.webkit.org/show_bug.cgi?id=68939
+
+ Reviewed by Darin Adler.
+
+ Simplified ReplaceSelectionCommand::positionAtStartOfInsertedContent.
+
+ This change revealed a bug in removeUnrenderedTextNodesAtEnds that text nodes without any visible
+ text at ends are not removed when it has a render object. Fixed the bug by checking the length of
+ the rendered text. (Tested by editing/pasteboard/pasting-word-in-div-extra-line.html)
+
+ This further revealed that caretMaxRenderedOffset doesn't return an offset and caretMaxRenderedOffset
+ on InlineBox, InlineTextBox, RenderObject, RenderBR, RenderPlaced are never called. To address this
+ issue, renamed caretMaxRenderedOffset to renderedTextLength for RenderText and removed the rest.
+
+ * dom/Position.cpp:
+ (WebCore::Position::rendersInDifferentPosition):
+ * editing/ReplaceSelectionCommand.cpp:
+ (WebCore::nodeHasVisibleRenderText): Added.
+ (WebCore::ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds): Calls nodeHasVisibleRenderText.
+ (WebCore::ReplaceSelectionCommand::positionAtStartOfInsertedContent): Simplified.
+ * editing/visible_units.cpp:
+ (WebCore::startOfParagraph): Calls renderedTextLength.
+ (WebCore::endOfParagraph): Ditto.
+ * rendering/InlineBox.cpp: Removed caretMaxRenderedOffset.
+ * rendering/InlineBox.h: Ditto.
+ * rendering/InlineTextBox.cpp: Ditto.
+ * rendering/InlineTextBox.h: Ditto.
+ * rendering/RenderBR.cpp: Ditto.
+ * rendering/RenderBR.h: Ditto.
+ * rendering/RenderObject.cpp: Ditto.
+ * rendering/RenderObject.h: Ditto.
+ * rendering/RenderReplaced.cpp: Ditto.
+ * rendering/RenderReplaced.h: Ditto.
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::renderedTextLength): Renamed from caretMaxRenderedOffset.
+ * rendering/RenderText.h:
+
2011-09-27 James Robinson <jamesr@chromium.org>
[chromium] LayerRenderChromium asserts about leaking textures.
return false;
}
-static unsigned caretMaxRenderedOffset(const Node* n)
-{
- RenderObject* r = n->renderer();
- if (r)
- return r->caretMaxRenderedOffset();
-
- if (n->isCharacterDataNode())
- return static_cast<const CharacterData*>(n)->length();
- return 1;
-}
-
bool Position::isRenderedCharacter() const
{
if (isNull() || !deprecatedNode()->isTextNode())
LOG(Editing, "thisRenderedOffset: %d\n", thisRenderedOffset);
LOG(Editing, "posRenderer: %p [%p]\n", posRenderer, b2);
LOG(Editing, "posRenderedOffset: %d\n", posRenderedOffset);
- LOG(Editing, "node min/max: %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxRenderedOffset(deprecatedNode()));
- LOG(Editing, "pos node min/max: %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxRenderedOffset(pos.deprecatedNode()));
+ LOG(Editing, "node min/max: %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxOffset(deprecatedNode()));
+ LOG(Editing, "pos node min/max: %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxOffset(pos.deprecatedNode()));
LOG(Editing, "----------------------------------------------------------------------\n");
if (!b1 || !b2) {
}
if (nextRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
- && thisRenderedOffset == (int)caretMaxRenderedOffset(deprecatedNode()) && !posRenderedOffset) {
+ && thisRenderedOffset == caretMaxOffset(deprecatedNode()) && !posRenderedOffset) {
return false;
}
if (previousRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
- && !thisRenderedOffset && posRenderedOffset == (int)caretMaxRenderedOffset(pos.deprecatedNode())) {
+ && !thisRenderedOffset && posRenderedOffset == caretMaxOffset(pos.deprecatedNode())) {
return false;
}
#include "HTMLNames.h"
#include "NodeList.h"
#include "RenderObject.h"
+#include "RenderText.h"
#include "SmartReplace.h"
#include "TextIterator.h"
#include "htmlediting.h"
}
}
+static inline bool nodeHasVisibleRenderText(Text* text)
+{
+ return text->renderer() && toRenderText(text->renderer())->renderedTextLength() > 0;
+}
+
void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds()
{
document()->updateLayoutIgnorePendingStylesheets();
- if (!m_lastLeafInserted->renderer()
- && m_lastLeafInserted->isTextNode()
+ if (m_lastLeafInserted->isTextNode() && !nodeHasVisibleRenderText(static_cast<Text*>(m_lastLeafInserted.get()))
&& !enclosingNodeWithTag(firstPositionInOrBeforeNode(m_lastLeafInserted.get()), selectTag)
&& !enclosingNodeWithTag(firstPositionInOrBeforeNode(m_lastLeafInserted.get()), scriptTag)) {
if (m_firstNodeInserted == m_lastLeafInserted) {
// We don't have to make sure that m_firstNodeInserted isn't inside a select or script element, because
// it is a top level node in the fragment and the user can't insert into those elements.
- if (!m_firstNodeInserted->renderer() &&
- m_firstNodeInserted->isTextNode()) {
+ if (m_firstNodeInserted->isTextNode() && !nodeHasVisibleRenderText(static_cast<Text*>(m_firstNodeInserted.get()))) {
if (m_firstNodeInserted == m_lastLeafInserted) {
removeNode(m_firstNodeInserted.get());
m_firstNodeInserted = 0;
VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent()
{
- // Return the inserted content's first VisiblePosition.
- return VisiblePosition(nextCandidate(positionInParentBeforeNode(m_firstNodeInserted.get())));
+ return firstPositionInOrBeforeNode(m_firstNodeInserted.get());
}
static void removeHeadContents(ReplacementFragment& fragment)
if (r->isBR() || isBlock(n))
break;
- if (r->isText() && r->caretMaxRenderedOffset() > 0) {
+ if (r->isText() && toRenderText(r)->renderedTextLength()) {
ASSERT(n->isTextNode());
type = Position::PositionIsOffsetInAnchor;
if (style->preserveNewline()) {
break;
// FIXME: We avoid returning a position where the renderer can't accept the caret.
- if (r->isText() && r->caretMaxRenderedOffset() > 0) {
+ if (r->isText() && toRenderText(r)->renderedTextLength()) {
ASSERT(n->isTextNode());
int length = toRenderText(r)->textLength();
type = Position::PositionIsOffsetInAnchor;
return m_renderer->caretMaxOffset();
}
-unsigned InlineBox::caretMaxRenderedOffset() const
-{
- return 1;
-}
-
void InlineBox::dirtyLineBoxes()
{
markDirty();
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
- virtual unsigned caretMaxRenderedOffset() const;
unsigned char bidiLevel() const { return m_bidiEmbeddingLevel; }
void setBidiLevel(unsigned char level) { m_bidiEmbeddingLevel = level; }
return m_start + m_len;
}
-unsigned InlineTextBox::caretMaxRenderedOffset() const
-{
- return m_start + m_len;
-}
-
float InlineTextBox::textPos() const
{
// When computing the width of a text run, RenderBlock::computeInlineDirectionPositionsForLine() doesn't include the actual offset
virtual int caretMaxOffset() const;
private:
- virtual unsigned caretMaxRenderedOffset() const;
-
float textPos() const; // returns the x position relative to the left start of the text line.
public:
return 1;
}
-unsigned RenderBR::caretMaxRenderedOffset() const
-{
- return 1;
-}
-
VisiblePosition RenderBR::positionForPoint(const LayoutPoint&)
{
return createVisiblePosition(0, DOWNSTREAM);
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
- virtual unsigned caretMaxRenderedOffset() const;
virtual VisiblePosition positionForPoint(const LayoutPoint&);
return 0;
}
-unsigned RenderObject::caretMaxRenderedOffset() const
-{
- return 0;
-}
-
int RenderObject::previousOffset(int current) const
{
return current - 1;
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
- virtual unsigned caretMaxRenderedOffset() const;
virtual int previousOffset(int current) const;
virtual int previousOffsetForBackwardDeletion(int current) const;
setPreferredLogicalWidthsDirty(false);
}
-unsigned RenderReplaced::caretMaxRenderedOffset() const
-{
- return 1;
-}
-
VisiblePosition RenderReplaced::positionForPoint(const LayoutPoint& point)
{
// FIXME: This code is buggy if the replaced element is relative positioned.
virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
- virtual unsigned caretMaxRenderedOffset() const;
virtual VisiblePosition positionForPoint(const LayoutPoint&);
virtual bool canBeSelectionLeaf() const { return true; }
int RenderText::caretMaxOffset() const
{
InlineTextBox* box = lastTextBox();
- if (!box)
+ if (!lastTextBox())
return textLength();
+
int maxOffset = box->start() + box->len();
for (box = box->prevTextBox(); box; box = box->prevTextBox())
maxOffset = max<int>(maxOffset, box->start() + box->len());
return maxOffset;
}
-unsigned RenderText::caretMaxRenderedOffset() const
+unsigned RenderText::renderedTextLength() const
{
int l = 0;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
- virtual unsigned caretMaxRenderedOffset() const;
+ virtual unsigned renderedTextLength() const;
virtual int previousOffset(int current) const;
virtual int previousOffsetForBackwardDeletion(int current) const;