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#include "SkSpriteBlitter.h" 9#include "SkBlitRow.h" 10#include "SkColorFilter.h" 11#include "SkColorPriv.h" 12#include "SkTemplates.h" 13#include "SkUtils.h" 14#include "SkXfermode.h" 15 16/////////////////////////////////////////////////////////////////////////////// 17 18class Sprite_D32_S32 : public SkSpriteBlitter { 19public: 20 Sprite_D32_S32(const SkPixmap& src, U8CPU alpha) : INHERITED(src) { 21 SkASSERT(src.colorType() == kN32_SkColorType); 22 23 unsigned flags32 = 0; 24 if (255 != alpha) { 25 flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 26 } 27 if (!src.isOpaque()) { 28 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 29 } 30 31 fProc32 = SkBlitRow::Factory32(flags32); 32 fAlpha = alpha; 33 } 34 35 void blitRect(int x, int y, int width, int height) override { 36 SkASSERT(width > 0 && height > 0); 37 uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y); 38 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 39 size_t dstRB = fDst.rowBytes(); 40 size_t srcRB = fSource.rowBytes(); 41 SkBlitRow::Proc32 proc = fProc32; 42 U8CPU alpha = fAlpha; 43 44 do { 45 proc(dst, src, width, alpha); 46 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 47 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 48 } while (--height != 0); 49 } 50 51private: 52 SkBlitRow::Proc32 fProc32; 53 U8CPU fAlpha; 54 55 typedef SkSpriteBlitter INHERITED; 56}; 57 58/////////////////////////////////////////////////////////////////////////////// 59 60class Sprite_D32_XferFilter : public SkSpriteBlitter { 61public: 62 Sprite_D32_XferFilter(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) { 63 fColorFilter = paint.getColorFilter(); 64 SkSafeRef(fColorFilter); 65 66 fXfermode = paint.getXfermode(); 67 SkSafeRef(fXfermode); 68 69 fBufferSize = 0; 70 fBuffer = nullptr; 71 72 unsigned flags32 = 0; 73 if (255 != paint.getAlpha()) { 74 flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 75 } 76 if (!source.isOpaque()) { 77 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 78 } 79 80 fProc32 = SkBlitRow::Factory32(flags32); 81 fAlpha = paint.getAlpha(); 82 } 83 84 virtual ~Sprite_D32_XferFilter() { 85 delete[] fBuffer; 86 SkSafeUnref(fXfermode); 87 SkSafeUnref(fColorFilter); 88 } 89 90 void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override { 91 this->INHERITED::setup(dst, left, top, paint); 92 93 int width = dst.width(); 94 if (width > fBufferSize) { 95 fBufferSize = width; 96 delete[] fBuffer; 97 fBuffer = new SkPMColor[width]; 98 } 99 } 100 101protected: 102 SkColorFilter* fColorFilter; 103 SkXfermode* fXfermode; 104 int fBufferSize; 105 SkPMColor* fBuffer; 106 SkBlitRow::Proc32 fProc32; 107 U8CPU fAlpha; 108 109private: 110 typedef SkSpriteBlitter INHERITED; 111}; 112 113/////////////////////////////////////////////////////////////////////////////// 114 115class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter { 116public: 117 Sprite_D32_S32A_XferFilter(const SkPixmap& source, const SkPaint& paint) 118 : Sprite_D32_XferFilter(source, paint) {} 119 120 void blitRect(int x, int y, int width, int height) override { 121 SkASSERT(width > 0 && height > 0); 122 uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y); 123 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 124 size_t dstRB = fDst.rowBytes(); 125 size_t srcRB = fSource.rowBytes(); 126 SkColorFilter* colorFilter = fColorFilter; 127 SkXfermode* xfermode = fXfermode; 128 129 do { 130 const SkPMColor* tmp = src; 131 132 if (colorFilter) { 133 colorFilter->filterSpan(src, width, fBuffer); 134 tmp = fBuffer; 135 } 136 137 if (xfermode) { 138 xfermode->xfer32(dst, tmp, width, nullptr); 139 } else { 140 fProc32(dst, tmp, width, fAlpha); 141 } 142 143 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 144 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 145 } while (--height != 0); 146 } 147 148private: 149 typedef Sprite_D32_XferFilter INHERITED; 150}; 151 152static void fillbuffer(SkPMColor* SK_RESTRICT dst, 153 const SkPMColor16* SK_RESTRICT src, int count) { 154 SkASSERT(count > 0); 155 156 do { 157 *dst++ = SkPixel4444ToPixel32(*src++); 158 } while (--count != 0); 159} 160 161class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter { 162public: 163 Sprite_D32_S4444_XferFilter(const SkPixmap& source, const SkPaint& paint) 164 : Sprite_D32_XferFilter(source, paint) {} 165 166 void blitRect(int x, int y, int width, int height) override { 167 SkASSERT(width > 0 && height > 0); 168 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y); 169 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop); 170 size_t dstRB = fDst.rowBytes(); 171 size_t srcRB = fSource.rowBytes(); 172 SkPMColor* SK_RESTRICT buffer = fBuffer; 173 SkColorFilter* colorFilter = fColorFilter; 174 SkXfermode* xfermode = fXfermode; 175 176 do { 177 fillbuffer(buffer, src, width); 178 179 if (colorFilter) { 180 colorFilter->filterSpan(buffer, width, buffer); 181 } 182 if (xfermode) { 183 xfermode->xfer32(dst, buffer, width, nullptr); 184 } else { 185 fProc32(dst, buffer, width, fAlpha); 186 } 187 188 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 189 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 190 } while (--height != 0); 191 } 192 193private: 194 typedef Sprite_D32_XferFilter INHERITED; 195}; 196 197/////////////////////////////////////////////////////////////////////////////// 198 199static void src_row(SkPMColor* SK_RESTRICT dst, 200 const SkPMColor16* SK_RESTRICT src, int count) { 201 do { 202 *dst = SkPixel4444ToPixel32(*src); 203 src += 1; 204 dst += 1; 205 } while (--count != 0); 206} 207 208class Sprite_D32_S4444_Opaque : public SkSpriteBlitter { 209public: 210 Sprite_D32_S4444_Opaque(const SkPixmap& source) : SkSpriteBlitter(source) {} 211 212 void blitRect(int x, int y, int width, int height) override { 213 SkASSERT(width > 0 && height > 0); 214 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y); 215 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop); 216 size_t dstRB = fDst.rowBytes(); 217 size_t srcRB = fSource.rowBytes(); 218 219 do { 220 src_row(dst, src, width); 221 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 222 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 223 } while (--height != 0); 224 } 225}; 226 227static void srcover_row(SkPMColor* SK_RESTRICT dst, 228 const SkPMColor16* SK_RESTRICT src, int count) { 229 do { 230 *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); 231 src += 1; 232 dst += 1; 233 } while (--count != 0); 234} 235 236class Sprite_D32_S4444 : public SkSpriteBlitter { 237public: 238 Sprite_D32_S4444(const SkPixmap& source) : SkSpriteBlitter(source) {} 239 240 void blitRect(int x, int y, int width, int height) override { 241 SkASSERT(width > 0 && height > 0); 242 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y); 243 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop); 244 size_t dstRB = fDst.rowBytes(); 245 size_t srcRB = fSource.rowBytes(); 246 247 do { 248 srcover_row(dst, src, width); 249 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 250 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 251 } while (--height != 0); 252 } 253}; 254 255/////////////////////////////////////////////////////////////////////////////// 256 257SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPaint& paint, 258 SkTBlitterAllocator* allocator) { 259 SkASSERT(allocator != nullptr); 260 261 if (paint.getMaskFilter() != nullptr) { 262 return nullptr; 263 } 264 265 U8CPU alpha = paint.getAlpha(); 266 SkXfermode* xfermode = paint.getXfermode(); 267 SkColorFilter* filter = paint.getColorFilter(); 268 SkSpriteBlitter* blitter = nullptr; 269 270 switch (source.colorType()) { 271 case kARGB_4444_SkColorType: 272 if (alpha != 0xFF) { 273 return nullptr; // we only have opaque sprites 274 } 275 if (xfermode || filter) { 276 blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint); 277 } else if (source.isOpaque()) { 278 blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source); 279 } else { 280 blitter = allocator->createT<Sprite_D32_S4444>(source); 281 } 282 break; 283 case kN32_SkColorType: 284 if (xfermode || filter) { 285 if (255 == alpha) { 286 // this can handle xfermode or filter, but not alpha 287 blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint); 288 } 289 } else { 290 // this can handle alpha, but not xfermode or filter 291 blitter = allocator->createT<Sprite_D32_S32>(source, alpha); 292 } 293 break; 294 default: 295 break; 296 } 297 return blitter; 298} 299