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/SkRefCnt.h" 14 #include "include/core/SkRegion.h" 15 #include "include/private/base/SkAssert.h" 16 #include "include/private/base/SkCPUTypes.h" 17 #include "include/private/base/SkDebug.h" 18 #include "include/private/base/SkTo.h" 19 #include "src/base/SkAutoMalloc.h" 20 21 #include <cstddef> 22 #include <cstdint> 23 24 class SkArenaAlloc; 25 class SkMatrix; 26 class SkPaint; 27 class SkPixmap; 28 class SkShader; 29 class SkSurfaceProps; 30 struct SkMask; 31 enum class SkDrawCoverage : bool; 32 33 /** SkBlitter and its subclasses are responsible for actually writing pixels 34 into memory. Besides efficiency, they handle clipping and antialiasing. 35 A SkBlitter subclass contains all the context needed to generate pixels 36 for the destination and how src/generated pixels map to the destination. 37 The coordinates passed to the blitX calls are in destination pixel space. 38 */ 39 class SkBlitter { 40 public: 41 virtual ~SkBlitter(); 42 SkBlitter() = default; 43 SkBlitter(const SkBlitter&) = delete; 44 SkBlitter(SkBlitter&&) = delete; 45 SkBlitter& operator=(const SkBlitter&) = delete; 46 SkBlitter& operator=(SkBlitter&&) = delete; 47 48 /// Blit a horizontal run of one or more pixels. 49 virtual void blitH(int x, int y, int width) = 0; 50 51 /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse* 52 /// zero-terminated run-length encoding of spans of constant alpha values. 53 /// The runs[] and antialias[] work together to represent long runs of pixels with the same 54 /// alphas. The runs[] contains the number of pixels with the same alpha, and antialias[] 55 /// contain the coverage value for that number of pixels. The runs[] (and antialias[]) are 56 /// encoded in a clever way. The runs array is zero terminated, and has enough entries for 57 /// each pixel plus one, in most cases some of the entries will not contain valid data. An entry 58 /// in the runs array contains the number of pixels (np) that have the same alpha value. The 59 /// next np value is found np entries away. For example, if runs[0] = 7, then the next valid 60 /// entry will by at runs[7]. The runs array and antialias[] are coupled by index. So, if the 61 /// np entry is at runs[45] = 12 then the alpha value can be found at antialias[45] = 0x88. 62 /// This would mean to use an alpha value of 0x88 for the next 12 pixels starting at pixel 45. 63 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) = 0; 64 65 /// Blit a vertical run of pixels with a constant alpha value. 66 virtual void blitV(int x, int y, int height, SkAlpha alpha); 67 68 /// Blit a solid rectangle one or more pixels wide. 69 virtual void blitRect(int x, int y, int width, int height); 70 71 /** Blit a rectangle with one alpha-blended column on the left, 72 width (zero or more) opaque pixels, and one alpha-blended column 73 on the right. 74 The result will always be at least two pixels wide. 75 */ 76 virtual void blitAntiRect(int x, int y, int width, int height, 77 SkAlpha leftAlpha, SkAlpha rightAlpha); 78 79 // Blit a rect in AA with size at least 3 x 3 (small rect has too many edge cases...) 80 void blitFatAntiRect(const SkRect& rect); 81 82 /// Blit a pattern of pixels defined by a rectangle-clipped mask; 83 /// typically used for text. 84 virtual void blitMask(const SkMask&, const SkIRect& clip); 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 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 #if defined(SK_SUPPORT_LEGACY_ALPHA_BITMAP_AS_COVERAGE) 135 void blitMaskRegion(const SkMask& mask, const SkRegion& clip); 136 #endif 137 void blitRectRegion(const SkIRect& rect, const SkRegion& clip); 138 void blitRegion(const SkRegion& clip); 139 ///@} 140 141 /** @name Factories 142 Return the correct blitter to use given the specified context. 143 */ 144 static SkBlitter* Choose(const SkPixmap& dst, 145 const SkMatrix& ctm, 146 const SkPaint& paint, 147 SkArenaAlloc*, 148 SkDrawCoverage, 149 sk_sp<SkShader> clipShader, 150 const SkSurfaceProps& props); 151 152 static SkBlitter* ChooseSprite(const SkPixmap& dst, 153 const SkPaint&, 154 const SkPixmap& src, 155 int left, int top, 156 SkArenaAlloc*, sk_sp<SkShader> clipShader); 157 ///@} 158 159 static bool UseLegacyBlitter(const SkPixmap&, const SkPaint&, const SkMatrix&); 160 161 protected: 162 SkAutoMalloc fBlitMemory; 163 }; 164 165 /** This blitter silently never draws anything. 166 */ 167 class SkNullBlitter final : public SkBlitter { 168 public: blitH(int x,int y,int width)169 void blitH(int x, int y, int width) override {} blitAntiH(int x,int y,const SkAlpha[],const int16_t runs[])170 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override {} blitV(int x,int y,int height,SkAlpha alpha)171 void blitV(int x, int y, int height, SkAlpha alpha) override {} blitRect(int x,int y,int width,int height)172 void blitRect(int x, int y, int width, int height) override {} blitMask(const SkMask &,const SkIRect & clip)173 void blitMask(const SkMask&, const SkIRect& clip) 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 final : 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 requestRowsPreserved()196 int requestRowsPreserved() const override { 197 return fBlitter->requestRowsPreserved(); 198 } 199 allocBlitMemory(size_t sz)200 void* allocBlitMemory(size_t sz) override { 201 return fBlitter->allocBlitMemory(sz); 202 } 203 204 private: 205 SkBlitter* fBlitter; 206 SkIRect fClipRect; 207 }; 208 209 /** Wraps another (real) blitter, and ensures that the real blitter is only 210 called with coordinates that have been clipped by the specified clipRgn. 211 This means the caller need not perform the clipping ahead of time. 212 */ 213 class SkRgnClipBlitter final : public SkBlitter { 214 public: init(SkBlitter * blitter,const SkRegion * clipRgn)215 void init(SkBlitter* blitter, const SkRegion* clipRgn) { 216 SkASSERT(clipRgn && !clipRgn->isEmpty()); 217 fBlitter = blitter; 218 fRgn = clipRgn; 219 } 220 221 void blitH(int x, int y, int width) override; 222 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override; 223 void blitV(int x, int y, int height, SkAlpha alpha) override; 224 void blitRect(int x, int y, int width, int height) override; 225 void blitAntiRect(int x, int y, int width, int height, 226 SkAlpha leftAlpha, SkAlpha rightAlpha) override; 227 void blitMask(const SkMask&, const SkIRect& clip) 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 final : 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 void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override; 260 void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override; 261 requestRowsPreserved()262 int requestRowsPreserved() const override { 263 return fBlitter->requestRowsPreserved(); 264 } 265 allocBlitMemory(size_t sz)266 void* allocBlitMemory(size_t sz) override { 267 return fBlitter->allocBlitMemory(sz); 268 } 269 270 private: 271 SkBlitter* fBlitter; 272 SkIRect fClipRect; 273 }; 274 #endif 275 276 /** Factory to set up the appropriate most-efficient wrapper blitter 277 to apply a clip. Returns a pointer to a member, so lifetime must 278 be managed carefully. 279 */ 280 class SkBlitterClipper { 281 public: 282 SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip, 283 const SkIRect* bounds = nullptr); 284 285 private: 286 SkNullBlitter fNullBlitter; 287 SkRectClipBlitter fRectBlitter; 288 SkRgnClipBlitter fRgnBlitter; 289 }; 290 291 #endif 292