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 "SkBitmap.h" 12 #include "SkBitmapProcShader.h" 13 #include "SkMask.h" 14 #include "SkMatrix.h" 15 #include "SkPaint.h" 16 #include "SkRefCnt.h" 17 #include "SkRegion.h" 18 #include "SkShader.h" 19 #include "SkSmallAllocator.h" 20 21 /** SkBlitter and its subclasses are responsible for actually writing pixels 22 into memory. Besides efficiency, they handle clipping and antialiasing. 23 */ 24 class SkBlitter { 25 public: 26 virtual ~SkBlitter(); 27 28 /// Blit a horizontal run of one or more pixels. 29 virtual void blitH(int x, int y, int width); 30 /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse* 31 /// zero-terminated run-length encoding of spans of constant alpha values. 32 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 33 const int16_t runs[]); 34 35 /// Blit a vertical run of pixels with a constant alpha value. 36 virtual void blitV(int x, int y, int height, SkAlpha alpha); 37 /// Blit a solid rectangle one or more pixels wide. 38 virtual void blitRect(int x, int y, int width, int height); 39 /** Blit a rectangle with one alpha-blended column on the left, 40 width (zero or more) opaque pixels, and one alpha-blended column 41 on the right. 42 The result will always be at least two pixels wide. 43 */ 44 virtual void blitAntiRect(int x, int y, int width, int height, 45 SkAlpha leftAlpha, SkAlpha rightAlpha); 46 /// Blit a pattern of pixels defined by a rectangle-clipped mask; 47 /// typically used for text. 48 virtual void blitMask(const SkMask&, const SkIRect& clip); 49 50 /** If the blitter just sets a single value for each pixel, return the 51 bitmap it draws into, and assign value. If not, return NULL and ignore 52 the value parameter. 53 */ 54 virtual const SkBitmap* justAnOpaqueColor(uint32_t* value); 55 56 // (x, y), (x + 1, y) blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)57 virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 58 int16_t runs[3]; 59 uint8_t aa[2]; 60 61 runs[0] = 1; 62 runs[1] = 1; 63 runs[2] = 0; 64 aa[0] = SkToU8(a0); 65 aa[1] = SkToU8(a1); 66 this->blitAntiH(x, y, aa, runs); 67 } 68 69 // (x, y), (x, y + 1) blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)70 virtual void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 71 int16_t runs[2]; 72 uint8_t aa[1]; 73 74 runs[0] = 1; 75 runs[1] = 0; 76 aa[0] = SkToU8(a0); 77 this->blitAntiH(x, y, aa, runs); 78 // reset in case the clipping blitter modified runs 79 runs[0] = 1; 80 runs[1] = 0; 81 aa[0] = SkToU8(a1); 82 this->blitAntiH(x, y + 1, aa, runs); 83 } 84 85 /** 86 * Special method just to identify the null blitter, which is returned 87 * from Choose() if the request cannot be fulfilled. Default impl 88 * returns false. 89 */ 90 virtual bool isNullBlitter() const; 91 92 /** 93 * Special methods for SkShaderBlitter. On all other classes this is a no-op. 94 */ 95 virtual bool resetShaderContext(const SkShader::ContextRec&); 96 virtual SkShader::Context* getShaderContext() const; 97 98 /** 99 * Special methods for blitters that can blit more than one row at a time. 100 * This function returns the number of rows that this blitter could optimally 101 * process at a time. It is still required to support blitting one scanline 102 * at a time. 103 */ requestRowsPreserved()104 virtual int requestRowsPreserved() const { return 1; } 105 106 /** 107 * This function allocates memory for the blitter that the blitter then owns. 108 * The memory can be used by the calling function at will, but it will be 109 * released when the blitter's destructor is called. This function returns 110 * NULL if no persistent memory is needed by the blitter. 111 */ allocBlitMemory(size_t sz)112 virtual void* allocBlitMemory(size_t sz) { 113 return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink); 114 } 115 116 ///@name non-virtual helpers 117 void blitMaskRegion(const SkMask& mask, const SkRegion& clip); 118 void blitRectRegion(const SkIRect& rect, const SkRegion& clip); 119 void blitRegion(const SkRegion& clip); 120 ///@} 121 122 /** @name Factories 123 Return the correct blitter to use given the specified context. 124 */ 125 static SkBlitter* Choose(const SkBitmap& device, 126 const SkMatrix& matrix, 127 const SkPaint& paint, 128 SkTBlitterAllocator*, 129 bool drawCoverage = false); 130 131 static SkBlitter* ChooseSprite(const SkBitmap& device, 132 const SkPaint&, 133 const SkBitmap& src, 134 int left, int top, 135 SkTBlitterAllocator*); 136 ///@} 137 138 protected: 139 140 SkAutoMalloc fBlitMemory; 141 142 private: 143 }; 144 145 /** This blitter silently never draws anything. 146 */ 147 class SkNullBlitter : public SkBlitter { 148 public: 149 void blitH(int x, int y, int width) override; 150 virtual void blitAntiH(int x, int y, const SkAlpha[], 151 const int16_t runs[]) override; 152 void blitV(int x, int y, int height, SkAlpha alpha) override; 153 void blitRect(int x, int y, int width, int height) override; 154 void blitMask(const SkMask&, const SkIRect& clip) override; 155 const SkBitmap* justAnOpaqueColor(uint32_t* value) override; 156 bool isNullBlitter() const override; 157 }; 158 159 /** Wraps another (real) blitter, and ensures that the real blitter is only 160 called with coordinates that have been clipped by the specified clipRect. 161 This means the caller need not perform the clipping ahead of time. 162 */ 163 class SkRectClipBlitter : public SkBlitter { 164 public: init(SkBlitter * blitter,const SkIRect & clipRect)165 void init(SkBlitter* blitter, const SkIRect& clipRect) { 166 SkASSERT(!clipRect.isEmpty()); 167 fBlitter = blitter; 168 fClipRect = clipRect; 169 } 170 171 void blitH(int x, int y, int width) override; 172 virtual void blitAntiH(int x, int y, const SkAlpha[], 173 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 virtual void blitAntiRect(int x, int y, int width, int height, 177 SkAlpha leftAlpha, SkAlpha rightAlpha) override; 178 void blitMask(const SkMask&, const SkIRect& clip) override; 179 const SkBitmap* justAnOpaqueColor(uint32_t* value) override; 180 requestRowsPreserved()181 int requestRowsPreserved() const override { 182 return fBlitter->requestRowsPreserved(); 183 } 184 allocBlitMemory(size_t sz)185 void* allocBlitMemory(size_t sz) override { 186 return fBlitter->allocBlitMemory(sz); 187 } 188 189 private: 190 SkBlitter* fBlitter; 191 SkIRect fClipRect; 192 }; 193 194 /** Wraps another (real) blitter, and ensures that the real blitter is only 195 called with coordinates that have been clipped by the specified clipRgn. 196 This means the caller need not perform the clipping ahead of time. 197 */ 198 class SkRgnClipBlitter : public SkBlitter { 199 public: init(SkBlitter * blitter,const SkRegion * clipRgn)200 void init(SkBlitter* blitter, const SkRegion* clipRgn) { 201 SkASSERT(clipRgn && !clipRgn->isEmpty()); 202 fBlitter = blitter; 203 fRgn = clipRgn; 204 } 205 206 void blitH(int x, int y, int width) override; 207 virtual void blitAntiH(int x, int y, const SkAlpha[], 208 const int16_t runs[]) override; 209 void blitV(int x, int y, int height, SkAlpha alpha) override; 210 void blitRect(int x, int y, int width, int height) override; 211 virtual void blitAntiRect(int x, int y, int width, int height, 212 SkAlpha leftAlpha, SkAlpha rightAlpha) override; 213 void blitMask(const SkMask&, const SkIRect& clip) override; 214 const SkBitmap* justAnOpaqueColor(uint32_t* value) override; 215 requestRowsPreserved()216 int requestRowsPreserved() const override { 217 return fBlitter->requestRowsPreserved(); 218 } 219 allocBlitMemory(size_t sz)220 void* allocBlitMemory(size_t sz) override { 221 return fBlitter->allocBlitMemory(sz); 222 } 223 224 private: 225 SkBlitter* fBlitter; 226 const SkRegion* fRgn; 227 }; 228 229 /** Factory to set up the appropriate most-efficient wrapper blitter 230 to apply a clip. Returns a pointer to a member, so lifetime must 231 be managed carefully. 232 */ 233 class SkBlitterClipper { 234 public: 235 SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip, 236 const SkIRect* bounds = NULL); 237 238 private: 239 SkNullBlitter fNullBlitter; 240 SkRectClipBlitter fRectBlitter; 241 SkRgnClipBlitter fRgnBlitter; 242 }; 243 244 #endif 245