• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 
8 #include "include/effects/SkImageFilters.h"
9 
10 #include "include/core/SkFlattenable.h"
11 #include "include/core/SkImageFilter.h"
12 #include "include/core/SkPicture.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkTypes.h"
16 #include "include/private/base/SkTo.h"
17 #include "src/core/SkImageFilterTypes.h"
18 #include "src/core/SkImageFilter_Base.h"
19 #include "src/core/SkPicturePriv.h"
20 #include "src/core/SkReadBuffer.h"
21 #include "src/core/SkWriteBuffer.h"
22 
23 #include <optional>
24 #include <utility>
25 
26 namespace {
27 
28 class SkPictureImageFilter final : public SkImageFilter_Base {
29 public:
SkPictureImageFilter(sk_sp<SkPicture> picture,const SkRect & cullRect)30     SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cullRect)
31             : SkImageFilter_Base(nullptr, 0)
32             , fPicture(std::move(picture))
33             , fCullRect(cullRect) {
34         // The external cullrect should already have been intersected with the internal cull rect
35         SkASSERT(fPicture && fPicture->cullRect().contains(cullRect));
36     }
37 
computeFastBounds(const SkRect &) const38     SkRect computeFastBounds(const SkRect&) const override { return SkRect(fCullRect); }
39 
40 protected:
41     void flatten(SkWriteBuffer&) const override;
42 
43 private:
44     friend void ::SkRegisterPictureImageFilterFlattenable();
SK_FLATTENABLE_HOOKS(SkPictureImageFilter)45     SK_FLATTENABLE_HOOKS(SkPictureImageFilter)
46 
47     MatrixCapability onGetCTMCapability() const override { return MatrixCapability::kComplex; }
48 
49     skif::FilterResult onFilterImage(const skif::Context& ctx) const override;
50 
51     skif::LayerSpace<SkIRect> onGetInputLayerBounds(
52             const skif::Mapping& mapping,
53             const skif::LayerSpace<SkIRect>& desiredOutput,
54             std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
55 
56     std::optional<skif::LayerSpace<SkIRect>> onGetOutputLayerBounds(
57             const skif::Mapping& mapping,
58             std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
59 
60     sk_sp<SkPicture> fPicture;
61     skif::ParameterSpace<SkRect> fCullRect;
62 };
63 
64 } // end namespace
65 
Picture(sk_sp<SkPicture> pic,const SkRect & targetRect)66 sk_sp<SkImageFilter> SkImageFilters::Picture(sk_sp<SkPicture> pic, const SkRect& targetRect) {
67     if (pic) {
68         SkRect cullRect = pic->cullRect();
69         if (cullRect.intersect(targetRect)) {
70             return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(pic), cullRect));
71         }
72     }
73     return SkImageFilters::Empty();
74 }
75 
SkRegisterPictureImageFilterFlattenable()76 void SkRegisterPictureImageFilterFlattenable() {
77     SK_REGISTER_FLATTENABLE(SkPictureImageFilter);
78     // TODO (michaelludwig) - Remove after grace period for SKPs to stop using old name
79     SkFlattenable::Register("SkPictureImageFilterImpl", SkPictureImageFilter::CreateProc);
80 }
81 
CreateProc(SkReadBuffer & buffer)82 sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
83     sk_sp<SkPicture> picture;
84     if (buffer.readBool()) {
85         picture = SkPicturePriv::MakeFromBuffer(buffer);
86     }
87 
88     SkRect cullRect;
89     buffer.readRect(&cullRect);
90     return SkImageFilters::Picture(std::move(picture), cullRect);
91 }
92 
flatten(SkWriteBuffer & buffer) const93 void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
94     buffer.writeBool(SkToBool(fPicture));
95     if (fPicture) {
96         SkPicturePriv::Flatten(fPicture, buffer);
97     }
98     buffer.writeRect(SkRect(fCullRect));
99 }
100 
101 ///////////////////////////////////////////////////////////////////////////////////////////////////
102 
onFilterImage(const skif::Context & ctx) const103 skif::FilterResult SkPictureImageFilter::onFilterImage(const skif::Context& ctx) const {
104     return skif::FilterResult::MakeFromPicture(ctx, fPicture, fCullRect);
105 }
106 
onGetInputLayerBounds(const skif::Mapping &,const skif::LayerSpace<SkIRect> &,std::optional<skif::LayerSpace<SkIRect>>) const107 skif::LayerSpace<SkIRect> SkPictureImageFilter::onGetInputLayerBounds(
108         const skif::Mapping&,
109         const skif::LayerSpace<SkIRect>&,
110         std::optional<skif::LayerSpace<SkIRect>>) const {
111     // This is a leaf filter, it requires no input and no further recursion
112     return skif::LayerSpace<SkIRect>::Empty();
113 }
114 
onGetOutputLayerBounds(const skif::Mapping & mapping,std::optional<skif::LayerSpace<SkIRect>>) const115 std::optional<skif::LayerSpace<SkIRect>> SkPictureImageFilter::onGetOutputLayerBounds(
116         const skif::Mapping& mapping,
117         std::optional<skif::LayerSpace<SkIRect>>) const {
118     // The output is the transformed bounds of the picture.
119     return mapping.paramToLayer(fCullRect).roundOut();
120 }
121