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