Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

Commit

Permalink
Add image generator registry and lookup with priority
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero committed May 6, 2021
1 parent ccaae8d commit 2aeb496
Show file tree
Hide file tree
Showing 18 changed files with 472 additions and 35 deletions.
5 changes: 5 additions & 0 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ source_set("ui") {
"painting/image_encoding.h",
"painting/image_filter.cc",
"painting/image_filter.h",
"painting/image_generator.cc",
"painting/image_generator.h",
"painting/image_generator_registry.cc",
"painting/image_generator_registry.h",
"painting/image_shader.cc",
"painting/image_shader.h",
"painting/immutable_buffer.cc",
Expand Down Expand Up @@ -197,6 +201,7 @@ if (enable_unittests) {
sources = [
"painting/image_dispose_unittests.cc",
"painting/image_encoding_unittests.cc",
"painting/image_generator_registry_unittests.cc",
"painting/path_unittests.cc",
"painting/vertices_unittests.cc",
"window/platform_configuration_unittests.cc",
Expand Down
69 changes: 69 additions & 0 deletions lib/ui/painting/image_generator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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.

#include "flutter/lib/ui/painting/image_generator.h"

namespace flutter {

BuiltinSkiaImageGenerator::BuiltinSkiaImageGenerator(
std::unique_ptr<SkImageGenerator> generator)
: generator_(std::move(generator)) {}

const SkImageInfo& BuiltinSkiaImageGenerator::getInfo() const {
return generator_->getInfo();
}

bool BuiltinSkiaImageGenerator::getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) const {
return generator_->getPixels(info, pixels, rowBytes);
}

SkISize BuiltinSkiaImageGenerator::getScaledDimensions(float desiredScale) {
return generator_->getInfo().dimensions();
}

std::unique_ptr<ImageGenerator> BuiltinSkiaImageGenerator::makeFromGenerator(
std::unique_ptr<SkImageGenerator> generator) {
if (!generator) {
return nullptr;
}
return std::make_unique<BuiltinSkiaImageGenerator>(std::move(generator));
}

BuiltinSkiaCodecImageGenerator::BuiltinSkiaCodecImageGenerator(
std::unique_ptr<SkCodec> codec)
: codec_generator_(static_cast<SkCodecImageGenerator*>(
SkCodecImageGenerator::MakeFromCodec(std::move(codec)).release())) {}

BuiltinSkiaCodecImageGenerator::BuiltinSkiaCodecImageGenerator(
sk_sp<SkData> buffer)
: codec_generator_(static_cast<SkCodecImageGenerator*>(
SkCodecImageGenerator::MakeFromEncodedCodec(buffer).release())) {}

const SkImageInfo& BuiltinSkiaCodecImageGenerator::getInfo() const {
return codec_generator_->getInfo();
}

bool BuiltinSkiaCodecImageGenerator::getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) const {
return codec_generator_->getPixels(info, pixels, rowBytes);
}

SkISize BuiltinSkiaCodecImageGenerator::getScaledDimensions(
float desiredScale) {
return codec_generator_->getScaledDimensions(desiredScale);
}

std::unique_ptr<ImageGenerator> BuiltinSkiaCodecImageGenerator::makeFromData(
sk_sp<SkData> data) {
auto codec = SkCodec::MakeFromData(data);
if (!codec) {
return nullptr;
}
return std::make_unique<BuiltinSkiaCodecImageGenerator>(std::move(codec));
}

} // namespace flutter
82 changes: 82 additions & 0 deletions lib/ui/painting/image_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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_H_
#define FLUTTER_LIB_UI_PAINTING_IMAGE_GENERATOR_H_

#include "flutter/lib/ui/painting/codec.h"
#include "third_party/skia/include/core/SkImageInfo.h"

namespace flutter {

/// The minimal interface necessary for creating decoders that can be used for
/// single-frame image decoding with optional support for decoding into a
/// subscaled buffer.
///
/// See `getScaledDimensions` for details about how subpixel image decoding can
/// be supported.
class ImageGenerator {
public:
virtual ~ImageGenerator(){};

virtual const SkImageInfo& getInfo() const = 0;

virtual bool getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) const = 0;

/// Given a scale value, returns the closest image size that can be used for
/// efficiently decoding the image. If subpixel image decoding is not
/// supported by the codec, this method just returns the original image size.
virtual SkISize getScaledDimensions(float scale) = 0;
};

class BuiltinSkiaImageGenerator : public ImageGenerator {
public:
BuiltinSkiaImageGenerator(std::unique_ptr<SkImageGenerator> generator);

~BuiltinSkiaImageGenerator() = default;

const SkImageInfo& getInfo() const override;

bool getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) const override;

SkISize getScaledDimensions(float desiredScale) override;

static std::unique_ptr<ImageGenerator> makeFromGenerator(
std::unique_ptr<SkImageGenerator> generator);

private:
BuiltinSkiaImageGenerator() = delete;
std::unique_ptr<SkImageGenerator> generator_;
};

class BuiltinSkiaCodecImageGenerator : public ImageGenerator {
public:
BuiltinSkiaCodecImageGenerator(std::unique_ptr<SkCodec> codec);

BuiltinSkiaCodecImageGenerator(sk_sp<SkData> buffer);

~BuiltinSkiaCodecImageGenerator() = default;

const SkImageInfo& getInfo() const override;

bool getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) const override;

SkISize getScaledDimensions(float desiredScale) override;

static std::unique_ptr<ImageGenerator> makeFromData(sk_sp<SkData> data);

private:
BuiltinSkiaCodecImageGenerator() = delete;
std::unique_ptr<SkCodecImageGenerator> codec_generator_;
};

} // namespace flutter

#endif // FLUTTER_LIB_UI_PAINTING_IMAGE_GENERATOR_H_
68 changes: 68 additions & 0 deletions lib/ui/painting/image_generator_registry.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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.

#include <algorithm>

#include "flutter/lib/ui/painting/image_generator_registry.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/src/codec/SkCodecImageGenerator.h"
#ifdef OS_MACOSX
#include "third_party/skia/include/ports/SkImageGeneratorCG.h"
#elif OS_WIN
#include "third_party/skia/include/ports/SkImageGeneratorWIC.h"
#endif

namespace flutter {

ImageGeneratorRegistry::ImageGeneratorRegistry() : weak_factory_(this) {
add(
[](sk_sp<SkData> buffer) {
return BuiltinSkiaCodecImageGenerator::makeFromData(buffer);
},
0);

#ifdef OS_MACOSX
add(
[](sk_sp<SkData> buffer) {
auto generator = SkImageGeneratorCG::MakeFromEncodedCG(buffer);
return BuiltinSkiaImageGenerator::makeFromGenerator(
std::move(generator));
},
0);
#elif OS_WIN
add(
[](sk_sp<SkData> buffer) {
auto generator = SkImageGeneratorWIC::MakeFromEncodedWIC(buffer);
return BuiltinSkiaImageGenerator::makeFromGenerator(
std::move(generator));
},
0);
#endif
}

void ImageGeneratorRegistry::add(ImageGeneratorFactory factory,
int32_t priority) {
image_generator_factories_.push_back({factory, priority});
std::stable_sort(image_generator_factories_.begin(),
image_generator_factories_.end());
}

std::unique_ptr<ImageGenerator> ImageGeneratorRegistry::createCompatible(
sk_sp<SkData> buffer) {
for (auto& factory : image_generator_factories_) {
std::unique_ptr<ImageGenerator> result = factory.callback(buffer);
if (result) {
return result;
}
}
return nullptr;
}

fml::WeakPtr<ImageGeneratorRegistry> ImageGeneratorRegistry::GetWeakPtr()
const {
return weak_factory_.GetWeakPtr();
}

} // namespace flutter
55 changes: 55 additions & 0 deletions lib/ui/painting/image_generator_registry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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 <vector>

#include "flutter/fml/mapping.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/lib/ui/painting/image_generator.h"

namespace flutter {

/// 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:
using ImageGeneratorFactory =
std::function<std::unique_ptr<ImageGenerator>(sk_sp<SkData> buffer)>;

ImageGeneratorRegistry();

~ImageGeneratorRegistry() = default;

void add(ImageGeneratorFactory factory, int32_t priority);

/// Walks the list of image generator builders in descending priority order
/// until a compatible SkImageGenerator is able to be built. If no compatible
/// image generator could be produced, `std::unique_ptr(nullptr)` is returned.
std::unique_ptr<ImageGenerator> createCompatible(sk_sp<SkData> buffer);

fml::WeakPtr<ImageGeneratorRegistry> GetWeakPtr() const;

private:
struct PrioritizedFactory_ {
ImageGeneratorFactory callback;

int32_t priority;

// Order by descending priority.
inline bool operator<(const PrioritizedFactory_& other) const {
return priority > other.priority;
}
};
std::vector<PrioritizedFactory_> image_generator_factories_;
fml::WeakPtrFactory<ImageGeneratorRegistry> weak_factory_;
};

} // namespace flutter

#endif // FLUTTER_LIB_UI_PAINTING_IMAGE_DECODER_H_
Loading

0 comments on commit 2aeb496

Please sign in to comment.