2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkSpriteBlitter.h"
10 #include "SkColorFilter.h"
11 #include "SkColorPriv.h"
12 #include "SkTemplates.h"
14 #include "SkXfermode.h"
16 ///////////////////////////////////////////////////////////////////////////////
18 class Sprite_D32_S32 : public SkSpriteBlitter {
20 Sprite_D32_S32(const SkPixmap& src, U8CPU alpha) : INHERITED(src) {
21 SkASSERT(src.colorType() == kN32_SkColorType);
25 flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
27 if (!src.isOpaque()) {
28 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
31 fProc32 = SkBlitRow::Factory32(flags32);
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;
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);
52 SkBlitRow::Proc32 fProc32;
55 typedef SkSpriteBlitter INHERITED;
58 ///////////////////////////////////////////////////////////////////////////////
60 class Sprite_D32_XferFilter : public SkSpriteBlitter {
62 Sprite_D32_XferFilter(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) {
63 fColorFilter = paint.getColorFilter();
64 SkSafeRef(fColorFilter);
66 fXfermode = SkXfermode::Peek(paint.getBlendMode());
72 if (255 != paint.getAlpha()) {
73 flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
75 if (!source.isOpaque()) {
76 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
79 fProc32 = SkBlitRow::Factory32(flags32);
80 fAlpha = paint.getAlpha();
83 virtual ~Sprite_D32_XferFilter() {
85 SkSafeUnref(fColorFilter);
88 void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
89 this->INHERITED::setup(dst, left, top, paint);
91 int width = dst.width();
92 if (width > fBufferSize) {
95 fBuffer = new SkPMColor[width];
100 SkColorFilter* fColorFilter;
101 SkXfermode* fXfermode;
104 SkBlitRow::Proc32 fProc32;
108 typedef SkSpriteBlitter INHERITED;
111 ///////////////////////////////////////////////////////////////////////////////
113 class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
115 Sprite_D32_S32A_XferFilter(const SkPixmap& source, const SkPaint& paint)
116 : Sprite_D32_XferFilter(source, paint) {}
118 void blitRect(int x, int y, int width, int height) override {
119 SkASSERT(width > 0 && height > 0);
120 uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
121 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
122 size_t dstRB = fDst.rowBytes();
123 size_t srcRB = fSource.rowBytes();
124 SkColorFilter* colorFilter = fColorFilter;
125 SkXfermode* xfermode = fXfermode;
128 const SkPMColor* tmp = src;
131 colorFilter->filterSpan(src, width, fBuffer);
136 xfermode->xfer32(dst, tmp, width, nullptr);
138 fProc32(dst, tmp, width, fAlpha);
141 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
142 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
143 } while (--height != 0);
147 typedef Sprite_D32_XferFilter INHERITED;
150 static void fillbuffer(SkPMColor* SK_RESTRICT dst,
151 const SkPMColor16* SK_RESTRICT src, int count) {
155 *dst++ = SkPixel4444ToPixel32(*src++);
156 } while (--count != 0);
159 class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
161 Sprite_D32_S4444_XferFilter(const SkPixmap& source, const SkPaint& paint)
162 : Sprite_D32_XferFilter(source, paint) {}
164 void blitRect(int x, int y, int width, int height) override {
165 SkASSERT(width > 0 && height > 0);
166 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
167 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
168 size_t dstRB = fDst.rowBytes();
169 size_t srcRB = fSource.rowBytes();
170 SkPMColor* SK_RESTRICT buffer = fBuffer;
171 SkColorFilter* colorFilter = fColorFilter;
172 SkXfermode* xfermode = fXfermode;
175 fillbuffer(buffer, src, width);
178 colorFilter->filterSpan(buffer, width, buffer);
181 xfermode->xfer32(dst, buffer, width, nullptr);
183 fProc32(dst, buffer, width, fAlpha);
186 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
187 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
188 } while (--height != 0);
192 typedef Sprite_D32_XferFilter INHERITED;
195 ///////////////////////////////////////////////////////////////////////////////
197 static void src_row(SkPMColor* SK_RESTRICT dst,
198 const SkPMColor16* SK_RESTRICT src, int count) {
200 *dst = SkPixel4444ToPixel32(*src);
203 } while (--count != 0);
206 class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
208 Sprite_D32_S4444_Opaque(const SkPixmap& source) : SkSpriteBlitter(source) {}
210 void blitRect(int x, int y, int width, int height) override {
211 SkASSERT(width > 0 && height > 0);
212 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
213 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
214 size_t dstRB = fDst.rowBytes();
215 size_t srcRB = fSource.rowBytes();
218 src_row(dst, src, width);
219 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
220 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
221 } while (--height != 0);
225 static void srcover_row(SkPMColor* SK_RESTRICT dst,
226 const SkPMColor16* SK_RESTRICT src, int count) {
228 *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
231 } while (--count != 0);
234 class Sprite_D32_S4444 : public SkSpriteBlitter {
236 Sprite_D32_S4444(const SkPixmap& source) : SkSpriteBlitter(source) {}
238 void blitRect(int x, int y, int width, int height) override {
239 SkASSERT(width > 0 && height > 0);
240 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
241 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
242 size_t dstRB = fDst.rowBytes();
243 size_t srcRB = fSource.rowBytes();
246 srcover_row(dst, src, width);
247 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
248 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
249 } while (--height != 0);
253 ///////////////////////////////////////////////////////////////////////////////
255 SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPaint& paint,
256 SkTBlitterAllocator* allocator) {
257 SkASSERT(allocator != nullptr);
259 if (paint.getMaskFilter() != nullptr) {
263 U8CPU alpha = paint.getAlpha();
264 bool isSrcOver = paint.isSrcOver();
265 SkColorFilter* filter = paint.getColorFilter();
266 SkSpriteBlitter* blitter = nullptr;
268 switch (source.colorType()) {
269 case kARGB_4444_SkColorType:
271 return nullptr; // we only have opaque sprites
273 if (!isSrcOver || filter) {
274 blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint);
275 } else if (source.isOpaque()) {
276 blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source);
278 blitter = allocator->createT<Sprite_D32_S4444>(source);
281 case kN32_SkColorType:
282 if (!isSrcOver || filter) {
284 // this can handle xfermode or filter, but not alpha
285 blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint);
288 // this can handle alpha, but not xfermode or filter
289 blitter = allocator->createT<Sprite_D32_S32>(source, alpha);