Changeset 128729 in webkit
- Timestamp:
- Sep 17, 2012 1:56:04 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r128728 r128729 1 2012-09-17 Philip Rogers <pdr@google.com> 2 3 Make SVGPathSegList.append O(1) instead of O(n) 4 https://bugs.webkit.org/show_bug.cgi?id=94048 5 6 Reviewed by Nikolas Zimmermann. 7 8 Add performance test to prove this patch works. The rest of SVGPathSegList.append should be covered 9 in existing tests. 10 11 * perf/svg-path-appenditem-expected.txt: Added. 12 * perf/svg-path-appenditem.html: Added. 13 1 14 2012-09-17 Christophe Dumez <christophe.dumez@intel.com> 2 15 -
trunk/Source/WebCore/ChangeLog
r128716 r128729 1 2012-09-17 Philip Rogers <pdr@google.com> 2 3 Make SVGPathSegList.appendItem O(1) instead of O(n) 4 https://bugs.webkit.org/show_bug.cgi?id=94048 5 6 Reviewed by Nikolas Zimmermann. 7 8 Paths in SVG can be specified with a String (with the d attribute) or 9 with an SVGPathSegList. In SVGPathElement a single representation is 10 maintained: an SVGPathByteStream. To keep the byte stream synchronized with 11 the d attribute and the PathSegList, this byte stream is 12 rebuilt on every operation. As a result, any modification to the 13 path is an O(n) operation. 14 15 This patch takes advantage of the stream aspect of SVGPathByteStream 16 to make SVGPathSegList.append an O(1) operation instead of O(n). 17 When an SVGPathSeg is appended to an SVGPathSegList, this patch parses 18 the SVGPathSeg and directly appends the resulting bytes to the 19 byte stream. 20 21 To achieve this some plumbing has been added to pass more information 22 about the actual path changes from the SVGPathSegListTearOff to the 23 SVGPathElement: instead of the generic commitChange() this patch adds 24 commitChange(ListModification type). If we decide to change our 25 internal path data structure in the future, this additional commitChange 26 function can be used to pass the information needed to make 27 SVGPathSegList synchronization faster. 28 29 SVG Path Benchmark (http://bl.ocks.org/1296930) showing just the 30 appendItem() time used in building a 5000 segment path (avg of 3 runs): 31 WebKit without patch: 562 ms 32 Firefox 18.01a: 55 ms 33 Opera 12.50 internal: 27 ms 34 WebKit with patch: 7 ms 35 36 Test: perf/svg-path-appenditem.html 37 38 This test proves the claim: SVGPathSegList.appendItem is now O(1). 39 Additional tests that appendItem works are covered with existing tests. 40 41 * svg/SVGPathByteStream.h: 42 (WebCore::SVGPathByteStream::append): 43 44 This additional append method allows an SVGPathByteStream to be 45 appended to another. 46 47 * svg/SVGPathElement.cpp: 48 (WebCore::SVGPathElement::pathSegListChanged): 49 50 By passing the extra ListModification type to pathSegListChanged, 51 SVGPathElement is now able to only synchronize the parts of the byte stream 52 that actually changed. In this patch only append is treated 53 differently but one can imagine other performance improvements this 54 additional information allows. 55 56 * svg/SVGPathElement.h: 57 (SVGPathElement): 58 * svg/SVGPathParser.cpp: 59 (WebCore::SVGPathParser::parsePathDataFromSource): 60 61 During normal SVGPathSegList parsing we enforce that the path start with a moveto 62 command. This function has been expanded to make that optional so that parsing 63 can be performed elsewhere in the path (e.g., in the middle). 64 65 * svg/SVGPathParser.h: 66 (SVGPathParser): 67 * svg/SVGPathSegList.cpp: 68 (WebCore::SVGPathSegList::commitChange): 69 * svg/SVGPathSegList.h: 70 (SVGPathSegList): 71 * svg/SVGPathSegWithContext.h: 72 (WebCore::SVGPathSegWithContext::commitChange): 73 * svg/SVGPathUtilities.cpp: 74 (WebCore::appendSVGPathByteStreamFromSVGPathSeg): 75 76 This function reuses the SVGPathSegList parsing infrastructure 77 to parse an SVGPathSegList with just the single SVGPathSeg that 78 is being appended. The resulting byte stream can then be appended 79 to the result path byte stream. 80 81 (WebCore): 82 * svg/SVGPathUtilities.h: 83 (WebCore): 84 * svg/properties/SVGListProperty.h: 85 (WebCore::SVGListProperty::appendItemValues): 86 (WebCore::SVGListProperty::appendItemValuesAndWrappers): 87 (WebCore::SVGListProperty::commitChange): 88 (SVGListProperty): 89 * svg/properties/SVGPathSegListPropertyTearOff.h: 90 (WebCore::SVGPathSegListPropertyTearOff::commitChange): 91 (SVGPathSegListPropertyTearOff): 92 1 93 2012-09-16 James Robinson <jamesr@chromium.org> 2 94 -
trunk/Source/WebCore/svg/SVGPathByteStream.h
r115555 r128729 63 63 DataIterator end() { return m_data.end(); } 64 64 void append(unsigned char byte) { m_data.append(byte); } 65 void append(SVGPathByteStream* other) 66 { 67 for (DataIterator it = other->begin(); it != other->end(); ++it) 68 append(*it); 69 } 65 70 void clear() { m_data.clear(); } 66 71 bool isEmpty() const { return !m_data.size(); } -
trunk/Source/WebCore/svg/SVGPathElement.cpp
r126693 r128729 334 334 } 335 335 336 void SVGPathElement::pathSegListChanged(SVGPathSegRole role )336 void SVGPathElement::pathSegListChanged(SVGPathSegRole role, ListModification listModification) 337 337 { 338 338 switch (role) { … … 341 341 break; 342 342 case PathSegUnalteredRole: 343 buildSVGPathByteStreamFromSVGPathSegList(m_pathSegList.value, m_pathByteStream.get(), UnalteredParsing); 343 if (listModification == ListModificationAppend) { 344 ASSERT(!m_pathSegList.value.isEmpty()); 345 appendSVGPathByteStreamFromSVGPathSeg(m_pathSegList.value.last(), m_pathByteStream.get(), UnalteredParsing); 346 } else 347 buildSVGPathByteStreamFromSVGPathSegList(m_pathSegList.value, m_pathByteStream.get(), UnalteredParsing); 344 348 break; 345 349 case PathSegUndefinedRole: -
trunk/Source/WebCore/svg/SVGPathElement.h
r126693 r128729 94 94 SVGPathByteStream* pathByteStream() const; 95 95 96 void pathSegListChanged(SVGPathSegRole );96 void pathSegListChanged(SVGPathSegRole, ListModification = ListModificationUnknown); 97 97 98 98 virtual FloatRect getBBox(StyleUpdateStrategy = AllowStyleUpdate); -
trunk/Source/WebCore/svg/SVGPathParser.cpp
r101895 r128729 283 283 } 284 284 285 bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode )285 bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, bool checkForInitialMoveTo) 286 286 { 287 287 ASSERT(m_source); … … 304 304 305 305 // Path must start with moveto. 306 if (c ommand != PathSegMoveToAbs && command != PathSegMoveToRel)306 if (checkForInitialMoveTo && command != PathSegMoveToAbs && command != PathSegMoveToRel) 307 307 return false; 308 308 -
trunk/Source/WebCore/svg/SVGPathParser.h
r127757 r128729 39 39 SVGPathParser(); 40 40 41 bool parsePathDataFromSource(PathParsingMode pathParsingMode);41 bool parsePathDataFromSource(PathParsingMode, bool checkForInitialMoveTo = true); 42 42 void setCurrentConsumer(SVGPathConsumer* consumer) { m_consumer = consumer; } 43 43 void setCurrentSource(SVGPathSource* source) { m_source = source; } -
trunk/Source/WebCore/svg/SVGPathSegList.cpp
r115560 r128729 39 39 } 40 40 41 void SVGPathSegList::commitChange(SVGElement* contextElement )41 void SVGPathSegList::commitChange(SVGElement* contextElement, ListModification listModification) 42 42 { 43 43 ASSERT(contextElement); 44 44 ASSERT(contextElement->hasTagName(SVGNames::pathTag)); 45 static_cast<SVGPathElement*>(contextElement)->pathSegListChanged(m_role );45 static_cast<SVGPathElement*>(contextElement)->pathSegListChanged(m_role, listModification); 46 46 } 47 47 -
trunk/Source/WebCore/svg/SVGPathSegList.h
r74493 r128729 22 22 23 23 #if ENABLE(SVG) 24 #include "SVGListProperty.h" 24 25 #include "SVGPathSeg.h" 25 26 #include "SVGPropertyTraits.h" … … 42 43 43 44 // Only used by SVGPathSegListPropertyTearOff. 44 void commitChange(SVGElement* contextElement );45 void commitChange(SVGElement* contextElement, ListModification); 45 46 46 47 private: -
trunk/Source/WebCore/svg/SVGPathUtilities.cpp
r115560 r128729 141 141 } 142 142 143 bool appendSVGPathByteStreamFromSVGPathSeg(PassRefPtr<SVGPathSeg> pathSeg, SVGPathByteStream* result, PathParsingMode parsingMode) 144 { 145 ASSERT(result); 146 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists! 147 ASSERT(parsingMode == UnalteredParsing); 148 149 SVGPathSegList appendedItemList(PathSegUnalteredRole); 150 appendedItemList.append(pathSeg); 151 OwnPtr<SVGPathByteStream> appendedByteStream = SVGPathByteStream::create(); 152 153 SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(appendedByteStream.get()); 154 OwnPtr<SVGPathSegListSource> source = SVGPathSegListSource::create(appendedItemList); 155 SVGPathParser* parser = globalSVGPathParser(source.get(), builder); 156 bool ok = parser->parsePathDataFromSource(parsingMode, false); 157 parser->cleanup(); 158 159 if (ok) 160 result->append(appendedByteStream.get()); 161 162 return ok; 163 } 164 143 165 bool buildPathFromByteStream(SVGPathByteStream* stream, Path& result) 144 166 { -
trunk/Source/WebCore/svg/SVGPathUtilities.h
r115560 r128729 24 24 #include "SVGPathByteStream.h" 25 25 #include "SVGPathConsumer.h" 26 #include "SVGPathSeg.h" 26 27 #include <wtf/OwnPtr.h> 27 28 #include <wtf/text/WTFString.h> … … 40 41 // SVGPathSegList/String -> SVGPathByteStream 41 42 bool buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList&, SVGPathByteStream*, PathParsingMode); 43 bool appendSVGPathByteStreamFromSVGPathSeg(PassRefPtr<SVGPathSeg>, SVGPathByteStream*, PathParsingMode); 42 44 bool buildSVGPathByteStreamFromString(const String&, SVGPathByteStream*, PathParsingMode); 43 45 -
trunk/Source/WebCore/svg/properties/SVGListProperty.h
r124733 r128729 29 29 namespace WebCore { 30 30 31 enum ListModification { 32 ListModificationUnknown = 0, 33 ListModificationInsert = 1, 34 ListModificationReplace = 2, 35 ListModificationRemove = 3, 36 ListModificationAppend = 4 37 }; 38 31 39 template<typename PropertyType> 32 40 class SVGAnimatedListPropertyTearOff; … … 391 399 m_values->append(newItem); 392 400 393 commitChange( );401 commitChange(ListModificationAppend); 394 402 return newItem; 395 403 } … … 417 425 m_wrappers->append(newItem); 418 426 419 commitChange( );427 commitChange(ListModificationAppend); 420 428 return newItem.release(); 421 429 } … … 449 457 450 458 virtual void commitChange() = 0; 459 virtual void commitChange(ListModification) 460 { 461 commitChange(); 462 } 463 451 464 virtual void processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify) = 0; 452 465 virtual void processIncomingListItemWrapper(RefPtr<ListItemTearOff>& newItem, unsigned* indexToModify) = 0; -
trunk/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h
r118735 r128729 141 141 { 142 142 ASSERT(m_values); 143 m_values->commitChange(m_animatedProperty->contextElement()); 143 m_values->commitChange(m_animatedProperty->contextElement(), ListModificationUnknown); 144 } 145 146 virtual void commitChange(ListModification listModification) 147 { 148 ASSERT(m_values); 149 m_values->commitChange(m_animatedProperty->contextElement(), listModification); 144 150 } 145 151
Note: See TracChangeset
for help on using the changeset viewer.