• 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/core/SkCanvas.h"
9 #include "include/core/SkPicture.h"
10 #include "include/effects/SkImageFilters.h"
11 #include "src/core/SkImageFilter_Base.h"
12 #include "src/core/SkPicturePriv.h"
13 #include "src/core/SkReadBuffer.h"
14 #include "src/core/SkSpecialImage.h"
15 #include "src/core/SkSpecialSurface.h"
16 #include "src/core/SkValidationUtils.h"
17 #include "src/core/SkWriteBuffer.h"
18 
19 namespace {
20 
21 class SkPictureImageFilter final : public SkImageFilter_Base {
22 public:
SkPictureImageFilter(sk_sp<SkPicture> picture,const SkRect & cropRect)23     SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect)
24             : INHERITED(nullptr, 0, nullptr)
25             , fPicture(std::move(picture))
26             , fCropRect(cropRect) {}
27 
28 protected:
29     /*  Constructs an SkPictureImageFilter object from an SkReadBuffer.
30      *  Note: If the SkPictureImageFilter object construction requires bitmap
31      *  decoding, the decoder must be set on the SkReadBuffer parameter by calling
32      *  SkReadBuffer::setBitmapDecoder() before calling this constructor.
33      *  @param SkReadBuffer Serialized picture data.
34      */
35     void flatten(SkWriteBuffer&) const override;
36     sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const override;
37 
38     SkRect computeFastBounds(const SkRect& src) const override;
39     SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,
40                                MapDirection, const SkIRect* inputRect) const override;
41 
42 private:
43     friend void ::SkRegisterPictureImageFilterFlattenable();
44     SK_FLATTENABLE_HOOKS(SkPictureImageFilter)
45 
46     sk_sp<SkPicture>    fPicture;
47     SkRect              fCropRect;
48 
49     using INHERITED = SkImageFilter_Base;
50 };
51 
52 } // end namespace
53 
Picture(sk_sp<SkPicture> pic,const SkRect & targetRect)54 sk_sp<SkImageFilter> SkImageFilters::Picture(sk_sp<SkPicture> pic, const SkRect& targetRect) {
55     return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(pic), targetRect));
56 }
57 
SkRegisterPictureImageFilterFlattenable()58 void SkRegisterPictureImageFilterFlattenable() {
59     SK_REGISTER_FLATTENABLE(SkPictureImageFilter);
60     // TODO (michaelludwig) - Remove after grace period for SKPs to stop using old name
61     SkFlattenable::Register("SkPictureImageFilterImpl", SkPictureImageFilter::CreateProc);
62 }
63 
CreateProc(SkReadBuffer & buffer)64 sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
65     sk_sp<SkPicture> picture;
66     SkRect cropRect;
67 
68     if (buffer.readBool()) {
69         picture = SkPicturePriv::MakeFromBuffer(buffer);
70     }
71     buffer.readRect(&cropRect);
72 
73     return SkImageFilters::Picture(std::move(picture), cropRect);
74 }
75 
flatten(SkWriteBuffer & buffer) const76 void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
77     bool hasPicture = (fPicture != nullptr);
78     buffer.writeBool(hasPicture);
79     if (hasPicture) {
80         SkPicturePriv::Flatten(fPicture, buffer);
81     }
82     buffer.writeRect(fCropRect);
83 }
84 
85 ///////////////////////////////////////////////////////////////////////////////////////////////////
86 
onFilterImage(const Context & ctx,SkIPoint * offset) const87 sk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(const Context& ctx,
88                                                           SkIPoint* offset) const {
89     if (!fPicture) {
90         return nullptr;
91     }
92 
93     SkRect floatBounds;
94     ctx.ctm().mapRect(&floatBounds, fCropRect);
95     SkIRect bounds = floatBounds.roundOut();
96     if (!bounds.intersect(ctx.clipBounds())) {
97         return nullptr;
98     }
99 
100     SkASSERT(!bounds.isEmpty());
101 
102     // Given the standard usage of the picture image filter (i.e., to render content at a fixed
103     // resolution that, most likely, differs from the screen's) disable LCD text by removing any
104     // knowledge of the pixel geometry.
105     SkSurfaceProps props = ctx.surfaceProps().cloneWithPixelGeometry(kUnknown_SkPixelGeometry);
106     sk_sp<SkSpecialSurface> surf(ctx.makeSurface(bounds.size(), &props));
107     if (!surf) {
108         return nullptr;
109     }
110 
111     SkASSERT(kUnknown_SkPixelGeometry == surf->props().pixelGeometry());
112 
113     SkCanvas* canvas = surf->getCanvas();
114     SkASSERT(canvas);
115     canvas->clear(0x0);
116 
117     canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
118     canvas->concat(ctx.ctm());
119     canvas->drawPicture(fPicture);
120 
121     offset->fX = bounds.fLeft;
122     offset->fY = bounds.fTop;
123     return surf->makeImageSnapshot();
124 }
125 
computeFastBounds(const SkRect & src) const126 SkRect SkPictureImageFilter::computeFastBounds(const SkRect& src) const {
127     return fCropRect;
128 }
129 
onFilterNodeBounds(const SkIRect & src,const SkMatrix & ctm,MapDirection direction,const SkIRect * inputRect) const130 SkIRect SkPictureImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
131                                                  MapDirection direction,
132                                                  const SkIRect* inputRect) const {
133     if (kReverse_MapDirection == direction) {
134         return INHERITED::onFilterNodeBounds(src, ctm, direction, inputRect);
135     }
136 
137     SkRect dstRect = fCropRect;
138     ctm.mapRect(&dstRect);
139     return dstRect.roundOut();
140 }
141