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