Modified: trunk/Source/WTF/wtf/TinyLRUCache.h (195969 => 195970)
--- trunk/Source/WTF/wtf/TinyLRUCache.h 2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WTF/wtf/TinyLRUCache.h 2016-02-01 19:45:18 UTC (rev 195970)
@@ -38,13 +38,13 @@
static ValueType createValueForKey(const KeyType&) { return { }; }
};
-template<typename KeyType, typename ValueType, size_t capacity = 4>
+template<typename KeyType, typename ValueType, size_t capacity = 4, typename Policy = TinyLRUCachePolicy<KeyType, ValueType>>
class TinyLRUCache {
public:
const ValueType& get(const KeyType& key)
{
- if (TinyLRUCachePolicy<KeyType, ValueType>::isKeyNull(key)) {
- static NeverDestroyed<ValueType> valueForNull = TinyLRUCachePolicy<KeyType, ValueType>::createValueForNullKey();
+ if (Policy::isKeyNull(key)) {
+ static NeverDestroyed<ValueType> valueForNull = Policy::createValueForNullKey();
return valueForNull;
}
@@ -66,7 +66,7 @@
if (m_cache.size() == capacity)
m_cache.remove(0);
- m_cache.append(std::make_pair(key, TinyLRUCachePolicy<KeyType, ValueType>::createValueForKey(key)));
+ m_cache.append(std::make_pair(key, Policy::createValueForKey(key)));
return m_cache.last().second;
}
Modified: trunk/Source/WebCore/rendering/style/BasicShapes.cpp (195969 => 195970)
--- trunk/Source/WebCore/rendering/style/BasicShapes.cpp 2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.cpp 2016-02-01 19:45:18 UTC (rev 195970)
@@ -41,6 +41,9 @@
#include "SVGPathByteStream.h"
#include "SVGPathUtilities.h"
+#include <wtf/NeverDestroyed.h>
+#include <wtf/TinyLRUCache.h>
+
namespace WebCore {
void BasicShapeCenterCoordinate::updateComputedLength()
@@ -60,6 +63,90 @@
m_computedLength = Length(CalculationValue::create(WTFMove(op), CalculationRangeAll));
}
+struct SVGPathTranslatedByteStream {
+ SVGPathTranslatedByteStream(const FloatPoint& offset, const SVGPathByteStream& rawStream)
+ : m_offset(offset)
+ , m_rawStream(rawStream)
+ { }
+
+ bool operator==(const SVGPathTranslatedByteStream& other) const { return other.m_offset == m_offset && other.m_rawStream == m_rawStream; }
+ bool operator!=(const SVGPathTranslatedByteStream& other) const { return !(*this == other); }
+ bool isEmpty() const { return m_rawStream.isEmpty(); }
+
+ Path path() const
+ {
+ Path path;
+ buildPathFromByteStream(m_rawStream, path);
+ path.translate(toFloatSize(m_offset));
+ return path;
+ }
+
+ FloatPoint m_offset;
+ SVGPathByteStream m_rawStream;
+};
+
+struct EllipsePathPolicy : public TinyLRUCachePolicy<FloatRect, Path> {
+public:
+ static bool isKeyNull(const FloatRect& rect) { return rect.isEmpty(); }
+
+ static Path createValueForKey(const FloatRect& rect)
+ {
+ Path path;
+ path.addEllipse(rect);
+ return path;
+ }
+};
+
+struct RoundedRectPathPolicy : public TinyLRUCachePolicy<FloatRoundedRect, Path> {
+public:
+ static bool isKeyNull(const FloatRoundedRect& rect) { return rect.isEmpty(); }
+
+ static Path createValueForKey(const FloatRoundedRect& rect)
+ {
+ Path path;
+ path.addRoundedRect(rect);
+ return path;
+ }
+};
+
+struct PolygonPathPolicy : public TinyLRUCachePolicy<Vector<FloatPoint>, Path> {
+public:
+ static bool isKeyNull(const Vector<FloatPoint>& points) { return !points.size(); }
+
+ static Path createValueForKey(const Vector<FloatPoint>& points) { return Path::polygonPathFromPoints(points); }
+};
+
+struct TranslatedByteStreamPathPolicy : public TinyLRUCachePolicy<SVGPathTranslatedByteStream, Path> {
+public:
+ static bool isKeyNull(const SVGPathTranslatedByteStream& stream) { return stream.isEmpty(); }
+
+ static Path createValueForKey(const SVGPathTranslatedByteStream& stream) { return stream.path(); }
+};
+
+static const Path& cachedEllipsePath(const FloatRect& rect)
+{
+ static NeverDestroyed<TinyLRUCache<FloatRect, Path, 4, EllipsePathPolicy>> cache;
+ return cache.get().get(rect);
+}
+
+static const Path& cachedRoundedRectPath(const FloatRoundedRect& rect)
+{
+ static NeverDestroyed<TinyLRUCache<FloatRoundedRect, Path, 4, RoundedRectPathPolicy>> cache;
+ return cache.get().get(rect);
+}
+
+static const Path& cachedPolygonPath(const Vector<FloatPoint>& points)
+{
+ static NeverDestroyed<TinyLRUCache<Vector<FloatPoint>, Path, 4, PolygonPathPolicy>> cache;
+ return cache.get().get(points);
+}
+
+static const Path& cachedTranslatedByteStreamPath(const SVGPathByteStream& stream, const FloatPoint& offset)
+{
+ static NeverDestroyed<TinyLRUCache<SVGPathTranslatedByteStream, Path, 4, TranslatedByteStreamPathPolicy>> cache;
+ return cache.get().get(SVGPathTranslatedByteStream(offset, stream));
+}
+
bool BasicShapeCircle::operator==(const BasicShape& other) const
{
if (type() != other.type())
@@ -88,19 +175,13 @@
return std::max(std::max(std::abs(centerX), widthDelta), std::max(std::abs(centerY), heightDelta));
}
-void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
+const Path& BasicShapeCircle::path(const FloatRect& boundingBox)
{
- ASSERT(path.isEmpty());
-
float centerX = floatValueForCenterCoordinate(m_centerX, boundingBox.width());
float centerY = floatValueForCenterCoordinate(m_centerY, boundingBox.height());
float radius = floatValueForRadiusInBox(boundingBox.width(), boundingBox.height());
- path.addEllipse(FloatRect(
- centerX - radius + boundingBox.x(),
- centerY - radius + boundingBox.y(),
- radius * 2,
- radius * 2
- ));
+
+ return cachedEllipsePath(FloatRect(centerX - radius + boundingBox.x(), centerY - radius + boundingBox.y(), radius * 2, radius * 2));
}
bool BasicShapeCircle::canBlend(const BasicShape& other) const
@@ -148,19 +229,14 @@
return std::max(std::abs(center), widthOrHeightDelta);
}
-void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
+const Path& BasicShapeEllipse::path(const FloatRect& boundingBox)
{
- ASSERT(path.isEmpty());
-
float centerX = floatValueForCenterCoordinate(m_centerX, boundingBox.width());
float centerY = floatValueForCenterCoordinate(m_centerY, boundingBox.height());
float radiusX = floatValueForRadiusInBox(m_radiusX, centerX, boundingBox.width());
float radiusY = floatValueForRadiusInBox(m_radiusY, centerY, boundingBox.height());
- path.addEllipse(FloatRect(
- centerX - radiusX + boundingBox.x(),
- centerY - radiusY + boundingBox.y(),
- radiusX * 2,
- radiusY * 2));
+
+ return cachedEllipsePath(FloatRect(centerX - radiusX + boundingBox.x(), centerY - radiusY + boundingBox.y(), radiusX * 2, radiusY * 2));
}
bool BasicShapeEllipse::canBlend(const BasicShape& other) const
@@ -204,22 +280,18 @@
&& m_values == otherPolygon.m_values;
}
-void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
+const Path& BasicShapePolygon::path(const FloatRect& boundingBox)
{
- ASSERT(path.isEmpty());
ASSERT(!(m_values.size() % 2));
size_t length = m_values.size();
-
- if (!length)
- return;
- path.moveTo(FloatPoint(floatValueForLength(m_values.at(0), boundingBox.width()) + boundingBox.x(),
- floatValueForLength(m_values.at(1), boundingBox.height()) + boundingBox.y()));
- for (size_t i = 2; i < length; i = i + 2) {
- path.addLineTo(FloatPoint(floatValueForLength(m_values.at(i), boundingBox.width()) + boundingBox.x(),
- floatValueForLength(m_values.at(i + 1), boundingBox.height()) + boundingBox.y()));
+ Vector<FloatPoint> points(length / 2);
+ for (size_t i = 0; i < points.size(); ++i) {
+ points[i].setX(floatValueForLength(m_values.at(i * 2), boundingBox.width()) + boundingBox.x());
+ points[i].setY(floatValueForLength(m_values.at(i * 2 + 1), boundingBox.height()) + boundingBox.y());
}
- path.closeSubpath();
+
+ return cachedPolygonPath(points);
}
bool BasicShapePolygon::canBlend(const BasicShape& other) const
@@ -259,11 +331,9 @@
{
}
-void BasicShapePath::path(Path& path, const FloatRect& boundingBox)
+const Path& BasicShapePath::path(const FloatRect& boundingBox)
{
- ASSERT(path.isEmpty());
- buildPathFromByteStream(*m_byteStream, path);
- path.translate(toFloatSize(boundingBox.location()));
+ return cachedTranslatedByteStreamPath(*m_byteStream, boundingBox.location());
}
bool BasicShapePath::operator==(const BasicShape& other) const
@@ -320,9 +390,8 @@
floatValueForLength(lengthSize.height(), boundingBox.height()));
}
-void BasicShapeInset::path(Path& path, const FloatRect& boundingBox)
+const Path& BasicShapeInset::path(const FloatRect& boundingBox)
{
- ASSERT(path.isEmpty());
float left = floatValueForLength(m_left, boundingBox.width());
float top = floatValueForLength(m_top, boundingBox.height());
auto rect = FloatRect(left + boundingBox.x(), top + boundingBox.y(),
@@ -333,7 +402,8 @@
floatSizeForLengthSize(m_bottomLeftRadius, boundingBox),
floatSizeForLengthSize(m_bottomRightRadius, boundingBox));
radii.scale(calcBorderRadiiConstraintScaleFor(rect, radii));
- path.addRoundedRect(FloatRoundedRect(rect, radii));
+
+ return cachedRoundedRectPath(FloatRoundedRect(rect, radii));
}
bool BasicShapeInset::canBlend(const BasicShape& other) const
Modified: trunk/Source/WebCore/rendering/style/BasicShapes.h (195969 => 195970)
--- trunk/Source/WebCore/rendering/style/BasicShapes.h 2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.h 2016-02-01 19:45:18 UTC (rev 195970)
@@ -60,7 +60,7 @@
virtual Type type() const = 0;
- virtual void path(Path&, const FloatRect&) = 0;
+ virtual const Path& path(const FloatRect&) = 0;
virtual WindRule windRule() const { return RULE_NONZERO; }
virtual bool canBlend(const BasicShape&) const = 0;
@@ -192,7 +192,7 @@
virtual Type type() const override { return BasicShapeCircleType; }
- virtual void path(Path&, const FloatRect&) override;
+ virtual const Path& path(const FloatRect&) override;
virtual bool canBlend(const BasicShape&) const override;
virtual Ref<BasicShape> blend(const BasicShape&, double) const override;
@@ -224,7 +224,7 @@
virtual Type type() const override { return BasicShapeEllipseType; }
- virtual void path(Path&, const FloatRect&) override;
+ virtual const Path& path(const FloatRect&) override;
virtual bool canBlend(const BasicShape&) const override;
virtual Ref<BasicShape> blend(const BasicShape&, double) const override;
@@ -255,7 +255,7 @@
virtual Type type() const override { return BasicShapePolygonType; }
- virtual void path(Path&, const FloatRect&) override;
+ virtual const Path& path(const FloatRect&) override;
virtual bool canBlend(const BasicShape&) const override;
virtual Ref<BasicShape> blend(const BasicShape&, double) const override;
@@ -283,7 +283,7 @@
virtual Type type() const override { return BasicShapePathType; }
- virtual void path(Path&, const FloatRect&) override;
+ virtual const Path& path(const FloatRect&) override;
virtual bool canBlend(const BasicShape&) const override;
virtual Ref<BasicShape> blend(const BasicShape&, double) const override;
@@ -323,7 +323,7 @@
virtual Type type() const override { return BasicShapeInsetType; }
- virtual void path(Path&, const FloatRect&) override;
+ virtual const Path& path(const FloatRect&) override;
virtual bool canBlend(const BasicShape&) const override;
virtual Ref<BasicShape> blend(const BasicShape&, double) const override;