| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FLUTTER_LIB_UI_PAINTING_IMAGE_GENERATOR_REGISTRY_H_ |
| #define FLUTTER_LIB_UI_PAINTING_IMAGE_GENERATOR_REGISTRY_H_ |
| |
| #include <functional> |
| #include <set> |
| |
| #include "flutter/fml/mapping.h" |
| #include "flutter/fml/memory/weak_ptr.h" |
| #include "flutter/lib/ui/painting/image_generator.h" |
| |
| namespace flutter { |
| |
| /// @brief `ImageGeneratorFactory` is the top level primitive for specifying an |
| /// image decoder in Flutter. When called, it should return an |
| /// `ImageGenerator` that typically compatible with the given input |
| /// data. |
| using ImageGeneratorFactory = |
| std::function<std::shared_ptr<ImageGenerator>(sk_sp<SkData> buffer)>; |
| |
| /// @brief Keeps a priority-ordered registry of image generator builders to be |
| /// used when decoding images. This object must be created, accessed, and |
| /// collected on the UI thread (typically the engine or its runtime |
| /// controller). |
| class ImageGeneratorRegistry { |
| public: |
| ImageGeneratorRegistry(); |
| |
| ~ImageGeneratorRegistry(); |
| |
| /// @brief Install a new factory for image generators |
| /// @param[in] factory Callback that produces `ImageGenerator`s for |
| /// compatible input data. |
| /// @param[in] priority The priority used to determine the order in which |
| /// factories are tried. Higher values mean higher |
| /// priority. The built-in Skia decoders are installed |
| /// at priority 0, and so a priority > 0 takes precedent |
| /// over the builtin decoders. When multiple decoders |
| /// are added with the same priority, those which are |
| /// added earlier take precedent. |
| /// @see `CreateCompatibleGenerator` |
| void AddFactory(ImageGeneratorFactory factory, int32_t priority); |
| |
| /// @brief Walks the list of image generator builders in descending |
| /// priority order until a compatible `ImageGenerator` is able to |
| /// be built. This method is safe to perform on the UI thread, as |
| /// checking for `ImageGenerator` compatibility is expected to be |
| /// a lightweight operation. The returned `ImageGenerator` can |
| /// then be used to fully decode the image on e.g. the IO thread. |
| /// @param[in] buffer The raw encoded image data. |
| /// @return An `ImageGenerator` that is compatible with the input buffer. |
| /// If no compatible `ImageGenerator` type was found, then |
| /// `std::shared_ptr<ImageGenerator>(nullptr)` is returned. |
| /// @see `ImageGenerator` |
| std::shared_ptr<ImageGenerator> CreateCompatibleGenerator( |
| sk_sp<SkData> buffer); |
| |
| fml::WeakPtr<ImageGeneratorRegistry> GetWeakPtr() const; |
| |
| private: |
| struct PrioritizedFactory { |
| ImageGeneratorFactory callback; |
| |
| int32_t priority = 0; |
| // Used as a fallback priority comparison when equal. |
| size_t ascending_nonce = 0; |
| }; |
| |
| struct Compare { |
| constexpr bool operator()(const PrioritizedFactory& lhs, |
| const PrioritizedFactory& rhs) const { |
| // When priorities are equal, factories registered earlier take |
| // precedent. |
| if (lhs.priority == rhs.priority) { |
| return lhs.ascending_nonce < rhs.ascending_nonce; |
| } |
| // Order by descending priority. |
| return lhs.priority > rhs.priority; |
| } |
| }; |
| |
| using FactorySet = std::set<PrioritizedFactory, Compare>; |
| FactorySet image_generator_factories_; |
| size_t nonce_; |
| fml::WeakPtrFactory<ImageGeneratorRegistry> weak_factory_; |
| }; |
| |
| } // namespace flutter |
| |
| #endif // FLUTTER_LIB_UI_PAINTING_IMAGE_DECODER_H_ |