Changeset 195970 in webkit
- Timestamp:
- Feb 1, 2016, 11:45:18 AM (10 years ago)
- Location:
- trunk/Source
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r195968 r195970 1 2016-02-01 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 Cache the Path instead of creating it every time it is required 4 https://bugs.webkit.org/show_bug.cgi?id=152939 5 6 Reviewed by Darin Adler. 7 8 If the key type of an LRU cache can't to be strongly tided to a specific 9 data type; e.g. FloatRect -> Path, we need to be able to pass the policy 10 type to the TinyLRUCache template instead of just specializing it. This 11 will make the code more readable and will allow different caches for the 12 same key type. 13 14 * wtf/TinyLRUCache.h: 15 (WebCore::TinyLRUCache::get): 16 1 17 2016-02-01 Alex Christensen <achristensen@webkit.org> 2 18 -
trunk/Source/WTF/wtf/TinyLRUCache.h
r195356 r195970 39 39 }; 40 40 41 template<typename KeyType, typename ValueType, size_t capacity = 4 >41 template<typename KeyType, typename ValueType, size_t capacity = 4, typename Policy = TinyLRUCachePolicy<KeyType, ValueType>> 42 42 class TinyLRUCache { 43 43 public: 44 44 const ValueType& get(const KeyType& key) 45 45 { 46 if ( TinyLRUCachePolicy<KeyType, ValueType>::isKeyNull(key)) {47 static NeverDestroyed<ValueType> valueForNull = TinyLRUCachePolicy<KeyType, ValueType>::createValueForNullKey();46 if (Policy::isKeyNull(key)) { 47 static NeverDestroyed<ValueType> valueForNull = Policy::createValueForNullKey(); 48 48 return valueForNull; 49 49 } … … 67 67 m_cache.remove(0); 68 68 69 m_cache.append(std::make_pair(key, TinyLRUCachePolicy<KeyType, ValueType>::createValueForKey(key)));69 m_cache.append(std::make_pair(key, Policy::createValueForKey(key))); 70 70 return m_cache.last().second; 71 71 } -
trunk/Source/WebCore/ChangeLog
r195969 r195970 1 2016-02-01 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 Cache the Path instead of creating it every time it is required 4 https://bugs.webkit.org/show_bug.cgi?id=152939 5 6 Reviewed by Darin Adler. 7 8 Instead of creating the Path object every time it is required, we should 9 cache it in an LRU cache. TinyLRUCache returns a reference to the cached 10 entry so we do not have to pay the cost of copying it either. 11 12 * platform/graphics/FloatRoundedRect.h: 13 (WebCore::operator!=): 14 Implement the inequality operator for FloatRoundedRect since it is 15 called by TinyLRUCache. 16 17 * rendering/ClipPathOperation.h: 18 Return a reference to the path in the cache since instead of creating a 19 new copy. 20 21 * rendering/style/BasicShapes.cpp: 22 (WebCore::SVGPathTranslatedByteStream::SVGPathTranslatedByteStream): 23 (WebCore::SVGPathTranslatedByteStream::operator==): 24 (WebCore::SVGPathTranslatedByteStream::operator!=): 25 (WebCore::SVGPathTranslatedByteStream::isEmpty): 26 (WebCore::SVGPathTranslatedByteStream::path): 27 This struct holds an offset and an SVGPathByteStream. It is the key of 28 the LRU cache for the the translated SVGPathByteStream. 29 30 (WebCore::EllipsePathPolicy::isKeyNull): 31 (WebCore::EllipsePathPolicy::createValueForKey): 32 (WebCore::RoundedRectPathPolicy::isKeyNull): 33 (WebCore::RoundedRectPathPolicy::createValueForKey): 34 (WebCore::PolygonPathPolicy::isKeyNull): 35 (WebCore::PolygonPathPolicy::createValueForKey): 36 (WebCore::TranslatedByteStreamPathPolicy::isKeyNull): 37 (WebCore::TranslatedByteStreamPathPolicy::createValueForKey): 38 Inherit from the LRU cache policy template, so have a specific name for 39 the desired path contents and pass this class explicitly to the LRU cache 40 template. 41 42 (WebCore::cachedEllipsePath): 43 (WebCore::cachedRoundedRectPath): 44 (WebCore::cachedPolygonPath): 45 (WebCore::cachedTranslatedByteStreamPath): 46 Return a cached path object for specific path contents. 47 48 (WebCore::BasicShapeCircle::path): 49 (WebCore::BasicShapeEllipse::path): 50 (WebCore::BasicShapePolygon::path): 51 (WebCore::BasicShapePath::path): 52 (WebCore::BasicShapeInset::path): 53 Get the Path object from the cache; create a new one if it does not exist. 54 55 * rendering/style/BasicShapes.h: 56 Change the prototype of the path() function to return a reference to the 57 path in the cache instead of a having to copying it. 58 59 * svg/SVGPathByteStream.h: 60 (WebCore::SVGPathByteStream::operator!=): 61 Implement the inequality operator for SVGPathByteStream because it is 62 called by TinyLRUCache. 63 1 64 2016-02-01 Chris Dumez <cdumez@apple.com> 2 65 -
trunk/Source/WebCore/platform/graphics/FloatRoundedRect.h
r191243 r195970 142 142 } 143 143 144 inline bool operator!=(const FloatRoundedRect::Radii& a, const FloatRoundedRect::Radii& b) 145 { 146 return !(a == b); 147 } 148 144 149 inline bool operator==(const FloatRoundedRect& a, const FloatRoundedRect& b) 145 150 { 146 151 return a.rect() == b.rect() && a.radii() == b.radii(); 152 } 153 154 inline bool operator!=(const FloatRoundedRect& a, const FloatRoundedRect& b) 155 { 156 return !(a == b); 147 157 } 148 158 -
trunk/Source/WebCore/rendering/ClipPathOperation.h
r194496 r195970 104 104 const BasicShape& basicShape() const { return m_shape; } 105 105 WindRule windRule() const { return m_shape.get().windRule(); } 106 const Path pathForReferenceRect(const FloatRect& boundingRect) 107 { 108 Path path; 109 m_shape.get().path(path, boundingRect); 110 return path; 111 } 106 const Path& pathForReferenceRect(const FloatRect& boundingRect) { return m_shape.get().path(boundingRect); } 112 107 113 108 void setReferenceBox(CSSBoxType referenceBox) { m_referenceBox = referenceBox; } -
trunk/Source/WebCore/rendering/style/BasicShapes.cpp
r194496 r195970 42 42 #include "SVGPathUtilities.h" 43 43 44 #include <wtf/NeverDestroyed.h> 45 #include <wtf/TinyLRUCache.h> 46 44 47 namespace WebCore { 45 48 … … 61 64 } 62 65 66 struct SVGPathTranslatedByteStream { 67 SVGPathTranslatedByteStream(const FloatPoint& offset, const SVGPathByteStream& rawStream) 68 : m_offset(offset) 69 , m_rawStream(rawStream) 70 { } 71 72 bool operator==(const SVGPathTranslatedByteStream& other) const { return other.m_offset == m_offset && other.m_rawStream == m_rawStream; } 73 bool operator!=(const SVGPathTranslatedByteStream& other) const { return !(*this == other); } 74 bool isEmpty() const { return m_rawStream.isEmpty(); } 75 76 Path path() const 77 { 78 Path path; 79 buildPathFromByteStream(m_rawStream, path); 80 path.translate(toFloatSize(m_offset)); 81 return path; 82 } 83 84 FloatPoint m_offset; 85 SVGPathByteStream m_rawStream; 86 }; 87 88 struct EllipsePathPolicy : public TinyLRUCachePolicy<FloatRect, Path> { 89 public: 90 static bool isKeyNull(const FloatRect& rect) { return rect.isEmpty(); } 91 92 static Path createValueForKey(const FloatRect& rect) 93 { 94 Path path; 95 path.addEllipse(rect); 96 return path; 97 } 98 }; 99 100 struct RoundedRectPathPolicy : public TinyLRUCachePolicy<FloatRoundedRect, Path> { 101 public: 102 static bool isKeyNull(const FloatRoundedRect& rect) { return rect.isEmpty(); } 103 104 static Path createValueForKey(const FloatRoundedRect& rect) 105 { 106 Path path; 107 path.addRoundedRect(rect); 108 return path; 109 } 110 }; 111 112 struct PolygonPathPolicy : public TinyLRUCachePolicy<Vector<FloatPoint>, Path> { 113 public: 114 static bool isKeyNull(const Vector<FloatPoint>& points) { return !points.size(); } 115 116 static Path createValueForKey(const Vector<FloatPoint>& points) { return Path::polygonPathFromPoints(points); } 117 }; 118 119 struct TranslatedByteStreamPathPolicy : public TinyLRUCachePolicy<SVGPathTranslatedByteStream, Path> { 120 public: 121 static bool isKeyNull(const SVGPathTranslatedByteStream& stream) { return stream.isEmpty(); } 122 123 static Path createValueForKey(const SVGPathTranslatedByteStream& stream) { return stream.path(); } 124 }; 125 126 static const Path& cachedEllipsePath(const FloatRect& rect) 127 { 128 static NeverDestroyed<TinyLRUCache<FloatRect, Path, 4, EllipsePathPolicy>> cache; 129 return cache.get().get(rect); 130 } 131 132 static const Path& cachedRoundedRectPath(const FloatRoundedRect& rect) 133 { 134 static NeverDestroyed<TinyLRUCache<FloatRoundedRect, Path, 4, RoundedRectPathPolicy>> cache; 135 return cache.get().get(rect); 136 } 137 138 static const Path& cachedPolygonPath(const Vector<FloatPoint>& points) 139 { 140 static NeverDestroyed<TinyLRUCache<Vector<FloatPoint>, Path, 4, PolygonPathPolicy>> cache; 141 return cache.get().get(points); 142 } 143 144 static const Path& cachedTranslatedByteStreamPath(const SVGPathByteStream& stream, const FloatPoint& offset) 145 { 146 static NeverDestroyed<TinyLRUCache<SVGPathTranslatedByteStream, Path, 4, TranslatedByteStreamPathPolicy>> cache; 147 return cache.get().get(SVGPathTranslatedByteStream(offset, stream)); 148 } 149 63 150 bool BasicShapeCircle::operator==(const BasicShape& other) const 64 151 { … … 89 176 } 90 177 91 void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox) 92 { 93 ASSERT(path.isEmpty()); 94 178 const Path& BasicShapeCircle::path(const FloatRect& boundingBox) 179 { 95 180 float centerX = floatValueForCenterCoordinate(m_centerX, boundingBox.width()); 96 181 float centerY = floatValueForCenterCoordinate(m_centerY, boundingBox.height()); 97 182 float radius = floatValueForRadiusInBox(boundingBox.width(), boundingBox.height()); 98 path.addEllipse(FloatRect( 99 centerX - radius + boundingBox.x(), 100 centerY - radius + boundingBox.y(), 101 radius * 2, 102 radius * 2 103 )); 183 184 return cachedEllipsePath(FloatRect(centerX - radius + boundingBox.x(), centerY - radius + boundingBox.y(), radius * 2, radius * 2)); 104 185 } 105 186 … … 149 230 } 150 231 151 void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox) 152 { 153 ASSERT(path.isEmpty()); 154 232 const Path& BasicShapeEllipse::path(const FloatRect& boundingBox) 233 { 155 234 float centerX = floatValueForCenterCoordinate(m_centerX, boundingBox.width()); 156 235 float centerY = floatValueForCenterCoordinate(m_centerY, boundingBox.height()); 157 236 float radiusX = floatValueForRadiusInBox(m_radiusX, centerX, boundingBox.width()); 158 237 float radiusY = floatValueForRadiusInBox(m_radiusY, centerY, boundingBox.height()); 159 path.addEllipse(FloatRect( 160 centerX - radiusX + boundingBox.x(), 161 centerY - radiusY + boundingBox.y(), 162 radiusX * 2, 163 radiusY * 2)); 238 239 return cachedEllipsePath(FloatRect(centerX - radiusX + boundingBox.x(), centerY - radiusY + boundingBox.y(), radiusX * 2, radiusY * 2)); 164 240 } 165 241 … … 205 281 } 206 282 207 void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox) 208 { 209 ASSERT(path.isEmpty()); 283 const Path& BasicShapePolygon::path(const FloatRect& boundingBox) 284 { 210 285 ASSERT(!(m_values.size() % 2)); 211 286 size_t length = m_values.size(); 212 213 if (!length) 214 return; 215 216 path.moveTo(FloatPoint(floatValueForLength(m_values.at(0), boundingBox.width()) + boundingBox.x(), 217 floatValueForLength(m_values.at(1), boundingBox.height()) + boundingBox.y())); 218 for (size_t i = 2; i < length; i = i + 2) { 219 path.addLineTo(FloatPoint(floatValueForLength(m_values.at(i), boundingBox.width()) + boundingBox.x(), 220 floatValueForLength(m_values.at(i + 1), boundingBox.height()) + boundingBox.y())); 221 } 222 path.closeSubpath(); 287 288 Vector<FloatPoint> points(length / 2); 289 for (size_t i = 0; i < points.size(); ++i) { 290 points[i].setX(floatValueForLength(m_values.at(i * 2), boundingBox.width()) + boundingBox.x()); 291 points[i].setY(floatValueForLength(m_values.at(i * 2 + 1), boundingBox.height()) + boundingBox.y()); 292 } 293 294 return cachedPolygonPath(points); 223 295 } 224 296 … … 260 332 } 261 333 262 void BasicShapePath::path(Path& path, const FloatRect& boundingBox) 263 { 264 ASSERT(path.isEmpty()); 265 buildPathFromByteStream(*m_byteStream, path); 266 path.translate(toFloatSize(boundingBox.location())); 334 const Path& BasicShapePath::path(const FloatRect& boundingBox) 335 { 336 return cachedTranslatedByteStreamPath(*m_byteStream, boundingBox.location()); 267 337 } 268 338 … … 321 391 } 322 392 323 void BasicShapeInset::path(Path& path, const FloatRect& boundingBox) 324 { 325 ASSERT(path.isEmpty()); 393 const Path& BasicShapeInset::path(const FloatRect& boundingBox) 394 { 326 395 float left = floatValueForLength(m_left, boundingBox.width()); 327 396 float top = floatValueForLength(m_top, boundingBox.height()); … … 334 403 floatSizeForLengthSize(m_bottomRightRadius, boundingBox)); 335 404 radii.scale(calcBorderRadiiConstraintScaleFor(rect, radii)); 336 path.addRoundedRect(FloatRoundedRect(rect, radii)); 405 406 return cachedRoundedRectPath(FloatRoundedRect(rect, radii)); 337 407 } 338 408 -
trunk/Source/WebCore/rendering/style/BasicShapes.h
r194496 r195970 61 61 virtual Type type() const = 0; 62 62 63 virtual void path(Path&,const FloatRect&) = 0;63 virtual const Path& path(const FloatRect&) = 0; 64 64 virtual WindRule windRule() const { return RULE_NONZERO; } 65 65 … … 193 193 virtual Type type() const override { return BasicShapeCircleType; } 194 194 195 virtual void path(Path&,const FloatRect&) override;195 virtual const Path& path(const FloatRect&) override; 196 196 197 197 virtual bool canBlend(const BasicShape&) const override; … … 225 225 virtual Type type() const override { return BasicShapeEllipseType; } 226 226 227 virtual void path(Path&,const FloatRect&) override;227 virtual const Path& path(const FloatRect&) override; 228 228 229 229 virtual bool canBlend(const BasicShape&) const override; … … 256 256 virtual Type type() const override { return BasicShapePolygonType; } 257 257 258 virtual void path(Path&,const FloatRect&) override;258 virtual const Path& path(const FloatRect&) override; 259 259 260 260 virtual bool canBlend(const BasicShape&) const override; … … 284 284 virtual Type type() const override { return BasicShapePathType; } 285 285 286 virtual void path(Path&,const FloatRect&) override;286 virtual const Path& path(const FloatRect&) override; 287 287 288 288 virtual bool canBlend(const BasicShape&) const override; … … 324 324 virtual Type type() const override { return BasicShapeInsetType; } 325 325 326 virtual void path(Path&,const FloatRect&) override;326 virtual const Path& path(const FloatRect&) override; 327 327 328 328 virtual bool canBlend(const BasicShape&) const override; -
trunk/Source/WebCore/svg/SVGPathByteStream.h
r191551 r195970 56 56 } 57 57 58 bool operator!=(const SVGPathByteStream& other) const 59 { 60 return !(*this == other); 61 } 62 58 63 std::unique_ptr<SVGPathByteStream> copy() const 59 64 {
Note:
See TracChangeset
for help on using the changeset viewer.