blob: baa9ccc39f878a171197808aa65c904c997e5170 [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.
25*/
reed@android.com8a1c16f2008-12-17 15:59:43 +000026class SkBlitter {
27public:
28 virtual ~SkBlitter();
29
tomhudson@google.coma31ac732011-12-29 16:09:31 +000030 /// Blit a horizontal run of one or more pixels.
reed@android.com8a1c16f2008-12-17 15:59:43 +000031 virtual void blitH(int x, int y, int width);
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000032 /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
33 /// zero-terminated run-length encoding of spans of constant alpha values.
34 virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
35 const int16_t runs[]);
krajcevski2ec93fc2014-07-16 13:31:41 -070036
reed@google.coma89c77b2011-12-01 21:47:26 +000037 /// Blit a vertical run of pixels with a constant alpha value.
reed@android.com8a1c16f2008-12-17 15:59:43 +000038 virtual void blitV(int x, int y, int height, SkAlpha alpha);
tomhudson@google.coma31ac732011-12-29 16:09:31 +000039 /// Blit a solid rectangle one or more pixels wide.
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 virtual void blitRect(int x, int y, int width, int height);
tomhudson@google.com49eac192011-12-27 13:59:20 +000041 /** Blit a rectangle with one alpha-blended column on the left,
tomhudson@google.com47143592011-12-28 17:58:07 +000042 width (zero or more) opaque pixels, and one alpha-blended column
43 on the right.
44 The result will always be at least two pixels wide.
tomhudson@google.com49eac192011-12-27 13:59:20 +000045 */
46 virtual void blitAntiRect(int x, int y, int width, int height,
47 SkAlpha leftAlpha, SkAlpha rightAlpha);
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000048 /// Blit a pattern of pixels defined by a rectangle-clipped mask;
49 /// typically used for text.
reed@android.com8a1c16f2008-12-17 15:59:43 +000050 virtual void blitMask(const SkMask&, const SkIRect& clip);
51
tomhudson@google.com05fffdc2011-12-01 20:41:24 +000052 /** If the blitter just sets a single value for each pixel, return the
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 bitmap it draws into, and assign value. If not, return NULL and ignore
54 the value parameter.
55 */
reed41e010c2015-06-09 12:16:53 -070056 virtual const SkPixmap* justAnOpaqueColor(uint32_t* value);
reed@android.com8a1c16f2008-12-17 15:59:43 +000057
reed793a6dd2015-04-15 07:51:15 -070058 // (x, y), (x + 1, y)
reeda8ec4802015-04-20 05:18:01 -070059 virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
reed793a6dd2015-04-15 07:51:15 -070060 int16_t runs[3];
61 uint8_t aa[2];
62
63 runs[0] = 1;
64 runs[1] = 1;
65 runs[2] = 0;
66 aa[0] = SkToU8(a0);
67 aa[1] = SkToU8(a1);
68 this->blitAntiH(x, y, aa, runs);
69 }
70
71 // (x, y), (x, y + 1)
reeda8ec4802015-04-20 05:18:01 -070072 virtual void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
reed793a6dd2015-04-15 07:51:15 -070073 int16_t runs[2];
74 uint8_t aa[1];
75
76 runs[0] = 1;
77 runs[1] = 0;
78 aa[0] = SkToU8(a0);
79 this->blitAntiH(x, y, aa, runs);
80 // reset in case the clipping blitter modified runs
81 runs[0] = 1;
82 runs[1] = 0;
83 aa[0] = SkToU8(a1);
84 this->blitAntiH(x, y + 1, aa, runs);
85 }
86
reed@google.comea033602012-12-14 13:13:55 +000087 /**
88 * Special method just to identify the null blitter, which is returned
89 * from Choose() if the request cannot be fulfilled. Default impl
90 * returns false.
91 */
92 virtual bool isNullBlitter() const;
93
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000094 /**
95 * Special methods for SkShaderBlitter. On all other classes this is a no-op.
96 */
commit-bot@chromium.org80116dc2014-05-06 17:16:03 +000097 virtual bool resetShaderContext(const SkShader::ContextRec&);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000098 virtual SkShader::Context* getShaderContext() const;
99
krajcevski2ec93fc2014-07-16 13:31:41 -0700100 /**
101 * Special methods for blitters that can blit more than one row at a time.
102 * This function returns the number of rows that this blitter could optimally
103 * process at a time. It is still required to support blitting one scanline
104 * at a time.
105 */
106 virtual int requestRowsPreserved() const { return 1; }
107
krajcevski75f88512014-07-21 09:54:23 -0700108 /**
109 * This function allocates memory for the blitter that the blitter then owns.
110 * The memory can be used by the calling function at will, but it will be
111 * released when the blitter's destructor is called. This function returns
112 * NULL if no persistent memory is needed by the blitter.
113 */
114 virtual void* allocBlitMemory(size_t sz) {
115 return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink);
116 }
117
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000118 ///@name non-virtual helpers
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119 void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
120 void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
121 void blitRegion(const SkRegion& clip);
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000122 ///@}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000124 /** @name Factories
125 Return the correct blitter to use given the specified context.
126 */
reed41e010c2015-06-09 12:16:53 -0700127 static SkBlitter* Choose(const SkPixmap& dst,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 const SkMatrix& matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 const SkPaint& paint,
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000130 SkTBlitterAllocator*,
reed@google.com126f7f52013-11-07 16:06:53 +0000131 bool drawCoverage = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132
reedcb674142015-06-05 06:58:22 -0700133 static SkBlitter* ChooseSprite(const SkPixmap& dst,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 const SkPaint&,
reedc240e712015-05-23 12:26:41 -0700135 const SkPixmap& src,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 int left, int top,
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000137 SkTBlitterAllocator*);
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000138 ///@}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
krajcevski75f88512014-07-21 09:54:23 -0700140protected:
krajcevski75f88512014-07-21 09:54:23 -0700141 SkAutoMalloc fBlitMemory;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142};
143
144/** This blitter silently never draws anything.
145*/
146class SkNullBlitter : public SkBlitter {
147public:
mtklein36352bf2015-03-25 18:17:31 -0700148 void blitH(int x, int y, int width) override;
reed3dfd1332015-06-25 14:26:11 -0700149 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
mtklein36352bf2015-03-25 18:17:31 -0700150 void blitV(int x, int y, int height, SkAlpha alpha) override;
151 void blitRect(int x, int y, int width, int height) override;
152 void blitMask(const SkMask&, const SkIRect& clip) override;
reed41e010c2015-06-09 12:16:53 -0700153 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
mtklein36352bf2015-03-25 18:17:31 -0700154 bool isNullBlitter() const override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155};
156
157/** Wraps another (real) blitter, and ensures that the real blitter is only
158 called with coordinates that have been clipped by the specified clipRect.
159 This means the caller need not perform the clipping ahead of time.
160*/
161class SkRectClipBlitter : public SkBlitter {
162public:
163 void init(SkBlitter* blitter, const SkIRect& clipRect) {
164 SkASSERT(!clipRect.isEmpty());
165 fBlitter = blitter;
166 fClipRect = clipRect;
167 }
168
mtklein36352bf2015-03-25 18:17:31 -0700169 void blitH(int x, int y, int width) override;
reed3dfd1332015-06-25 14:26:11 -0700170 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
mtklein36352bf2015-03-25 18:17:31 -0700171 void blitV(int x, int y, int height, SkAlpha alpha) override;
172 void blitRect(int x, int y, int width, int height) override;
tomhudson@google.com49eac192011-12-27 13:59:20 +0000173 virtual void blitAntiRect(int x, int y, int width, int height,
mtklein36352bf2015-03-25 18:17:31 -0700174 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
175 void blitMask(const SkMask&, const SkIRect& clip) override;
reed41e010c2015-06-09 12:16:53 -0700176 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000177
mtklein36352bf2015-03-25 18:17:31 -0700178 int requestRowsPreserved() const override {
krajcevskifdd7d2b2014-07-29 07:21:41 -0700179 return fBlitter->requestRowsPreserved();
180 }
181
mtklein36352bf2015-03-25 18:17:31 -0700182 void* allocBlitMemory(size_t sz) override {
krajcevski75f88512014-07-21 09:54:23 -0700183 return fBlitter->allocBlitMemory(sz);
184 }
185
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186private:
187 SkBlitter* fBlitter;
188 SkIRect fClipRect;
189};
190
191/** Wraps another (real) blitter, and ensures that the real blitter is only
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000192 called with coordinates that have been clipped by the specified clipRgn.
193 This means the caller need not perform the clipping ahead of time.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194*/
195class SkRgnClipBlitter : public SkBlitter {
196public:
197 void init(SkBlitter* blitter, const SkRegion* clipRgn) {
198 SkASSERT(clipRgn && !clipRgn->isEmpty());
199 fBlitter = blitter;
200 fRgn = clipRgn;
201 }
202
mtklein36352bf2015-03-25 18:17:31 -0700203 void blitH(int x, int y, int width) override;
reed3dfd1332015-06-25 14:26:11 -0700204 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
mtklein36352bf2015-03-25 18:17:31 -0700205 void blitV(int x, int y, int height, SkAlpha alpha) override;
206 void blitRect(int x, int y, int width, int height) override;
reed3dfd1332015-06-25 14:26:11 -0700207 void blitAntiRect(int x, int y, int width, int height,
208 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
mtklein36352bf2015-03-25 18:17:31 -0700209 void blitMask(const SkMask&, const SkIRect& clip) override;
reed41e010c2015-06-09 12:16:53 -0700210 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211
mtklein36352bf2015-03-25 18:17:31 -0700212 int requestRowsPreserved() const override {
krajcevskifdd7d2b2014-07-29 07:21:41 -0700213 return fBlitter->requestRowsPreserved();
214 }
215
mtklein36352bf2015-03-25 18:17:31 -0700216 void* allocBlitMemory(size_t sz) override {
krajcevski75f88512014-07-21 09:54:23 -0700217 return fBlitter->allocBlitMemory(sz);
218 }
219
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220private:
221 SkBlitter* fBlitter;
222 const SkRegion* fRgn;
223};
224
tomhudson@google.com05fffdc2011-12-01 20:41:24 +0000225/** Factory to set up the appropriate most-efficient wrapper blitter
226 to apply a clip. Returns a pointer to a member, so lifetime must
227 be managed carefully.
228*/
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229class SkBlitterClipper {
230public:
231 SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip,
232 const SkIRect* bounds = NULL);
233
234private:
235 SkNullBlitter fNullBlitter;
236 SkRectClipBlitter fRectBlitter;
237 SkRgnClipBlitter fRgnBlitter;
238};
239
240#endif