Changeset 21611 in webkit
- Timestamp:
- May 20, 2007, 2:14:40 PM (18 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r21610 r21611 1 2007-05-20 Darin Adler <darin@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 - fix <rdar://problem/5193416> REGRESSION: Selection on large pages extremely slow 6 7 * dom/Document.cpp: (WebCore::Document::removeMarkers): Added an early exit for the common 8 case where there are no markers. Changed code to iterate over all the nodes in the range 9 instead of using TextIterator, which is more efficient. 10 11 * page/Frame.cpp: (WebCore::Frame::respondToChangedSelection): Added checks for editable, 12 so we don't bother doing work related to spell checking and grammar checking when changing 13 the selection in non-editable text. Also rearranged the code so we only compute the old 14 word boundaries and sentence boundaries when actually needed, and don't do the sentence 15 range checks unless grammar checking is enabled. 16 17 * platform/TextBreakIteratorICU.cpp: 18 (WebCore::setUpIterator): Don't take a locale parameter. Always pass in currentTextBreakLocaleID. 19 (WebCore::characterBreakIterator): Removed local parameter. 20 (WebCore::wordBreakIterator): Ditto. 21 (WebCore::lineBreakIterator): Ditto. 22 (WebCore::sentenceBreakIterator): Ditto. 23 24 * platform/mac/TextBreakIteratorInternalICUMac.mm: 25 (WebCore::getTextBreakLocale): Broke out the code to actually get the locale. 26 (WebCore::currentTextBreakLocaleID): This function now handles only the caching and calls 27 getTextBreakLocale to actually figure it out. 28 29 * editing/visible_units.cpp: Added lots of FIXME comments, but no code change. 30 1 31 2007-05-20 Adam Treat <adam@staikos.net> 2 32 … … 728 758 load completed, even if we think the current frame load is already complete. 729 759 730 2007-05-16 dethbakin <bdakin@apple.com>760 2007-05-16 Beth Dakin <bdakin@apple.com> 731 761 732 762 Reviewed by Hyatt. -
trunk/WebCore/dom/Document.cpp
r21467 r21611 2762 2762 } 2763 2763 2764 void Document::removeMarkers(Range *range, DocumentMarker::MarkerType markerType) 2765 { 2766 // Use a TextIterator to visit the potentially multiple nodes the range covers. 2767 for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) { 2768 RefPtr<Range> textPiece = markedText.range(); 2769 int exception = 0; 2770 unsigned startOffset = textPiece->startOffset(exception); 2771 unsigned length = textPiece->endOffset(exception) - startOffset + 1; 2772 removeMarkers(textPiece->startContainer(exception), startOffset, length, markerType); 2773 } 2774 } 2775 2776 // Markers are stored in order sorted by their location. They do not overlap each other, as currently 2777 // required by the drawing code in RenderText.cpp. 2764 void Document::removeMarkers(Range* range, DocumentMarker::MarkerType markerType) 2765 { 2766 if (m_markers.isEmpty()) 2767 return; 2768 2769 ExceptionCode ec = 0; 2770 Node* startContainer = range->startContainer(ec); 2771 int startOffset = range->startOffset(ec); 2772 Node* endContainer = range->endContainer(ec); 2773 int endOffset = range->endOffset(ec); 2774 2775 Node* pastEndNode = range->pastEndNode(); 2776 for (Node* node = range->startNode(); node != pastEndNode; node = node->traverseNextNode()) 2777 removeMarkers(node, 2778 node == startContainer ? startOffset : 0, 2779 node == endContainer ? endOffset : INT_MAX, 2780 markerType); 2781 } 2782 2783 // Markers are stored in order sorted by their location. 2784 // They do not overlap each other, as currently required by the drawing code in RenderText.cpp. 2778 2785 2779 2786 void Document::addMarker(Node *node, DocumentMarker newMarker) … … 2872 2879 } 2873 2880 2874 void Document::removeMarkers(Node *node, unsigned startOffset, int length, DocumentMarker::MarkerType markerType)2881 void Document::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerType markerType) 2875 2882 { 2876 2883 if (length <= 0) … … 3008 3015 } 3009 3016 3010 3011 3017 void Document::removeMarkers(Node* node) 3012 3018 { -
trunk/WebCore/editing/visible_units.cpp
r21374 r21611 522 522 { 523 523 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 524 // FIXME: The following function can return -1; we don't handle that. 524 525 return textBreakPreceding(iterator, length); 525 526 } … … 527 528 VisiblePosition startOfSentence(const VisiblePosition &c) 528 529 { 530 // FIXME: The sentence break iterator will not stop at paragraph boundaries. 531 // Thus this treats many large documents as one giant sentence. 529 532 return previousBoundary(c, startSentenceBoundary); 530 533 } … … 532 535 static unsigned endSentenceBoundary(const UChar* characters, unsigned length) 533 536 { 537 // FIXME: It's unclear why this starts searching from the end of the buffer. 538 // The word equivalent starts at the start of the buffer, and I think that's correct. 534 539 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 540 // FIXME: The following function can return -1; we don't handle that. 535 541 int start = textBreakPreceding(iterator, length); 536 542 return textBreakFollowing(iterator, start); … … 539 545 VisiblePosition endOfSentence(const VisiblePosition &c) 540 546 { 547 // FIXME: The sentence break iterator will not stop at paragraph boundaries. 548 // Thus this treats many large documents as one giant sentence. 541 549 return nextBoundary(c, endSentenceBoundary); 542 550 } … … 544 552 static unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length) 545 553 { 554 // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right. 546 555 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 556 // FIXME: The following function can return -1; we don't handle that. 547 557 return textBreakPreceding(iterator, length); 548 558 } … … 550 560 VisiblePosition previousSentencePosition(const VisiblePosition &c) 551 561 { 562 // FIXME: The sentence break iterator will not stop at paragraph boundaries. 563 // Thus this treats many large documents as one giant sentence. 552 564 return previousBoundary(c, previousSentencePositionBoundary); 553 565 } … … 555 567 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length) 556 568 { 569 // FIXME: This is too close to endSentenceBoundary. I'm pretty sure it's not right. 557 570 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 571 // FIXME: The following function can return -1; we don't handle that. 558 572 return textBreakFollowing(iterator, 0); 559 573 } … … 561 575 VisiblePosition nextSentencePosition(const VisiblePosition &c) 562 576 { 577 // FIXME: The sentence break iterator will not stop at paragraph boundaries. 578 // Thus this treats many large documents as one giant sentence. 563 579 return nextBoundary(c, nextSentencePositionBoundary); 564 580 } -
trunk/WebCore/page/Frame.cpp
r21476 r21611 1 /* This file is part of the KDE project 2 * 1 /* 3 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 4 3 * 1999 Lars Knoll <knoll@kde.org> … … 7 6 * 2000 Stefan Schimanski <1Stein@gmx.de> 8 7 * 2001 George Staikos <staikos@kde.org> 9 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.8 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 10 9 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> 11 10 * Copyright (C) 2007 Trolltech ASA … … 36 35 #include "CSSProperty.h" 37 36 #include "CSSPropertyNames.h" 38 #include "Cache.h"39 37 #include "CachedCSSStyleSheet.h" 40 #include "Chrome.h"41 38 #include "DOMWindow.h" 42 39 #include "DocLoader.h" … … 44 41 #include "EditingText.h" 45 42 #include "EditorClient.h" 46 #include "Event.h"47 43 #include "EventNames.h" 48 #include "FloatRect.h"49 44 #include "FocusController.h" 50 #include "Frame.h"51 #include "FrameLoadRequest.h"52 45 #include "FrameLoader.h" 53 46 #include "FrameView.h" 54 47 #include "GraphicsContext.h" 48 #include "HTMLDocument.h" 55 49 #include "HTMLFormElement.h" 56 50 #include "HTMLFrameElementBase.h" 57 51 #include "HTMLGenericFormElement.h" 58 #include "HTMLInputElement.h"59 52 #include "HTMLNames.h" 60 #include "HTMLObjectElement.h"61 53 #include "HTMLTableCellElement.h" 62 #include "HitTestRequest.h"63 #include "HitTestResult.h"64 #include "IconDatabase.h"65 #include "IconLoader.h"66 #include "ImageDocument.h"67 #include "IndentOutdentCommand.h"68 54 #include "Logging.h" 69 55 #include "MediaFeatureNames.h" 70 #include "MouseEventWithHitTestResults.h"71 56 #include "NodeList.h" 72 57 #include "Page.h" 73 #include "PlatformScrollBar.h"74 58 #include "RegularExpression.h" 75 #include "RenderListBox.h"76 #include "RenderObject.h"77 59 #include "RenderPart.h" 78 60 #include "RenderTableCell.h" … … 80 62 #include "RenderTheme.h" 81 63 #include "RenderView.h" 82 #include "SegmentedString.h"83 64 #include "TextIterator.h" 84 65 #include "TextResourceDecoder.h" 85 #include "TypingCommand.h" 86 #include "XMLTokenizer.h" 87 #include "cssstyleselector.h" 88 #include "htmlediting.h" 89 #include "kjs_proxy.h" 90 #include "kjs_window.h" 91 #include "markup.h" 92 #include "visible_units.h" 93 #include "xmlhttprequest.h" 94 #include <math.h> 95 #include <sys/types.h> 96 #include <wtf/Platform.h> 97 66 #include "XMLNames.h" 98 67 #include "bindings/NP_jsobject.h" 99 68 #include "bindings/npruntime_impl.h" 100 69 #include "bindings/runtime_root.h" 101 102 #if !PLATFORM(WIN_OS) 103 #include <unistd.h> 104 #endif 70 #include "kjs_proxy.h" 71 #include "kjs_window.h" 72 #include "visible_units.h" 105 73 106 74 #if ENABLE(SVG) 107 75 #include "SVGNames.h" 108 76 #include "XLinkNames.h" 109 #include "SVGDocument.h"110 #include "SVGDocumentExtensions.h"111 77 #endif 112 78 113 #include "XMLNames.h"114 115 79 using namespace std; 116 80 117 81 using KJS::JSLock; 118 using KJS::JSValue;119 using KJS::Location;120 using KJS::PausedTimeouts;121 using KJS::SavedProperties;122 using KJS::SavedBuiltins;123 using KJS::UString;124 82 using KJS::Window; 125 83 … … 1804 1762 } 1805 1763 1806 void Frame::respondToChangedSelection(const Selection &oldSelection, bool closeTyping)1764 void Frame::respondToChangedSelection(const Selection& oldSelection, bool closeTyping) 1807 1765 { 1808 1766 if (document()) { 1809 if (editor()->isContinuousSpellCheckingEnabled()) { 1810 Selection oldAdjacentWords; 1811 Selection oldSelectedSentence; 1812 1813 // If this is a change in selection resulting from a delete operation, oldSelection may no longer 1814 // be in the document. 1815 if (oldSelection.start().node() && oldSelection.start().node()->inDocument()) { 1767 bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled(); 1768 bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled(); 1769 if (isContinuousSpellCheckingEnabled) { 1770 Selection newAdjacentWords; 1771 Selection newSelectedSentence; 1772 if (selectionController()->selection().isContentEditable()) { 1773 VisiblePosition newStart(selectionController()->selection().visibleStart()); 1774 newAdjacentWords = Selection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); 1775 if (isContinuousGrammarCheckingEnabled) 1776 newSelectedSentence = Selection(startOfSentence(newStart), endOfSentence(newStart)); 1777 } 1778 1779 // When typing we check spelling elsewhere, so don't redo it here. 1780 // If this is a change in selection resulting from a delete operation, 1781 // oldSelection may no longer be in the document. 1782 if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) { 1816 1783 VisiblePosition oldStart(oldSelection.visibleStart()); 1817 oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); 1818 oldSelectedSentence = Selection(startOfSentence(oldStart), endOfSentence(oldStart)); 1784 Selection oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); 1785 if (oldAdjacentWords != newAdjacentWords) { 1786 editor()->markMisspellings(oldAdjacentWords); 1787 if (isContinuousGrammarCheckingEnabled) { 1788 Selection oldSelectedSentence = Selection(startOfSentence(oldStart), endOfSentence(oldStart)); 1789 if (oldSelectedSentence != newSelectedSentence) 1790 editor()->markBadGrammar(oldSelectedSentence); 1791 } 1792 } 1819 1793 } 1820 1821 VisiblePosition newStart(selectionController()->selection().visibleStart()); 1822 Selection newAdjacentWords(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); 1823 Selection newSelectedSentence(startOfSentence(newStart), endOfSentence(newStart)); 1824 1825 // When typing we check spelling elsewhere, so don't redo it here. 1826 if (closeTyping && oldAdjacentWords != newAdjacentWords) { 1827 editor()->markMisspellings(oldAdjacentWords); 1828 1829 if (oldSelectedSentence != newSelectedSentence) 1830 editor()->markBadGrammar(oldSelectedSentence); 1831 } 1832 1833 // This only erases a marker in the first unit (word or sentence) of the selection. 1794 1795 // This only erases markers that are in the first unit (word or sentence) of the selection. 1834 1796 // Perhaps peculiar, but it matches AppKit. 1835 document()->removeMarkers(newAdjacentWords.toRange().get(), DocumentMarker::Spelling); 1836 document()->removeMarkers(newSelectedSentence.toRange().get(), DocumentMarker::Grammar); 1837 } else { 1838 // When continuous spell checking is off, existing markers disappear after the selection changes. 1797 if (RefPtr<Range> wordRange = newAdjacentWords.toRange()) 1798 document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling); 1799 if (RefPtr<Range> sentenceRange = newSelectedSentence.toRange()) 1800 document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar); 1801 } 1802 1803 // When continuous spell checking is off, existing markers disappear after the selection changes. 1804 if (!isContinuousSpellCheckingEnabled) 1839 1805 document()->removeMarkers(DocumentMarker::Spelling); 1806 if (!isContinuousGrammarCheckingEnabled) 1840 1807 document()->removeMarkers(DocumentMarker::Grammar); 1841 } 1842 } 1843 1808 } 1809 1844 1810 editor()->respondToChangedSelection(oldSelection); 1845 1811 } -
trunk/WebCore/platform/TextBreakIteratorICU.cpp
r21270 r21611 30 30 31 31 static TextBreakIterator* setUpIterator(bool& createdIterator, TextBreakIterator*& iterator, 32 UBreakIteratorType type, const UChar* string, int length , const char* locale)32 UBreakIteratorType type, const UChar* string, int length) 33 33 { 34 34 if (!string) … … 36 36 37 37 if (!createdIterator) { 38 // The locale is currently ignored when determining character cluster breaks.39 // This may change in the future, according to Deborah Goldsmith.40 // FIXME: Presumably we do need to pass the correct locale for word and line41 // break iterators, though!42 38 UErrorCode openStatus = U_ZERO_ERROR; 43 iterator = static_cast<TextBreakIterator*>(ubrk_open(type, locale, 0, 0, &openStatus));39 iterator = static_cast<TextBreakIterator*>(ubrk_open(type, currentTextBreakLocaleID(), 0, 0, &openStatus)); 44 40 createdIterator = true; 45 41 } … … 60 56 static TextBreakIterator* staticCharacterBreakIterator; 61 57 return setUpIterator(createdCharacterBreakIterator, 62 staticCharacterBreakIterator, UBRK_CHARACTER, string, length , "en_us");58 staticCharacterBreakIterator, UBRK_CHARACTER, string, length); 63 59 } 64 60 … … 68 64 static TextBreakIterator* staticWordBreakIterator; 69 65 return setUpIterator(createdWordBreakIterator, 70 staticWordBreakIterator, UBRK_WORD, string, length , "en_us");66 staticWordBreakIterator, UBRK_WORD, string, length); 71 67 } 72 68 … … 76 72 static TextBreakIterator* staticLineBreakIterator; 77 73 return setUpIterator(createdLineBreakIterator, 78 staticLineBreakIterator, UBRK_LINE, string, length , "en_us");74 staticLineBreakIterator, UBRK_LINE, string, length); 79 75 } 80 76 … … 84 80 static TextBreakIterator* staticSentenceBreakIterator; 85 81 return setUpIterator(createdSentenceBreakIterator, 86 staticSentenceBreakIterator, UBRK_SENTENCE, string, length , currentTextBreakLocaleID());82 staticSentenceBreakIterator, UBRK_SENTENCE, string, length); 87 83 } 88 84 -
trunk/WebCore/platform/mac/TextBreakIteratorInternalICUMac.mm
r21446 r21611 24 24 namespace WebCore { 25 25 26 static const int maxLocaleStringLength = 32; 27 26 28 // This code was swiped from the CarbonCore UnicodeUtilities. One change from that is to use the empty 27 29 // string instead of the "old locale model" as the ultimate fallback. This change is per the UnicodeUtilities 28 30 // engineer. 29 // 30 // NOTE: this abviously could be fairly expensive to do. If it turns out to be a bottleneck, it might 31 // help to instead put a call in the iterator initializer to set the current text break locale. Unfortunately, 32 // we can not cache it across calls to our API since the result can change without our knowing (AFAIK 33 // there are no notifiers for AppleTextBreakLocale and/or AppleLanguages changes). 34 const char* currentTextBreakLocaleID() 31 static void getTextBreakLocale(char localeStringBuffer[maxLocaleStringLength]) 35 32 { 36 const int localeStringLength = 32; 37 static char localeStringBuffer[localeStringLength] = { 0 }; 38 char* localeString = &localeStringBuffer[0]; 39 40 // Empty string means "root locale", which what we use if we can't use a pref. 41 33 // Empty string means "root locale", which is what we use if we can't use a pref. 34 42 35 // We get the parts string from AppleTextBreakLocale pref. 43 36 // If that fails then look for the first language in the AppleLanguages pref. … … 55 48 } 56 49 } 57 58 50 if (prefLocaleStr) { 59 // Canonicalize pref string in case it is not in the canonical format. This call is only available on Tiger and newer.51 // Canonicalize pref string in case it is not in the canonical format. 60 52 CFStringRef canonLocaleCFStr = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorDefault, prefLocaleStr); 61 53 if (canonLocaleCFStr) { 62 CFStringGetCString(canonLocaleCFStr, localeString , localeStringLength, kCFStringEncodingASCII);54 CFStringGetCString(canonLocaleCFStr, localeStringBuffer, maxLocaleStringLength, kCFStringEncodingASCII); 63 55 CFRelease(canonLocaleCFStr); 64 56 } 65 57 CFRelease(prefLocaleStr); 66 58 } 67 68 return localeString; 59 } 60 61 const char* currentTextBreakLocaleID() 62 { 63 static char localeStringBuffer[maxLocaleStringLength]; 64 static bool gotTextBreakLocale = false; 65 if (!gotTextBreakLocale) { 66 getTextBreakLocale(localeStringBuffer); 67 gotTextBreakLocale = true; 68 } 69 return localeStringBuffer; 69 70 } 70 71
Note:
See TracChangeset
for help on using the changeset viewer.