1 /*
2  * Copyright 2017 Google Inc.
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 "include/core/SkShader.h"
9 #include "include/private/SkColorData.h"
10 #include "include/private/SkColorData.h"
11 #include "src/core/SkCoreBlitters.h"
12 #include "src/core/SkXfermodePriv.h"
13 
14 #include "include/private/SkNx.h"
15 
D16_S32X_src(uint16_t dst[],const SkPMColor src[],int count,uint8_t coverage)16 static void D16_S32X_src(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) {
17     SkASSERT(coverage == 0xFF);
18     for (int i = 0; i < count; ++i) {
19         dst[i] = SkPixel32ToPixel16(src[i]);
20     }
21 }
22 
D16_S32X_src_coverage(uint16_t dst[],const SkPMColor src[],int count,uint8_t coverage)23 static void D16_S32X_src_coverage(uint16_t dst[], const SkPMColor src[], int count,
24                                   uint8_t coverage) {
25     switch (coverage) {
26         case 0: break;
27         case 0xFF:
28             for (int i = 0; i < count; ++i) {
29                 dst[i] = SkPixel32ToPixel16(src[i]);
30             }
31             break;
32         default:
33             unsigned scale = coverage + (coverage >> 7);
34             for (int i = 0; i < count; ++i) {
35                 dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]);
36             }
37             break;
38     }
39 }
40 
D16_S32A_srcover(uint16_t dst[],const SkPMColor src[],int count,uint8_t coverage)41 static void D16_S32A_srcover(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) {
42     SkASSERT(coverage == 0xFF);
43     for (int i = 0; i < count; ++i) {
44         dst[i] = SkSrcOver32To16(src[i], dst[i]);
45     }
46 }
47 
D16_S32A_srcover_coverage(uint16_t dst[],const SkPMColor src[],int count,uint8_t coverage)48 static void D16_S32A_srcover_coverage(uint16_t dst[], const SkPMColor src[], int count,
49                                       uint8_t coverage) {
50     switch (coverage) {
51         case 0: break;
52         case 0xFF:
53             for (int i = 0; i < count; ++i) {
54                 dst[i] = SkSrcOver32To16(src[i], dst[i]);
55             }
56             break;
57         default:
58             unsigned scale = coverage + (coverage >> 7);
59             for (int i = 0; i < count; ++i) {
60                 dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]);
61             }
62             break;
63     }
64 }
65 
Supports(const SkPixmap & device,const SkPaint & paint)66 bool SkRGB565_Shader_Blitter::Supports(const SkPixmap& device, const SkPaint& paint) {
67     if (device.colorType() != kRGB_565_SkColorType) {
68         return false;
69     }
70     if (device.colorSpace()) {
71         return false;
72     }
73     if (paint.getBlendMode() != SkBlendMode::kSrcOver &&
74         paint.getBlendMode() != SkBlendMode::kSrc) {
75         return false;
76     }
77     if (paint.isDither()) {
78         return false;
79     }
80     return true;
81 }
82 
SkRGB565_Shader_Blitter(const SkPixmap & device,const SkPaint & paint,SkShaderBase::Context * shaderContext)83 SkRGB565_Shader_Blitter::SkRGB565_Shader_Blitter(const SkPixmap& device,
84         const SkPaint& paint, SkShaderBase::Context* shaderContext)
85     : INHERITED(device, paint, shaderContext)
86 {
87     SkASSERT(shaderContext);
88     SkASSERT(Supports(device, paint));
89 
90     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
91 
92     bool isOpaque = SkToBool(shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag);
93 
94     if (paint.getBlendMode() == SkBlendMode::kSrc || isOpaque) {
95         fBlend = D16_S32X_src;
96         fBlendCoverage = D16_S32X_src_coverage;
97     } else {    // srcover
98         fBlend = isOpaque ? D16_S32X_src : D16_S32A_srcover;
99         fBlendCoverage = isOpaque ? D16_S32X_src_coverage : D16_S32A_srcover_coverage;
100     }
101 }
102 
~SkRGB565_Shader_Blitter()103 SkRGB565_Shader_Blitter::~SkRGB565_Shader_Blitter() {
104     sk_free(fBuffer);
105 }
106 
blitH(int x,int y,int width)107 void SkRGB565_Shader_Blitter::blitH(int x, int y, int width) {
108     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
109 
110     uint16_t* device = fDevice.writable_addr16(x, y);
111 
112     SkPMColor*  span = fBuffer;
113     fShaderContext->shadeSpan(x, y, span, width);
114     fBlend(device, span, width, 0xFF);
115 }
116 
blitAntiH(int x,int y,const SkAlpha coverage[],const int16_t runs[])117 void SkRGB565_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha coverage[],
118                                         const int16_t runs[]) {
119     SkPMColor* span = fBuffer;
120     uint16_t*  device = fDevice.writable_addr16(x, y);
121     auto*      shaderContext = fShaderContext;
122 
123     for (;;) {
124         int count = *runs;
125         if (count <= 0) {
126             break;
127         }
128         int aa = *coverage;
129         if (aa) {
130             shaderContext->shadeSpan(x, y, span, count);
131             fBlendCoverage(device, span, count, aa);
132         }
133         device += count;
134         runs += count;
135         coverage += count;
136         x += count;
137     }
138 }
139