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/base/SkTo.h" 15 #include "src/base/SkAutoMalloc.h" 16 #include "src/shaders/SkShaderBase.h" 17 18 class SkArenaAlloc; 19 class SkMatrix; 20 class SkMatrixProvider; 21 class SkPaint; 22 class SkPixmap; 23 class SkSurfaceProps; 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 #if defined(SK_SUPPORT_LEGACY_ALPHA_BITMAP_AS_COVERAGE) 136 void blitMaskRegion(const SkMask& mask, const SkRegion& clip); 137 #endif 138 void blitRectRegion(const SkIRect& rect, const SkRegion& clip); 139 void blitRegion(const SkRegion& clip); 140 ///@} 141 142 /** @name Factories 143 Return the correct blitter to use given the specified context. 144 */ 145 static SkBlitter* Choose(const SkPixmap& dst, 146 const SkMatrix& ctm, 147 const SkPaint& paint, 148 SkArenaAlloc*, 149 bool drawCoverage, 150 sk_sp<SkShader> clipShader, 151 const SkSurfaceProps& props); 152 153 static SkBlitter* ChooseSprite(const SkPixmap& dst, 154 const SkPaint&, 155 const SkPixmap& src, 156 int left, int top, 157 SkArenaAlloc*, sk_sp<SkShader> clipShader); 158 ///@} 159 160 static bool UseLegacyBlitter(const SkPixmap&, const SkPaint&, const SkMatrix&); 161 162 protected: 163 SkAutoMalloc fBlitMemory; 164 }; 165 166 /** This blitter silently never draws anything. 167 */ 168 class SkNullBlitter : public SkBlitter { 169 public: 170 void blitH(int x, int y, int width) override; 171 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override; 172 void blitV(int x, int y, int height, SkAlpha alpha) override; 173 void blitRect(int x, int y, int width, int height) override; 174 void blitMask(const SkMask&, const SkIRect& clip) override; 175 const SkPixmap* justAnOpaqueColor(uint32_t* value) override; 176 bool isNullBlitter() const override; 177 }; 178 179 /** Wraps another (real) blitter, and ensures that the real blitter is only 180 called with coordinates that have been clipped by the specified clipRect. 181 This means the caller need not perform the clipping ahead of time. 182 */ 183 class SkRectClipBlitter : public SkBlitter { 184 public: init(SkBlitter * blitter,const SkIRect & clipRect)185 void init(SkBlitter* blitter, const SkIRect& clipRect) { 186 SkASSERT(!clipRect.isEmpty()); 187 fBlitter = blitter; 188 fClipRect = clipRect; 189 } 190 191 void blitH(int x, int y, int width) override; 192 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override; 193 void blitV(int x, int y, int height, SkAlpha alpha) override; 194 void blitRect(int x, int y, int width, int height) override; 195 void blitAntiRect(int x, int y, int width, int height, 196 SkAlpha leftAlpha, SkAlpha rightAlpha) override; 197 void blitMask(const SkMask&, const SkIRect& clip) override; 198 const SkPixmap* justAnOpaqueColor(uint32_t* value) override; 199 requestRowsPreserved()200 int requestRowsPreserved() const override { 201 return fBlitter->requestRowsPreserved(); 202 } 203 allocBlitMemory(size_t sz)204 void* allocBlitMemory(size_t sz) override { 205 return fBlitter->allocBlitMemory(sz); 206 } 207 208 private: 209 SkBlitter* fBlitter; 210 SkIRect fClipRect; 211 }; 212 213 /** Wraps another (real) blitter, and ensures that the real blitter is only 214 called with coordinates that have been clipped by the specified clipRgn. 215 This means the caller need not perform the clipping ahead of time. 216 */ 217 class SkRgnClipBlitter : public SkBlitter { 218 public: init(SkBlitter * blitter,const SkRegion * clipRgn)219 void init(SkBlitter* blitter, const SkRegion* clipRgn) { 220 SkASSERT(clipRgn && !clipRgn->isEmpty()); 221 fBlitter = blitter; 222 fRgn = clipRgn; 223 } 224 225 void blitH(int x, int y, int width) override; 226 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override; 227 void blitV(int x, int y, int height, SkAlpha alpha) override; 228 void blitRect(int x, int y, int width, int height) override; 229 void blitAntiRect(int x, int y, int width, int height, 230 SkAlpha leftAlpha, SkAlpha rightAlpha) override; 231 void blitMask(const SkMask&, const SkIRect& clip) override; 232 const SkPixmap* justAnOpaqueColor(uint32_t* value) override; 233 requestRowsPreserved()234 int requestRowsPreserved() const override { 235 return fBlitter->requestRowsPreserved(); 236 } 237 allocBlitMemory(size_t sz)238 void* allocBlitMemory(size_t sz) override { 239 return fBlitter->allocBlitMemory(sz); 240 } 241 242 private: 243 SkBlitter* fBlitter; 244 const SkRegion* fRgn; 245 }; 246 247 #ifdef SK_DEBUG 248 class SkRectClipCheckBlitter : public SkBlitter { 249 public: init(SkBlitter * blitter,const SkIRect & clipRect)250 void init(SkBlitter* blitter, const SkIRect& clipRect) { 251 SkASSERT(blitter); 252 SkASSERT(!clipRect.isEmpty()); 253 fBlitter = blitter; 254 fClipRect = clipRect; 255 } 256 257 void blitH(int x, int y, int width) override; 258 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override; 259 void blitV(int x, int y, int height, SkAlpha alpha) override; 260 void blitRect(int x, int y, int width, int height) override; 261 void blitAntiRect(int x, int y, int width, int height, 262 SkAlpha leftAlpha, SkAlpha rightAlpha) override; 263 void blitMask(const SkMask&, const SkIRect& clip) override; 264 const SkPixmap* justAnOpaqueColor(uint32_t* value) override; 265 void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override; 266 void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override; 267 requestRowsPreserved()268 int requestRowsPreserved() const override { 269 return fBlitter->requestRowsPreserved(); 270 } 271 allocBlitMemory(size_t sz)272 void* allocBlitMemory(size_t sz) override { 273 return fBlitter->allocBlitMemory(sz); 274 } 275 276 private: 277 SkBlitter* fBlitter; 278 SkIRect fClipRect; 279 }; 280 #endif 281 282 /** Factory to set up the appropriate most-efficient wrapper blitter 283 to apply a clip. Returns a pointer to a member, so lifetime must 284 be managed carefully. 285 */ 286 class SkBlitterClipper { 287 public: 288 SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip, 289 const SkIRect* bounds = nullptr); 290 291 private: 292 SkNullBlitter fNullBlitter; 293 SkRectClipBlitter fRectBlitter; 294 SkRgnClipBlitter fRgnBlitter; 295 }; 296 297 // A good size for creating shader contexts on the stack. 298 enum {kSkBlitterContextSize = 3332}; 299 300 #endif 301