Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
SkImageImageFilter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
14#include "include/core/SkRect.h"
24
25#include <optional>
26#include <utility>
27
28namespace {
29
30class SkImageImageFilter final : public SkImageFilter_Base {
31public:
32 SkImageImageFilter(sk_sp<SkImage> image,
33 const SkRect& srcRect,
34 const SkRect& dstRect,
36 : SkImageFilter_Base(nullptr, 0)
37 , fImage(std::move(image))
38 , fSrcRect(srcRect)
39 , fDstRect(dstRect)
40 , fSampling(sampling) {
41 // The dst rect should be non-empty
42 SkASSERT(fImage && !dstRect.isEmpty());
43 }
44
45 SkRect computeFastBounds(const SkRect&) const override { return SkRect(fDstRect); }
46
47protected:
48 void flatten(SkWriteBuffer&) const override;
49
50private:
52 SK_FLATTENABLE_HOOKS(SkImageImageFilter)
53
55
56 skif::FilterResult onFilterImage(const skif::Context&) const override;
57
59 const skif::Mapping& mapping,
60 const skif::LayerSpace<SkIRect>& desiredOutput,
61 std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
62
63 std::optional<skif::LayerSpace<SkIRect>> onGetOutputLayerBounds(
64 const skif::Mapping& mapping,
65 std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
66
67 sk_sp<SkImage> fImage;
68 // The src rect is relative to the image's contents, so is not technically in the parameter
69 // coordinate space that responds to the layer matrix (unlike fDstRect).
70 SkRect fSrcRect;
72 SkSamplingOptions fSampling;
73};
74
75} // end namespace
76
78 const SkRect& srcRect,
79 const SkRect& dstRect,
81 if (srcRect.isEmpty() || dstRect.isEmpty() || !image) {
82 // There is no content to draw, so the filter should produce transparent black
83 return SkImageFilters::Empty();
84 } else {
85 SkRect imageBounds = SkRect::Make(image->dimensions());
86 if (imageBounds.contains(srcRect)) {
87 // No change to srcRect and dstRect needed
88 return sk_sp<SkImageFilter>(new SkImageImageFilter(
89 std::move(image), srcRect, dstRect, sampling));
90 } else {
91 SkMatrix srcToDst = SkMatrix::RectToRect(srcRect, dstRect);
92 if (!imageBounds.intersect(srcRect)) {
93 // No overlap, so draw empty
94 return SkImageFilters::Empty();
95 }
96
97 // Adjust dstRect to match the updated src (which is stored in imageBounds)
98 SkRect mappedBounds = srcToDst.mapRect(imageBounds);
99 if (mappedBounds.isEmpty()) {
100 return SkImageFilters::Empty();
101 }
102 return sk_sp<SkImageFilter>(new SkImageImageFilter(
103 std::move(image), imageBounds, mappedBounds, sampling));
104 }
105 }
106}
107
109 SK_REGISTER_FLATTENABLE(SkImageImageFilter);
110 // TODO (michaelludwig) - Remove after grace period for SKPs to stop using old name
111 SkFlattenable::Register("SkImageSourceImpl", SkImageImageFilter::CreateProc);
112}
113
114sk_sp<SkFlattenable> SkImageImageFilter::CreateProc(SkReadBuffer& buffer) {
118 } else {
119 sampling = buffer.readSampling();
120 }
121
122 SkRect src, dst;
123 buffer.readRect(&src);
124 buffer.readRect(&dst);
125
126 sk_sp<SkImage> image(buffer.readImage());
127 if (!image) {
128 return nullptr;
129 }
130
131 return SkImageFilters::Image(std::move(image), src, dst, sampling);
132}
133
134void SkImageImageFilter::flatten(SkWriteBuffer& buffer) const {
135 buffer.writeSampling(fSampling);
136 buffer.writeRect(fSrcRect);
137 buffer.writeRect(SkRect(fDstRect));
138 buffer.writeImage(fImage.get());
139}
140
141///////////////////////////////////////////////////////////////////////////////////////////////////
142
143skif::FilterResult SkImageImageFilter::onFilterImage(const skif::Context& ctx) const {
144 return skif::FilterResult::MakeFromImage(ctx, fImage, fSrcRect, fDstRect, fSampling);
145}
146
147skif::LayerSpace<SkIRect> SkImageImageFilter::onGetInputLayerBounds(
148 const skif::Mapping&,
150 std::optional<skif::LayerSpace<SkIRect>>) const {
151 // This is a leaf filter, it requires no input and no further recursion
153}
154
155std::optional<skif::LayerSpace<SkIRect>> SkImageImageFilter::onGetOutputLayerBounds(
156 const skif::Mapping& mapping,
157 std::optional<skif::LayerSpace<SkIRect>>) const {
158 // The output is the transformed bounds of the image.
159 return mapping.paramToLayer(fDstRect).roundOut();
160}
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SK_FLATTENABLE_HOOKS(type)
#define SK_REGISTER_FLATTENABLE(type)
void SkRegisterImageImageFilterFlattenable()
@ kLinear_SkMediumAs
static void Register(const char name[], Factory)
virtual skif::LayerSpace< SkIRect > onGetInputLayerBounds(const skif::Mapping &mapping, const skif::LayerSpace< SkIRect > &desiredOutput, std::optional< skif::LayerSpace< SkIRect > > contentBounds) const =0
void flatten(SkWriteBuffer &) const override
virtual std::optional< skif::LayerSpace< SkIRect > > onGetOutputLayerBounds(const skif::Mapping &mapping, std::optional< skif::LayerSpace< SkIRect > > contentBounds) const =0
virtual skif::FilterResult onFilterImage(const skif::Context &context) const =0
virtual MatrixCapability onGetCTMCapability() const
virtual SkRect computeFastBounds(const SkRect &bounds) const
static sk_sp< SkImageFilter > Empty()
static sk_sp< SkImageFilter > Image(sk_sp< SkImage > image, const SkRect &srcRect, const SkRect &dstRect, const SkSamplingOptions &sampling)
SkISize dimensions() const
Definition: SkImage.h:297
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition: SkMatrix.h:157
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
@ kImageFilterImageSampling_Version
static SkSamplingOptions FromFQ(SkLegacyFQ fq, SkMediumAs behavior=kNearest_SkMediumAs)
static FilterResult MakeFromImage(const Context &ctx, sk_sp< SkImage > image, SkRect srcRect, ParameterSpace< SkRect > dstRect, const SkSamplingOptions &sampling)
LayerSpace< T > paramToLayer(const ParameterSpace< T > &paramGeometry) const
sk_sp< const SkImage > image
Definition: SkRecords.h:269
SkSamplingOptions sampling
Definition: SkRecords.h:337
SK_API sk_sp< SkShader > Empty()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
dst
Definition: cp.py:12
Definition: ref_ptr.h:256
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
bool intersect(const SkRect &r)
Definition: SkRect.cpp:114
bool contains(SkScalar x, SkScalar y) const
Definition: extension.cpp:19
bool isEmpty() const
Definition: SkRect.h:693