blob: 0e5fedd7ebb648668d663c22987c775aaa7ca390 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#ifndef SkBlitter_DEFINED
9#define SkBlitter_DEFINED
10
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +000011#include "SkBitmapProcShader.h"
bungemand3ebb482015-08-05 13:57:49 -070012#include "SkColor.h"
13#include "SkRect.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkRegion.h"
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +000015#include "SkShader.h"
bungemand3ebb482015-08-05 13:57:49 -070016#include "SkTypes.h"
17
18class SkMatrix;
19class SkPaint;
20class SkPixmap;
21struct SkMask;
reed@android.com8a1c16f2008-12-17 15:59:43 +000022
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000023/** SkBlitter and its subclasses are responsible for actually writing pixels
24 into memory. Besides efficiency, they handle clipping and antialiasing.
herb3be72b02016-06-24 13:02:31 -070025 A SkBlitter subclass contains all the context needed to generate pixels
26 for the destination and how src/generated pixels map to the destination.
27 The coordinates passed to the blitX calls are in destination pixel space.
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000028*/
reed@android.com8a1c16f2008-12-17 15:59:43 +000029class SkBlitter {
30public:
31 virtual ~SkBlitter();
32
tomhudson@google.coma31ac732011-12-29 16:09:31 +000033 /// Blit a horizontal run of one or more pixels.
herb7df9e4a2016-06-10 13:01:27 -070034 virtual void blitH(int x, int y, int width) = 0;
35
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000036 /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
37 /// zero-terminated run-length encoding of spans of constant alpha values.
herb3be72b02016-06-24 13:02:31 -070038 /// The runs[] and antialias[] work together to represent long runs of pixels with the same
39 /// alphas. The runs[] contains the number of pixels with the same alpha, and antialias[]
40 /// contain the coverage value for that number of pixels. The runs[] (and antialias[]) are
41 /// encoded in a clever way. The runs array is zero terminated, and has enough entries for
42 /// each pixel plus one, in most cases some of the entries will not contain valid data. An entry
43 /// in the runs array contains the number of pixels (np) that have the same alpha value. The
44 /// next np value is found np entries away. For example, if runs[0] = 7, then the next valid
45 /// entry will by at runs[7]. The runs array and antialias[] are coupled by index. So, if the
46 /// np entry is at runs[45] = 12 then the alpha value can be found at antialias[45] = 0x88.
47 /// This would mean to use an alpha value of 0x88 for the next 12 pixels starting at pixel 45.
herb7df9e4a2016-06-10 13:01:27 -070048 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) = 0;
krajcevski2ec93fc2014-07-16 13:31:41 -070049
reed@google.coma89c77b2011-12-01 21:47:26 +000050 /// Blit a vertical run of pixels with a constant alpha value.
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 virtual void blitV(int x, int y, int height, SkAlpha alpha);
herb7df9e4a2016-06-10 13:01:27 -070052
tomhudson@google.coma31ac732011-12-29 16:09:31 +000053 /// Blit a solid rectangle one or more pixels wide.
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 virtual void blitRect(int x, int y, int width, int height);
herb7df9e4a2016-06-10 13:01:27 -070055
tomhudson@google.com49eac192011-12-27 13:59:20 +000056 /** Blit a rectangle with one alpha-blended column on the left,
tomhudson@google.com47143592011-12-28 17:58:07 +000057 width (zero or more) opaque pixels, and one alpha-blended column
58 on the right.
59 The result will always be at least two pixels wide.
tomhudson@google.com49eac192011-12-27 13:59:20 +000060 */
61 virtual void blitAntiRect(int x, int y, int width, int height,
62 SkAlpha leftAlpha, SkAlpha rightAlpha);
herb7df9e4a2016-06-10 13:01:27 -070063
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000064 /// Blit a pattern of pixels defined by a rectangle-clipped mask;
65 /// typically used for text.
reed@android.com8a1c16f2008-12-17 15:59:43 +000066 virtual void blitMask(const SkMask&, const SkIRect& clip);
67
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000068 /** If the blitter just sets a single value for each pixel, return the
halcanary96fcdcc2015-08-27 07:41:13 -070069 bitmap it draws into, and assign value. If not, return nullptr and ignore
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 the value parameter.
71 */
reed41e010c2015-06-09 12:16:53 -070072 virtual const SkPixmap* justAnOpaqueColor(uint32_t* value);
reed@android.com8a1c16f2008-12-17 15:59:43 +000073
reed793a6dd2015-04-15 07:51:15 -070074 // (x, y), (x + 1, y)
reeda8ec4802015-04-20 05:18:01 -070075 virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
reed793a6dd2015-04-15 07:51:15 -070076 int16_t runs[3];
77 uint8_t aa[2];
halcanary9d524f22016-03-29 09:03:52 -070078
reed793a6dd2015-04-15 07:51:15 -070079 runs[0] = 1;
80 runs[1] = 1;
81 runs[2] = 0;
82 aa[0] = SkToU8(a0);
83 aa[1] = SkToU8(a1);
84 this->blitAntiH(x, y, aa, runs);
85 }
86
87 // (x, y), (x, y + 1)
reeda8ec4802015-04-20 05:18:01 -070088 virtual void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
reed793a6dd2015-04-15 07:51:15 -070089 int16_t runs[2];
90 uint8_t aa[1];
halcanary9d524f22016-03-29 09:03:52 -070091
reed793a6dd2015-04-15 07:51:15 -070092 runs[0] = 1;
93 runs[1] = 0;
94 aa[0] = SkToU8(a0);
95 this->blitAntiH(x, y, aa, runs);
96 // reset in case the clipping blitter modified runs
97 runs[0] = 1;
98 runs[1] = 0;
99 aa[0] = SkToU8(a1);
100 this->blitAntiH(x, y + 1, aa, runs);
101 }
halcanary9d524f22016-03-29 09:03:52 -0700102
reed@google.comea033602012-12-14 13:13:55 +0000103 /**
104 * Special method just to identify the null blitter, which is returned
105 * from Choose() if the request cannot be fulfilled. Default impl
106 * returns false.
107 */
108 virtual bool isNullBlitter() const;
109
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000110 /**
111 * Special methods for SkShaderBlitter. On all other classes this is a no-op.
112 */
commit-bot@chromium.org80116dc2014-05-06 17:16:03 +0000113 virtual bool resetShaderContext(const SkShader::ContextRec&);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000114 virtual SkShader::Context* getShaderContext() const;
115
krajcevski2ec93fc2014-07-16 13:31:41 -0700116 /**
117 * Special methods for blitters that can blit more than one row at a time.
118 * This function returns the number of rows that this blitter could optimally
119 * process at a time. It is still required to support blitting one scanline
120 * at a time.
121 */
122 virtual int requestRowsPreserved() const { return 1; }
123
krajcevski75f88512014-07-21 09:54:23 -0700124 /**
125 * This function allocates memory for the blitter that the blitter then owns.
126 * The memory can be used by the calling function at will, but it will be
127 * released when the blitter's destructor is called. This function returns
halcanary96fcdcc2015-08-27 07:41:13 -0700128 * nullptr if no persistent memory is needed by the blitter.
krajcevski75f88512014-07-21 09:54:23 -0700129 */
130 virtual void* allocBlitMemory(size_t sz) {
131 return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink);
132 }
133
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000134 ///@name non-virtual helpers
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135 void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
136 void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
137 void blitRegion(const SkRegion& clip);
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000138 ///@}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000140 /** @name Factories
141 Return the correct blitter to use given the specified context.
142 */
reed41e010c2015-06-09 12:16:53 -0700143 static SkBlitter* Choose(const SkPixmap& dst,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 const SkMatrix& matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 const SkPaint& paint,
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000146 SkTBlitterAllocator*,
reed@google.com126f7f52013-11-07 16:06:53 +0000147 bool drawCoverage = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148
reedcb674142015-06-05 06:58:22 -0700149 static SkBlitter* ChooseSprite(const SkPixmap& dst,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150 const SkPaint&,
reedc240e712015-05-23 12:26:41 -0700151 const SkPixmap& src,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152 int left, int top,
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000153 SkTBlitterAllocator*);
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000154 ///@}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155
fmalitad0c4e092016-02-22 17:19:04 -0800156 static SkShader::ContextRec::DstType PreferredShaderDest(const SkImageInfo&);
157
krajcevski75f88512014-07-21 09:54:23 -0700158protected:
krajcevski75f88512014-07-21 09:54:23 -0700159 SkAutoMalloc fBlitMemory;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160};
161
162/** This blitter silently never draws anything.
163*/
164class SkNullBlitter : public SkBlitter {
165public:
mtklein36352bf2015-03-25 18:17:31 -0700166 void blitH(int x, int y, int width) override;
reed3dfd1332015-06-25 14:26:11 -0700167 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
mtklein36352bf2015-03-25 18:17:31 -0700168 void blitV(int x, int y, int height, SkAlpha alpha) override;
169 void blitRect(int x, int y, int width, int height) override;
170 void blitMask(const SkMask&, const SkIRect& clip) override;
reed41e010c2015-06-09 12:16:53 -0700171 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
mtklein36352bf2015-03-25 18:17:31 -0700172 bool isNullBlitter() const override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173};
174
175/** Wraps another (real) blitter, and ensures that the real blitter is only
176 called with coordinates that have been clipped by the specified clipRect.
177 This means the caller need not perform the clipping ahead of time.
178*/
179class SkRectClipBlitter : public SkBlitter {
180public:
181 void init(SkBlitter* blitter, const SkIRect& clipRect) {
182 SkASSERT(!clipRect.isEmpty());
183 fBlitter = blitter;
184 fClipRect = clipRect;
185 }
186
mtklein36352bf2015-03-25 18:17:31 -0700187 void blitH(int x, int y, int width) override;
reed3dfd1332015-06-25 14:26:11 -0700188 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
mtklein36352bf2015-03-25 18:17:31 -0700189 void blitV(int x, int y, int height, SkAlpha alpha) override;
190 void blitRect(int x, int y, int width, int height) override;
tomhudson@google.com49eac192011-12-27 13:59:20 +0000191 virtual void blitAntiRect(int x, int y, int width, int height,
mtklein36352bf2015-03-25 18:17:31 -0700192 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
193 void blitMask(const SkMask&, const SkIRect& clip) override;
reed41e010c2015-06-09 12:16:53 -0700194 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195
mtklein36352bf2015-03-25 18:17:31 -0700196 int requestRowsPreserved() const override {
krajcevskifdd7d2b2014-07-29 07:21:41 -0700197 return fBlitter->requestRowsPreserved();
198 }
199
mtklein36352bf2015-03-25 18:17:31 -0700200 void* allocBlitMemory(size_t sz) override {
krajcevski75f88512014-07-21 09:54:23 -0700201 return fBlitter->allocBlitMemory(sz);
202 }
203
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204private:
205 SkBlitter* fBlitter;
206 SkIRect fClipRect;
207};
208
209/** Wraps another (real) blitter, and ensures that the real blitter is only
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000210 called with coordinates that have been clipped by the specified clipRgn.
211 This means the caller need not perform the clipping ahead of time.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212*/
213class SkRgnClipBlitter : public SkBlitter {
214public:
215 void init(SkBlitter* blitter, const SkRegion* clipRgn) {
216 SkASSERT(clipRgn && !clipRgn->isEmpty());
217 fBlitter = blitter;
218 fRgn = clipRgn;
219 }
220
mtklein36352bf2015-03-25 18:17:31 -0700221 void blitH(int x, int y, int width) override;
reed3dfd1332015-06-25 14:26:11 -0700222 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
mtklein36352bf2015-03-25 18:17:31 -0700223 void blitV(int x, int y, int height, SkAlpha alpha) override;
224 void blitRect(int x, int y, int width, int height) override;
reed3dfd1332015-06-25 14:26:11 -0700225 void blitAntiRect(int x, int y, int width, int height,
226 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
mtklein36352bf2015-03-25 18:17:31 -0700227 void blitMask(const SkMask&, const SkIRect& clip) override;
reed41e010c2015-06-09 12:16:53 -0700228 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229
mtklein36352bf2015-03-25 18:17:31 -0700230 int requestRowsPreserved() const override {
krajcevskifdd7d2b2014-07-29 07:21:41 -0700231 return fBlitter->requestRowsPreserved();
232 }
233
mtklein36352bf2015-03-25 18:17:31 -0700234 void* allocBlitMemory(size_t sz) override {
krajcevski75f88512014-07-21 09:54:23 -0700235 return fBlitter->allocBlitMemory(sz);
236 }
237
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238private:
239 SkBlitter* fBlitter;
240 const SkRegion* fRgn;
241};
242
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000243/** Factory to set up the appropriate most-efficient wrapper blitter
244 to apply a clip. Returns a pointer to a member, so lifetime must
245 be managed carefully.
246*/
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247class SkBlitterClipper {
248public:
249 SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip,
halcanary96fcdcc2015-08-27 07:41:13 -0700250 const SkIRect* bounds = nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251
252private:
253 SkNullBlitter fNullBlitter;
254 SkRectClipBlitter fRectBlitter;
255 SkRgnClipBlitter fRgnBlitter;
256};
257
258#endif