Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2016 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 "SkArenaAlloc.h"
      9 #include "SkColorShader.h"
     10 #include "SkColorSpace.h"
     11 #include "SkPM4fPriv.h"
     12 #include "SkRasterPipeline.h"
     13 #include "SkReadBuffer.h"
     14 #include "SkUtils.h"
     15 
     16 SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
     17 
     18 bool SkColorShader::isOpaque() const {
     19     return SkColorGetA(fColor) == 255;
     20 }
     21 
     22 sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
     23     return sk_make_sp<SkColorShader>(buffer.readColor());
     24 }
     25 
     26 void SkColorShader::flatten(SkWriteBuffer& buffer) const {
     27     buffer.writeColor(fColor);
     28 }
     29 
     30 uint32_t SkColorShader::ColorShaderContext::getFlags() const {
     31     return fFlags;
     32 }
     33 
     34 SkShader::Context* SkColorShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
     35     return alloc->make<ColorShaderContext>(*this, rec);
     36 }
     37 
     38 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
     39                                                       const ContextRec& rec)
     40     : INHERITED(shader, rec)
     41 {
     42     SkColor color = shader.fColor;
     43     unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
     44 
     45     unsigned r = SkColorGetR(color);
     46     unsigned g = SkColorGetG(color);
     47     unsigned b = SkColorGetB(color);
     48 
     49     if (a != 255) {
     50         r = SkMulDiv255Round(r, a);
     51         g = SkMulDiv255Round(g, a);
     52         b = SkMulDiv255Round(b, a);
     53     }
     54     fPMColor = SkPackARGB32(a, r, g, b);
     55 
     56     SkColor4f c4 = SkColor4f::FromColor(shader.fColor);
     57     c4.fA *= rec.fPaint->getAlpha() / 255.0f;
     58     fPM4f = c4.premul();
     59 
     60     fFlags = kConstInY32_Flag;
     61     if (255 == a) {
     62         fFlags |= kOpaqueAlpha_Flag;
     63     }
     64 }
     65 
     66 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
     67     sk_memset32(span, fPMColor, count);
     68 }
     69 
     70 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
     71     memset(alpha, SkGetPackedA32(fPMColor), count);
     72 }
     73 
     74 void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
     75     for (int i = 0; i < count; ++i) {
     76         span[i] = fPM4f;
     77     }
     78 }
     79 
     80 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
     81     if (info) {
     82         if (info->fColors && info->fColorCount >= 1) {
     83             info->fColors[0] = fColor;
     84         }
     85         info->fColorCount = 1;
     86         info->fTileMode = SkShader::kRepeat_TileMode;
     87     }
     88     return kColor_GradientType;
     89 }
     90 
     91 #if SK_SUPPORT_GPU
     92 
     93 #include "SkGr.h"
     94 #include "effects/GrConstColorProcessor.h"
     95 sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const {
     96     GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace);
     97     return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
     98 }
     99 
    100 #endif
    101 
    102 #ifndef SK_IGNORE_TO_STRING
    103 void SkColorShader::toString(SkString* str) const {
    104     str->append("SkColorShader: (");
    105 
    106     str->append("Color: ");
    107     str->appendHex(fColor);
    108 
    109     this->INHERITED::toString(str);
    110 
    111     str->append(")");
    112 }
    113 #endif
    114 
    115 ///////////////////////////////////////////////////////////////////////////////////////////////////
    116 ///////////////////////////////////////////////////////////////////////////////////////////////////
    117 
    118 static unsigned unit_to_byte(float unit) {
    119     SkASSERT(unit >= 0 && unit <= 1);
    120     return (unsigned)(unit * 255 + 0.5);
    121 }
    122 
    123 static SkColor unit_to_skcolor(const SkColor4f& unit, SkColorSpace* cs) {
    124     return SkColorSetARGB(unit_to_byte(unit.fA), unit_to_byte(unit.fR),
    125                           unit_to_byte(unit.fG), unit_to_byte(unit.fB));
    126 }
    127 
    128 SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
    129     : fColorSpace(std::move(space))
    130     , fColor4(color)
    131     , fCachedByteColor(unit_to_skcolor(color.pin(), space.get()))
    132 {}
    133 
    134 sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
    135     SkColor4f color;
    136     buffer.readColor4f(&color);
    137     if (buffer.readBool()) {
    138         // TODO how do we unflatten colorspaces
    139     }
    140     return SkShader::MakeColorShader(color, nullptr);
    141 }
    142 
    143 void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
    144     buffer.writeColor4f(fColor4);
    145     buffer.writeBool(false);    // TODO how do we flatten colorspaces?
    146 }
    147 
    148 uint32_t SkColor4Shader::Color4Context::getFlags() const {
    149     return fFlags;
    150 }
    151 
    152 SkShader::Context* SkColor4Shader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
    153     return alloc->make<Color4Context>(*this, rec);
    154 }
    155 
    156 SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader,
    157                                                       const ContextRec& rec)
    158 : INHERITED(shader, rec)
    159 {
    160     SkColor color = shader.fCachedByteColor;
    161     unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
    162 
    163     unsigned r = SkColorGetR(color);
    164     unsigned g = SkColorGetG(color);
    165     unsigned b = SkColorGetB(color);
    166 
    167     if (a != 255) {
    168         r = SkMulDiv255Round(r, a);
    169         g = SkMulDiv255Round(g, a);
    170         b = SkMulDiv255Round(b, a);
    171     }
    172     fPMColor = SkPackARGB32(a, r, g, b);
    173 
    174     SkColor4f c4 = shader.fColor4;
    175     c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f);
    176     fPM4f = c4.premul();
    177 
    178     fFlags = kConstInY32_Flag;
    179     if (255 == a) {
    180         fFlags |= kOpaqueAlpha_Flag;
    181     }
    182 }
    183 
    184 void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], int count) {
    185     sk_memset32(span, fPMColor, count);
    186 }
    187 
    188 void SkColor4Shader::Color4Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    189     memset(alpha, SkGetPackedA32(fPMColor), count);
    190 }
    191 
    192 void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
    193     for (int i = 0; i < count; ++i) {
    194         span[i] = fPM4f;
    195     }
    196 }
    197 
    198 // TODO: do we need an updated version of this method for color4+colorspace?
    199 SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const {
    200     if (info) {
    201         if (info->fColors && info->fColorCount >= 1) {
    202             info->fColors[0] = fCachedByteColor;
    203         }
    204         info->fColorCount = 1;
    205         info->fTileMode = SkShader::kRepeat_TileMode;
    206     }
    207     return kColor_GradientType;
    208 }
    209 
    210 #if SK_SUPPORT_GPU
    211 
    212 #include "SkGr.h"
    213 #include "effects/GrConstColorProcessor.h"
    214 #include "GrColorSpaceXform.h"
    215 sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const {
    216     sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
    217                                                                        args.fDstColorSpace);
    218     GrColor4f color = GrColor4f::FromSkColor4f(fColor4);
    219     if (colorSpaceXform) {
    220         color = colorSpaceXform->apply(color);
    221     }
    222     return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode);
    223 }
    224 
    225 #endif
    226 
    227 #ifndef SK_IGNORE_TO_STRING
    228 void SkColor4Shader::toString(SkString* str) const {
    229     str->append("SkColor4Shader: (");
    230 
    231     str->append("RGBA:");
    232     for (int i = 0; i < 4; ++i) {
    233         str->appendf(" %g", fColor4.vec()[i]);
    234     }
    235     str->append(" )");
    236 }
    237 #endif
    238 
    239 sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) {
    240     if (!SkScalarsAreFinite(color.vec(), 4)) {
    241         return nullptr;
    242     }
    243     return sk_make_sp<SkColor4Shader>(color, std::move(space));
    244 }
    245 
    246 ///////////////////////////////////////////////////////////////////////////////////////////////////
    247 ///////////////////////////////////////////////////////////////////////////////////////////////////
    248 
    249 static void D32_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
    250                        int count) {
    251     SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0];
    252     const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
    253     proc(state->fMode, dst.writable_addr32(x, y), src, count, nullptr);
    254 }
    255 
    256 static void D32_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
    257                        int count, const SkAlpha aa[]) {
    258     SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0];
    259     const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
    260     proc(state->fMode, dst.writable_addr32(x, y), src, count, aa);
    261 }
    262 
    263 static void F16_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
    264                        int count) {
    265     SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0];
    266     const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
    267     proc(state->fMode, dst.writable_addr64(x, y), src, count, nullptr);
    268 }
    269 
    270 static void F16_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
    271                        int count, const SkAlpha aa[]) {
    272     SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0];
    273     const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
    274     proc(state->fMode, dst.writable_addr64(x, y), src, count, aa);
    275 }
    276 
    277 static bool choose_blitprocs(const SkPM4f* pm4, const SkImageInfo& info,
    278                              SkShader::Context::BlitState* state) {
    279     uint32_t flags = SkXfermode::kSrcIsSingle_D32Flag;
    280     if (pm4->a() == 1) {
    281         flags |= SkXfermode::kSrcIsOpaque_D32Flag;
    282     }
    283     switch (info.colorType()) {
    284         case kN32_SkColorType:
    285             if (info.gammaCloseToSRGB()) {
    286                 flags |= SkXfermode::kDstIsSRGB_D32Flag;
    287             }
    288             state->fStorage[0] = (void*)SkXfermode::GetD32Proc(state->fMode, flags);
    289             state->fStorage[1] = (void*)pm4;
    290             state->fBlitBW = D32_BlitBW;
    291             state->fBlitAA = D32_BlitAA;
    292             return true;
    293         case kRGBA_F16_SkColorType:
    294             state->fStorage[0] = (void*)SkXfermode::GetF16Proc(state->fMode, flags);
    295             state->fStorage[1] = (void*)pm4;
    296             state->fBlitBW = F16_BlitBW;
    297             state->fBlitAA = F16_BlitAA;
    298             return true;
    299         default:
    300             return false;
    301     }
    302 }
    303 
    304 bool SkColorShader::ColorShaderContext::onChooseBlitProcs(const SkImageInfo& info,
    305                                                           BlitState* state) {
    306     return choose_blitprocs(&fPM4f, info, state);
    307 }
    308 
    309 bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, BlitState* state) {
    310     return choose_blitprocs(&fPM4f, info, state);
    311 }
    312 
    313 bool SkColorShader::onAppendStages(SkRasterPipeline* p,
    314                                    SkColorSpace* dst,
    315                                    SkArenaAlloc* scratch,
    316                                    const SkMatrix&,
    317                                    const SkPaint&,
    318                                    const SkMatrix*) const {
    319     auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst));
    320     p->append(SkRasterPipeline::constant_color, color);
    321     return append_gamut_transform(p, scratch,
    322                                   SkColorSpace::MakeSRGB().get(), dst);
    323 }
    324 
    325 bool SkColor4Shader::onAppendStages(SkRasterPipeline* p,
    326                                     SkColorSpace* dst,
    327                                     SkArenaAlloc* scratch,
    328                                     const SkMatrix&,
    329                                     const SkPaint&,
    330                                     const SkMatrix*) const {
    331     auto color = scratch->make<SkPM4f>(fColor4.premul());
    332     p->append(SkRasterPipeline::constant_color, color);
    333     return append_gamut_transform(p, scratch, fColorSpace.get(), dst);
    334 }
    335