aboutsummaryrefslogtreecommitdiff
path: root/src/core/SkSpecialImage.h
blob: 89c82bbb9115418537521fe0f9cfe2177cfe9baf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file
 */

#ifndef SkSpecialImage_DEFINED
#define SkSpecialImage_DEFINED

#include "include/core/SkImageInfo.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurfaceProps.h"

#include <cstddef>
#include <cstdint>

class GrRecordingContext;
class SkBitmap;
class SkCanvas;
class SkColorSpace;
class SkImage;
class SkMatrix;
class SkPaint;
class SkShader;
enum SkAlphaType : int;
enum SkColorType : int;
enum class SkTileMode;

enum {
    kNeedNewImageUniqueID_SpecialImage = 0
};

/**
 * This is a restricted form of SkImage solely intended for internal use. It
 * differs from SkImage in that:
 *      - it can only be backed by raster or gpu (no generators)
 *      - it can be backed by a GrTextureProxy larger than its nominal bounds
 *      - it can't be drawn tiled
 *      - it can't be drawn with MIPMAPs
 * It is similar to SkImage in that it abstracts how the pixels are stored/represented.
 *
 * Note: the contents of the backing storage outside of the subset rect are undefined.
 */
class SkSpecialImage : public SkRefCnt {
public:
    typedef void* ReleaseContext;
    typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);

    const SkSurfaceProps& props() const { return fProps; }

    int width() const { return fSubset.width(); }
    int height() const { return fSubset.height(); }
    SkISize dimensions() const { return { this->width(), this->height() }; }
    const SkIRect& subset() const { return fSubset; }

    uint32_t uniqueID() const { return fUniqueID; }

    virtual size_t getSize() const = 0;

    const SkColorInfo& colorInfo() const { return fColorInfo; }
    SkAlphaType alphaType() const { return fColorInfo.alphaType(); }
    SkColorType colorType() const { return fColorInfo.colorType(); }
    SkColorSpace* getColorSpace() const { return fColorInfo.colorSpace(); }

    /**
     *  Draw this SpecialImage into the canvas, automatically taking into account the image's subset
     */
    void draw(SkCanvas* canvas,
              SkScalar x, SkScalar y,
              const SkSamplingOptions& sampling,
              const SkPaint* paint,
              bool strict = true) const;
    void draw(SkCanvas* canvas, SkScalar x, SkScalar y) const {
        this->draw(canvas, x, y, SkSamplingOptions(), nullptr);
    }

    /**
     * Extract a subset of this special image and return it as a special image.
     * It may or may not point to the same backing memory. The input 'subset' is relative to the
     * special image's content rect.
     */
    sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const {
        SkIRect absolute = subset.makeOffset(this->subset().topLeft());
        return this->onMakeSubset(absolute);
    }

    /**
     * Create an SkImage view of the contents of this special image, pointing to the same
     * underlying memory.
     *
     * TODO: If SkImages::MakeFiltered were to return an SkShader that accounted for the subset
     * constraint and offset, then this could move to a private virtual for use in draw() and
     * asShader().
     */
    virtual sk_sp<SkImage> asImage() const = 0;

    /**
     * Create an SkShader that samples the contents of this special image, applying tile mode for
     * any sample that falls outside its internal subset.
     */
    sk_sp<SkShader> asShader(SkTileMode, const SkSamplingOptions&, const SkMatrix& lm) const;
    sk_sp<SkShader> asShader(const SkSamplingOptions& sampling) const;
    sk_sp<SkShader> asShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;

    /**
     *  If the SpecialImage is backed by a gpu texture, return true.
     */
    virtual bool isGaneshBacked() const { return false; }
    virtual bool isGraphiteBacked() const { return false; }

    /**
     * Return the GrRecordingContext if the SkSpecialImage is GrTexture-backed
     */
    virtual GrRecordingContext* getContext() const { return nullptr; }

protected:
    SkSpecialImage(const SkIRect& subset,
                   uint32_t uniqueID,
                   const SkColorInfo&,
                   const SkSurfaceProps&);

    // This subset is relative to the backing store's coordinate frame, it has already been mapped
    // from the content rect by the non-virtual makeSubset().
    virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;

    virtual sk_sp<SkShader> onAsShader(SkTileMode,
                                       const SkSamplingOptions&,
                                       const SkMatrix&) const = 0;

private:
    const SkIRect        fSubset;
    const uint32_t       fUniqueID;
    const SkColorInfo    fColorInfo;
    const SkSurfaceProps fProps;
};

namespace SkSpecialImages {

sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset, sk_sp<SkImage>, const SkSurfaceProps&);
sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset, const SkBitmap&, const SkSurfaceProps&);
sk_sp<SkSpecialImage> CopyFromRaster(const SkIRect& subset, const SkBitmap&, const SkSurfaceProps&);

bool AsBitmap(const SkSpecialImage* img, SkBitmap*);

}  // namespace SkSpecialImages

#endif // SkSpecialImage_DEFINED