Extended Color: Switch ColorMac.mm's nsColor() function over to using TinyLRUCache
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Jun 2020 14:13:33 +0000 (14:13 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Jun 2020 14:13:33 +0000 (14:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=212918

Reviewed by Darin Adler.

* platform/graphics/Color.h:
(WebCore::Color::isExtended const):
Make asSimple() public, so nsColor() can use it. This also allows us to unfriend cachedCGColor().

* platform/graphics/mac/ColorMac.mm:
(WTF::RetainPtr<NSColor>>::createValueForKey):
(WebCore::nsColor):
Mimic the structure of cachedCGColor() by switching over simpleColor values for common
colors and using a 32 value TinyLRUCache for the rest.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@262790 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/Color.cpp
Source/WebCore/platform/graphics/Color.h
Source/WebCore/platform/graphics/cg/ColorCG.cpp
Source/WebCore/platform/graphics/mac/ColorMac.mm

index 67b681a..36dae07 100644 (file)
@@ -1,3 +1,20 @@
+2020-06-09  Sam Weinig  <weinig@apple.com>
+
+        Extended Color: Switch ColorMac.mm's nsColor() function over to using TinyLRUCache
+        https://bugs.webkit.org/show_bug.cgi?id=212918
+
+        Reviewed by Darin Adler.
+
+        * platform/graphics/Color.h:
+        (WebCore::Color::isExtended const):
+        Make asSimple() public, so nsColor() can use it. This also allows us to unfriend cachedCGColor().
+
+        * platform/graphics/mac/ColorMac.mm:
+        (WTF::RetainPtr<NSColor>>::createValueForKey):
+        (WebCore::nsColor):
+        Mimic the structure of cachedCGColor() by switching over simpleColor values for common
+        colors and using a 32 value TinyLRUCache for the rest.
+
 2020-06-09  Xabier Rodriguez Calvar  <calvaris@igalia.com>
 
         [EME] CDMProxyInstance should not keep CDMInstanceSessions hard referenced
index 8ed75fd..96472ea 100644 (file)
@@ -103,7 +103,7 @@ String Color::nameForRenderTreeAsText() const
 Color Color::lightened() const
 {
     // Hardcode this common case for speed.
-    if (!isExtended() && asSimple() == black)
+    if (isSimple() && asSimple() == black)
         return lightenedBlack;
 
     auto [r, g, b, a] = toSRGBAComponentsLossy();
@@ -120,7 +120,7 @@ Color Color::lightened() const
 Color Color::darkened() const
 {
     // Hardcode this common case for speed.
-    if (!isExtended() && asSimple() == white)
+    if (isSimple() && asSimple() == white)
         return darkenedWhite;
     
     auto [r, g, b, a] = toSRGBAComponentsLossy();
index 8ff1d01..cb8f0a0 100644 (file)
@@ -162,7 +162,7 @@ public:
     Color semanticColor() const;
 
     // True if the color originated from a CSS semantic color name.
-    bool isSemantic() const { return !isExtended() && (m_colorData.simpleColorAndFlags & isSemanticSimpleColorBit); }
+    bool isSemantic() const { return isSimple() && (m_colorData.simpleColorAndFlags & isSemanticSimpleColorBit); }
 
 #if PLATFORM(GTK)
     Color(const GdkRGBA&);
@@ -172,7 +172,6 @@ public:
 #if USE(CG)
     WEBCORE_EXPORT Color(CGColorRef);
     WEBCORE_EXPORT Color(CGColorRef, SemanticTag);
-    friend WEBCORE_EXPORT CGColorRef cachedCGColor(const Color&);
 #endif
 
 #if PLATFORM(WIN)
@@ -190,11 +189,11 @@ public:
     static constexpr SimpleColor cyan { 0xFF00FFFF };
     static constexpr SimpleColor yellow { 0xFFFFFF00 };
 
-    bool isExtended() const
-    {
-        return !(m_colorData.simpleColorAndFlags & invalidSimpleColor);
-    }
+    bool isExtended() const { return !(m_colorData.simpleColorAndFlags & invalidSimpleColor); }
+    bool isSimple() const { return !isExtended(); }
+
     const ExtendedColor& asExtended() const;
+    const SimpleColor asSimple() const;
 
     WEBCORE_EXPORT Color& operator=(const Color&);
     WEBCORE_EXPORT Color& operator=(Color&&);
@@ -211,8 +210,6 @@ public:
     template<class Decoder> static Optional<Color> decode(Decoder&);
 
 private:
-    const SimpleColor asSimple() const;
-
     void setSimpleColor(SimpleColor);
 
     void tagAsSemantic() { m_colorData.simpleColorAndFlags |= isSemanticSimpleColorBit; }
@@ -316,7 +313,7 @@ inline const ExtendedColor& Color::asExtended() const
 
 inline const SimpleColor Color::asSimple() const
 {
-    ASSERT(!isExtended());
+    ASSERT(isSimple());
     return { static_cast<uint32_t>(m_colorData.simpleColorAndFlags >> 32) };
 }
 
index 4d0ea8c..7c11ebb 100644 (file)
@@ -128,7 +128,7 @@ static CGColorRef leakCGColor(const Color& color)
 
 CGColorRef cachedCGColor(const Color& color)
 {
-    if (!color.isExtended()) {
+    if (color.isSimple()) {
         switch (color.asSimple().value()) {
         case Color::transparent.value(): {
             static CGColorRef transparentCGColor = leakCGColor(color);
index 5282f64..4c5f354 100644 (file)
 #import <wtf/BlockObjCExceptions.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/RetainPtr.h>
-#import <wtf/StdLibExtras.h>
+#import <wtf/TinyLRUCache.h>
+
+namespace WTF {
+
+template<> RetainPtr<NSColor> TinyLRUCachePolicy<WebCore::Color, RetainPtr<NSColor>>::createValueForKey(const WebCore::Color& color)
+{
+    return [NSColor colorWithCGColor:cachedCGColor(color)];
+}
+
+} // namespace WTF
 
 namespace WebCore {
 
@@ -113,43 +122,27 @@ Color semanticColorFromNSColor(NSColor *color)
 
 NSColor *nsColor(const Color& color)
 {
-    if (!color.isValid()) {
-        // Need this to avoid returning nil because cachedRGBAValues will default to 0.
-        static NeverDestroyed<NSColor *> clearColor = [[NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:0] retain];
-        return clearColor;
-    }
-
-    if (Color::isBlackColor(color)) {
-        static NeverDestroyed<NSColor *> blackColor = [[NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:1] retain];
-        return blackColor;
+    if (color.isSimple()) {
+        switch (color.asSimple().value()) {
+        case Color::transparent.value(): {
+            static NSColor *clearColor = [[NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:0] retain];
+            return clearColor;
+        }
+        case Color::black.value(): {
+            static NSColor *blackColor = [[NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:1] retain];
+            return blackColor;
+        }
+        case Color::white.value(): {
+            static NSColor *whiteColor = [[NSColor colorWithSRGBRed:1 green:1 blue:1 alpha:1] retain];
+            return whiteColor;
+        }
+        }
     }
 
-    if (Color::isWhiteColor(color)) {
-        static NeverDestroyed<NSColor *> whiteColor = [[NSColor colorWithSRGBRed:1 green:1 blue:1 alpha:1] retain];
-        return whiteColor;
-    }
-
-    const int cacheSize = 32;
-    static unsigned cachedRGBAValues[cacheSize];
-    static RetainPtr<NSColor>* cachedColors = new RetainPtr<NSColor>[cacheSize];
-
-    unsigned hash = color.hash();
-    for (int i = 0; i < cacheSize; ++i) {
-        if (cachedRGBAValues[i] == hash)
-            return cachedColors[i].get();
-    }
-
-    NSColor *result = [NSColor colorWithCGColor:cachedCGColor(color)];
-
-    static int cursor;
-    cachedRGBAValues[cursor] = hash;
-    cachedColors[cursor] = result;
-    if (++cursor == cacheSize)
-        cursor = 0;
-    return result;
+    static NeverDestroyed<TinyLRUCache<Color, RetainPtr<NSColor>, 32>> cache;
+    return cache.get().get(color).get();
 }
 
-
 } // namespace WebCore
 
 #endif // USE(APPKIT)