Line data Source code
1 : /*
2 : * Copyright 2006 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 : #ifndef SkBlitter_DEFINED
9 : #define SkBlitter_DEFINED
10 :
11 : #include "SkAutoMalloc.h"
12 : #include "SkBitmapProcShader.h"
13 : #include "SkColor.h"
14 : #include "SkRect.h"
15 : #include "SkRegion.h"
16 : #include "SkShader.h"
17 :
18 : class SkArenaAlloc;
19 : class SkMatrix;
20 : class SkPaint;
21 : class SkPixmap;
22 : struct SkMask;
23 :
24 : /** SkBlitter and its subclasses are responsible for actually writing pixels
25 : into memory. Besides efficiency, they handle clipping and antialiasing.
26 : A SkBlitter subclass contains all the context needed to generate pixels
27 : for the destination and how src/generated pixels map to the destination.
28 : The coordinates passed to the blitX calls are in destination pixel space.
29 : */
30 2033 : class SkBlitter {
31 : public:
32 : virtual ~SkBlitter();
33 :
34 : /// Blit a horizontal run of one or more pixels.
35 : virtual void blitH(int x, int y, int width) = 0;
36 :
37 : /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
38 : /// zero-terminated run-length encoding of spans of constant alpha values.
39 : /// The runs[] and antialias[] work together to represent long runs of pixels with the same
40 : /// alphas. The runs[] contains the number of pixels with the same alpha, and antialias[]
41 : /// contain the coverage value for that number of pixels. The runs[] (and antialias[]) are
42 : /// encoded in a clever way. The runs array is zero terminated, and has enough entries for
43 : /// each pixel plus one, in most cases some of the entries will not contain valid data. An entry
44 : /// in the runs array contains the number of pixels (np) that have the same alpha value. The
45 : /// next np value is found np entries away. For example, if runs[0] = 7, then the next valid
46 : /// entry will by at runs[7]. The runs array and antialias[] are coupled by index. So, if the
47 : /// np entry is at runs[45] = 12 then the alpha value can be found at antialias[45] = 0x88.
48 : /// This would mean to use an alpha value of 0x88 for the next 12 pixels starting at pixel 45.
49 : virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) = 0;
50 :
51 : /// Blit a vertical run of pixels with a constant alpha value.
52 : virtual void blitV(int x, int y, int height, SkAlpha alpha);
53 :
54 : /// Blit a solid rectangle one or more pixels wide.
55 : virtual void blitRect(int x, int y, int width, int height);
56 :
57 : /** Blit a rectangle with one alpha-blended column on the left,
58 : width (zero or more) opaque pixels, and one alpha-blended column
59 : on the right.
60 : The result will always be at least two pixels wide.
61 : */
62 : virtual void blitAntiRect(int x, int y, int width, int height,
63 : SkAlpha leftAlpha, SkAlpha rightAlpha);
64 :
65 : /// Blit a pattern of pixels defined by a rectangle-clipped mask;
66 : /// typically used for text.
67 : virtual void blitMask(const SkMask&, const SkIRect& clip);
68 :
69 : /** If the blitter just sets a single value for each pixel, return the
70 : bitmap it draws into, and assign value. If not, return nullptr and ignore
71 : the value parameter.
72 : */
73 : virtual const SkPixmap* justAnOpaqueColor(uint32_t* value);
74 :
75 : // (x, y), (x + 1, y)
76 294 : virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
77 : int16_t runs[3];
78 : uint8_t aa[2];
79 :
80 294 : runs[0] = 1;
81 294 : runs[1] = 1;
82 294 : runs[2] = 0;
83 294 : aa[0] = SkToU8(a0);
84 294 : aa[1] = SkToU8(a1);
85 294 : this->blitAntiH(x, y, aa, runs);
86 294 : }
87 :
88 : // (x, y), (x, y + 1)
89 0 : virtual void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
90 : int16_t runs[2];
91 : uint8_t aa[1];
92 :
93 0 : runs[0] = 1;
94 0 : runs[1] = 0;
95 0 : aa[0] = SkToU8(a0);
96 0 : this->blitAntiH(x, y, aa, runs);
97 : // reset in case the clipping blitter modified runs
98 0 : runs[0] = 1;
99 0 : runs[1] = 0;
100 0 : aa[0] = SkToU8(a1);
101 0 : this->blitAntiH(x, y + 1, aa, runs);
102 0 : }
103 :
104 : /**
105 : * Special method just to identify the null blitter, which is returned
106 : * from Choose() if the request cannot be fulfilled. Default impl
107 : * returns false.
108 : */
109 : virtual bool isNullBlitter() const;
110 :
111 : /**
112 : * Special methods for blitters that can blit more than one row at a time.
113 : * This function returns the number of rows that this blitter could optimally
114 : * process at a time. It is still required to support blitting one scanline
115 : * at a time.
116 : */
117 190 : virtual int requestRowsPreserved() const { return 1; }
118 :
119 : /**
120 : * This function allocates memory for the blitter that the blitter then owns.
121 : * The memory can be used by the calling function at will, but it will be
122 : * released when the blitter's destructor is called. This function returns
123 : * nullptr if no persistent memory is needed by the blitter.
124 : */
125 190 : virtual void* allocBlitMemory(size_t sz) {
126 190 : return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink);
127 : }
128 :
129 : ///@name non-virtual helpers
130 : void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
131 : void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
132 : void blitRegion(const SkRegion& clip);
133 : ///@}
134 :
135 : /** @name Factories
136 : Return the correct blitter to use given the specified context.
137 : */
138 : static SkBlitter* Choose(const SkPixmap& dst,
139 : const SkMatrix& matrix,
140 : const SkPaint& paint,
141 : SkArenaAlloc*,
142 : bool drawCoverage = false);
143 :
144 : static SkBlitter* ChooseSprite(const SkPixmap& dst,
145 : const SkPaint&,
146 : const SkPixmap& src,
147 : int left, int top,
148 : SkArenaAlloc*);
149 : ///@}
150 :
151 : static SkShader::ContextRec::DstType PreferredShaderDest(const SkImageInfo&);
152 :
153 : protected:
154 : SkAutoMalloc fBlitMemory;
155 : };
156 :
157 : /** This blitter silently never draws anything.
158 : */
159 0 : class SkNullBlitter : public SkBlitter {
160 : public:
161 : void blitH(int x, int y, int width) override;
162 : void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
163 : void blitV(int x, int y, int height, SkAlpha alpha) override;
164 : void blitRect(int x, int y, int width, int height) override;
165 : void blitMask(const SkMask&, const SkIRect& clip) override;
166 : const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
167 : bool isNullBlitter() const override;
168 : };
169 :
170 : /** Wraps another (real) blitter, and ensures that the real blitter is only
171 : called with coordinates that have been clipped by the specified clipRect.
172 : This means the caller need not perform the clipping ahead of time.
173 : */
174 452 : class SkRectClipBlitter : public SkBlitter {
175 : public:
176 26 : void init(SkBlitter* blitter, const SkIRect& clipRect) {
177 26 : SkASSERT(!clipRect.isEmpty());
178 26 : fBlitter = blitter;
179 26 : fClipRect = clipRect;
180 26 : }
181 :
182 : void blitH(int x, int y, int width) override;
183 : void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
184 : void blitV(int x, int y, int height, SkAlpha alpha) override;
185 : void blitRect(int x, int y, int width, int height) override;
186 : virtual void blitAntiRect(int x, int y, int width, int height,
187 : SkAlpha leftAlpha, SkAlpha rightAlpha) override;
188 : void blitMask(const SkMask&, const SkIRect& clip) override;
189 : const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
190 :
191 25 : int requestRowsPreserved() const override {
192 25 : return fBlitter->requestRowsPreserved();
193 : }
194 :
195 25 : void* allocBlitMemory(size_t sz) override {
196 25 : return fBlitter->allocBlitMemory(sz);
197 : }
198 :
199 : private:
200 : SkBlitter* fBlitter;
201 : SkIRect fClipRect;
202 : };
203 :
204 : /** Wraps another (real) blitter, and ensures that the real blitter is only
205 : called with coordinates that have been clipped by the specified clipRgn.
206 : This means the caller need not perform the clipping ahead of time.
207 : */
208 452 : class SkRgnClipBlitter : public SkBlitter {
209 : public:
210 0 : void init(SkBlitter* blitter, const SkRegion* clipRgn) {
211 0 : SkASSERT(clipRgn && !clipRgn->isEmpty());
212 0 : fBlitter = blitter;
213 0 : fRgn = clipRgn;
214 0 : }
215 :
216 : void blitH(int x, int y, int width) override;
217 : void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
218 : void blitV(int x, int y, int height, SkAlpha alpha) override;
219 : void blitRect(int x, int y, int width, int height) override;
220 : void blitAntiRect(int x, int y, int width, int height,
221 : SkAlpha leftAlpha, SkAlpha rightAlpha) override;
222 : void blitMask(const SkMask&, const SkIRect& clip) override;
223 : const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
224 :
225 0 : int requestRowsPreserved() const override {
226 0 : return fBlitter->requestRowsPreserved();
227 : }
228 :
229 0 : void* allocBlitMemory(size_t sz) override {
230 0 : return fBlitter->allocBlitMemory(sz);
231 : }
232 :
233 : private:
234 : SkBlitter* fBlitter;
235 : const SkRegion* fRgn;
236 : };
237 :
238 : #ifdef SK_DEBUG
239 452 : class SkRectClipCheckBlitter : public SkBlitter {
240 : public:
241 200 : void init(SkBlitter* blitter, const SkIRect& clipRect) {
242 200 : SkASSERT(blitter);
243 200 : SkASSERT(!clipRect.isEmpty());
244 200 : fBlitter = blitter;
245 200 : fClipRect = clipRect;
246 200 : }
247 :
248 : void blitH(int x, int y, int width) override;
249 : void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
250 : void blitV(int x, int y, int height, SkAlpha alpha) override;
251 : void blitRect(int x, int y, int width, int height) override;
252 : void blitAntiRect(int x, int y, int width, int height,
253 : SkAlpha leftAlpha, SkAlpha rightAlpha) override;
254 : void blitMask(const SkMask&, const SkIRect& clip) override;
255 : const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
256 : void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
257 : void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
258 :
259 165 : int requestRowsPreserved() const override {
260 165 : return fBlitter->requestRowsPreserved();
261 : }
262 :
263 165 : void* allocBlitMemory(size_t sz) override {
264 165 : return fBlitter->allocBlitMemory(sz);
265 : }
266 :
267 : private:
268 : SkBlitter* fBlitter;
269 : SkIRect fClipRect;
270 : };
271 : #endif
272 :
273 : /** Factory to set up the appropriate most-efficient wrapper blitter
274 : to apply a clip. Returns a pointer to a member, so lifetime must
275 : be managed carefully.
276 : */
277 0 : class SkBlitterClipper {
278 : public:
279 : SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip,
280 : const SkIRect* bounds = nullptr);
281 :
282 : private:
283 : SkNullBlitter fNullBlitter;
284 : SkRectClipBlitter fRectBlitter;
285 : SkRgnClipBlitter fRgnBlitter;
286 : };
287 :
288 : #endif
|