Commit b6dd43c0 authored by enrica@apple.com's avatar enrica@apple.com

Huge plain text pastes are slow

<rdar://problem/5195056>
https://bugs.webkit.org/show_bug.cgi?id=34237

Reviewed by Maciej Stachowiak.

WebCore: 

No new tests. It is a performance improvement.

The performance of the plain text paste is now linear.
We treat as a special case, a fragment that has been
created from plain text. Finding VisiblePositions and
applying style is greatly simplified, given the nature of
the fragment.

* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::doApply):
* editing/markup.cpp:
(WebCore::isPlainTextMarkup):
* editing/markup.h:

WebKit/mac: 

Mail is ignoring the fragment created from plain text or HTML that is
passed to the delegate function, that creates a new one.
This fix avoids creating the fragment twice.

* WebView/WebHTMLView.mm:
(-[WebHTMLView _pasteWithPasteboard:allowPlainText:]):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54036 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6994c6a2
2010-01-28 Enrica Casucci <enrica@apple.com>
Reviewed by Maciej Stachowiak.
Huge plain text pastes are slow
<rdar://problem/5195056>
https://bugs.webkit.org/show_bug.cgi?id=34237
No new tests. It is a performance improvement.
The performance of the plain text paste is now linear.
We treat as a special case, a fragment that has been
created from plain text. Finding VisiblePositions and
applying style is greatly simplified, given the nature of
the fragment.
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::doApply):
* editing/markup.cpp:
(WebCore::isPlainTextMarkup):
* editing/markup.h:
2010-01-28 Jeremy Orlow <jorlow@chromium.org>
Reviewed by Adam Barth.
......@@ -877,6 +877,8 @@ void ReplaceSelectionCommand::doApply()
if (!refNode->inDocument())
return;
bool plainTextFragment = isPlainTextMarkup(refNode.get());
while (node) {
Node* next = node->nextSibling();
fragment.removeNode(node);
......@@ -887,6 +889,8 @@ void ReplaceSelectionCommand::doApply()
return;
refNode = node;
if (node && plainTextFragment)
plainTextFragment = isPlainTextMarkup(node.get());
node = next;
}
......@@ -913,7 +917,7 @@ void ReplaceSelectionCommand::doApply()
bool interchangeNewlineAtEnd = fragment.hasInterchangeNewlineAtEnd();
if (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR))
if (endBR && (plainTextFragment || shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR)))
removeNodeAndPruneAncestors(endBR);
// Determine whether or not we should merge the end of inserted content with what's after it before we do
......@@ -1020,6 +1024,11 @@ void ReplaceSelectionCommand::doApply()
}
}
// If we are dealing with a fragment created from plain text
// no style matching is necessary.
if (plainTextFragment)
m_matchStyle = false;
completeHTMLReplacement(lastPositionToSelect);
}
......
......@@ -1133,6 +1133,17 @@ static void fillContainerFromString(ContainerNode* paragraph, const String& stri
}
}
bool isPlainTextMarkup(Node *node)
{
if (!node->isElementNode() || !node->hasTagName(divTag) || static_cast<Element*>(node)->attributes()->length())
return false;
if (node->childNodeCount() == 1 && (node->firstChild()->isTextNode() || (node->firstChild()->firstChild())))
return true;
return (node->childNodeCount() == 2 && isTabSpanTextNode(node->firstChild()->firstChild()) && node->firstChild()->nextSibling()->isTextNode());
}
PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String& text)
{
if (!context)
......
......@@ -45,6 +45,8 @@ namespace WebCore {
PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document*, const String& markup, const String& baseURL, FragmentScriptingPermission = FragmentScriptingAllowed);
PassRefPtr<DocumentFragment> createFragmentFromNodes(Document*, const Vector<Node*>&);
bool isPlainTextMarkup(Node *node);
String createMarkup(const Range*,
Vector<Node*>* = 0, EAnnotateForInterchange = DoNotAnnotateForInterchange, bool convertBlocksToInlines = false);
String createMarkup(const Node*, EChildrenOnly = IncludeNode, Vector<Node*>* = 0);
......
2010-01-28 Enrica Casucci <enrica@apple.com>
Reviewed by Maciej Stachowiak.
Huge plain text pastes are slow
<rdar://problem/5195056>
https://bugs.webkit.org/show_bug.cgi?id=34237
Mail is ignoring the fragment created from plain text or HTML that is
passed to the delegate function, that creates a new one.
This fix avoids creating the fragment twice.
* WebView/WebHTMLView.mm:
(-[WebHTMLView _pasteWithPasteboard:allowPlainText:]):
2010-01-25 Anders Carlsson <andersca@apple.com>
Featureless build fixes.
......
......@@ -103,6 +103,7 @@
#import <WebCore/Page.h>
#import <WebCore/PlatformKeyboardEvent.h>
#import <WebCore/Range.h>
#import <WebCore/RuntimeApplicationChecks.h>
#import <WebCore/SelectionController.h>
#import <WebCore/SharedBuffer.h>
#import <WebCore/SimpleFontData.h>
......@@ -796,10 +797,26 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
[webView _setInsertionPasteboard:pasteboard];
DOMRange *range = [self _selectedRange];
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard inContext:range allowPlainText:allowPlainText];
if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionPasted])
[[self _frame] _replaceSelectionWithFragment:fragment selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard] matchStyle:NO];
#else
// Mail is ignoring the frament passed to the delegate and creates a new one.
// We want to avoid creating the fragment twice.
if (applicationIsAppleMail()) {
if ([self _shouldInsertFragment:nil replacingDOMRange:range givenAction:WebViewInsertActionPasted]) {
DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard inContext:range allowPlainText:allowPlainText];
if (fragment)
[[self _frame] _replaceSelectionWithFragment:fragment selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard] matchStyle:NO];
}
} else {
DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard inContext:range allowPlainText:allowPlainText];
if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionPasted])
[[self _frame] _replaceSelectionWithFragment:fragment selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard] matchStyle:NO];
}
#endif
[webView _setInsertionPasteboard:nil];
[webView release];
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment