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