diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h b/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h index ca11a1c7dee..1539c8e20fa 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h @@ -8,15 +8,27 @@ #pragma once #include -#include +#include #include #include #include #include +#include #include +#include namespace facebook::react { +static size_t hashGetColourArguments( + int32_t surfaceId, + const std::vector& resourcePaths) { + std::size_t seed = surfaceId; + for (const auto& item : resourcePaths) { + facebook::react::hash_combine(seed, item); + } + return seed; +} + inline SharedColor parsePlatformColor( const ContextContainer& contextContainer, int32_t surfaceId, @@ -25,29 +37,45 @@ inline SharedColor parsePlatformColor( if (value.hasType< std::unordered_map>>()) { - const auto& fabricUIManager = - contextContainer.at>("FabricUIManager"); - static auto getColorFromJava = - fabricUIManager->getClass() - ->getMethod)>("getColor"); - auto map = (std::unordered_map>)value; auto& resourcePaths = map["resource_paths"]; - auto javaResourcePaths = - jni::JArrayClass::newArray(resourcePaths.size()); - for (int i = 0; i < resourcePaths.size(); i++) { - javaResourcePaths->setElement(i, *jni::make_jstring(resourcePaths[i])); - } - auto color = - getColorFromJava(fabricUIManager, surfaceId, *javaResourcePaths); + // JNI calls are time consuming. Let's cache results here to avoid + // unnecessary calls. + static auto getColorCache = + folly::EvictingCacheMap(64); - auto argb = (int64_t)color; - auto ratio = 255.f; - colorComponents.alpha = ((argb >> 24) & 0xFF) / ratio; - colorComponents.red = ((argb >> 16) & 0xFF) / ratio; - colorComponents.green = ((argb >> 8) & 0xFF) / ratio; - colorComponents.blue = (argb & 0xFF) / ratio; + auto hash = hashGetColourArguments(surfaceId, resourcePaths); + auto iterator = getColorCache.find(hash); + + if (iterator != getColorCache.end()) { + colorComponents = iterator->second; + } else { + const auto& fabricUIManager = + contextContainer.at>("FabricUIManager"); + static auto getColorFromJava = + fabricUIManager->getClass() + ->getMethod)>( + "getColor"); + auto javaResourcePaths = + jni::JArrayClass::newArray(resourcePaths.size()); + + for (int i = 0; i < resourcePaths.size(); i++) { + javaResourcePaths->setElement(i, *jni::make_jstring(resourcePaths[i])); + } + auto color = + getColorFromJava(fabricUIManager, surfaceId, *javaResourcePaths); + + auto argb = (int64_t)color; + auto ratio = 255.f; + + colorComponents.alpha = ((argb >> 24) & 0xFF) / ratio; + colorComponents.red = ((argb >> 16) & 0xFF) / ratio; + colorComponents.green = ((argb >> 8) & 0xFF) / ratio; + colorComponents.blue = (argb & 0xFF) / ratio; + + getColorCache.set(hash, colorComponents); + } } return {colorFromComponents(colorComponents)};