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