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