• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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