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