Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkMergeImageFilter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 The Android Open Source Project
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
12#include "include/core/SkRect.h"
18
19#include <optional>
20#include <utility>
21
22namespace {
23
24class SkMergeImageFilter final : public SkImageFilter_Base {
25public:
26 SkMergeImageFilter(sk_sp<SkImageFilter>* const filters, int count)
27 : SkImageFilter_Base(filters, count) {
28 SkASSERT(filters && count > 0);
29 }
30
31 SkRect computeFastBounds(const SkRect&) const override;
32
33 // No need to override flatten() since there's no additional state to write over base class.
34
35private:
36 friend void ::SkRegisterMergeImageFilterFlattenable();
37 SK_FLATTENABLE_HOOKS(SkMergeImageFilter)
38
39 MatrixCapability onGetCTMCapability() const override { return MatrixCapability::kComplex; }
40
41 skif::FilterResult onFilterImage(const skif::Context& ctx) const override;
42
44 const skif::Mapping& mapping,
45 const skif::LayerSpace<SkIRect>& desiredOutput,
46 std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
47
48 std::optional<skif::LayerSpace<SkIRect>> onGetOutputLayerBounds(
49 const skif::Mapping& mapping,
50 std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
51};
52
53} // end namespace
54
56 const CropRect& cropRect) {
57 if (count <= 0 || !filters) {
58 return SkImageFilters::Empty();
59 }
60
61 sk_sp<SkImageFilter> filter{new SkMergeImageFilter(filters, count)};
62 if (cropRect) {
63 filter = SkImageFilters::Crop(*cropRect, std::move(filter));
64 }
65 return filter;
66}
67
69 SK_REGISTER_FLATTENABLE(SkMergeImageFilter);
70 // TODO (michaelludwig) - Remove after grace period for SKPs to stop using old name
71 SkFlattenable::Register("SkMergeImageFilterImpl", SkMergeImageFilter::CreateProc);
72}
73
74sk_sp<SkFlattenable> SkMergeImageFilter::CreateProc(SkReadBuffer& buffer) {
75 Common common;
76 if (!common.unflatten(buffer, -1) || !buffer.isValid()) {
77 return nullptr;
78 }
79 return SkImageFilters::Merge(common.inputs(), common.inputCount(), common.cropRect());
80}
81
82///////////////////////////////////////////////////////////////////////////////
83
84skif::FilterResult SkMergeImageFilter::onFilterImage(const skif::Context& ctx) const {
85 const int inputCount = this->countInputs();
87 for (int i = 0; i < inputCount; ++i) {
88 builder.add(this->getChildOutput(i, ctx));
89 }
90 return builder.merge();
91}
92
93skif::LayerSpace<SkIRect> SkMergeImageFilter::onGetInputLayerBounds(
94 const skif::Mapping& mapping,
95 const skif::LayerSpace<SkIRect>& desiredOutput,
96 std::optional<skif::LayerSpace<SkIRect>> contentBounds) const {
97 const int inputCount = this->countInputs();
98 // Union of all child input bounds so that one source image can provide for all of them.
100 inputCount,
101 [&](int i) {
102 return this->getChildInputLayerBounds(i, mapping, desiredOutput, contentBounds);
103 });
104}
105
106std::optional<skif::LayerSpace<SkIRect>> SkMergeImageFilter::onGetOutputLayerBounds(
107 const skif::Mapping& mapping,
108 std::optional<skif::LayerSpace<SkIRect>> contentBounds) const {
109 const int inputCount = this->countInputs();
110 // Merge is src-over of all child outputs, so covers their union but no more
111 bool childIsUnbounded = false;
112 auto childOutput = skif::LayerSpace<SkIRect>::Union(
113 inputCount,
114 [&](int i) {
115 auto o = this->getChildOutputLayerBounds(i, mapping, contentBounds);
116 if (o) {
117 return *o;
118 } else {
119 childIsUnbounded = true;
120 // This value doesn't matter once childIsUnbounded is true
122 }
123 });
124 if (childIsUnbounded) {
126 } else {
127 return childOutput;
128 }
129}
130
131SkRect SkMergeImageFilter::computeFastBounds(const SkRect& rect) const {
132 // The base computeFastBounds() implementation is the union of all fast bounds from children,
133 // or 'rect' if there are none. For merge, zero children means zero output so only call the
134 // base implementation when there are filters to merge.
135 // TODO: When the bounds update is complete, this default implementation may go away and we
136 // can move the union'ing logic here.
138}
int count
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SK_FLATTENABLE_HOOKS(type)
#define SK_REGISTER_FLATTENABLE(type)
void SkRegisterMergeImageFilterFlattenable()
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
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 > Merge(sk_sp< SkImageFilter > *const filters, int count, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Empty()
static sk_sp< SkImageFilter > Crop(const SkRect &rect, SkTileMode tileMode, sk_sp< SkImageFilter > input)
static const uint8_t buffer[]