Home | History | Annotate | Download | only in core
      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 "SkBlendModePriv.h"
      9 #include "SkRasterPipeline.h"
     10 
     11 bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) {
     12     switch (mode) {
     13         case SkBlendMode::kDst:
     14         case SkBlendMode::kSrcOver:
     15         case SkBlendMode::kDstOver:
     16         case SkBlendMode::kDstOut:
     17         case SkBlendMode::kSrcATop:
     18         case SkBlendMode::kXor:
     19         case SkBlendMode::kPlus:
     20             return true;
     21         default:
     22             break;
     23     }
     24     return false;
     25 }
     26 
     27 struct CoeffRec {
     28     SkBlendModeCoeff    fSrc;
     29     SkBlendModeCoeff    fDst;
     30 };
     31 
     32 const CoeffRec gCoeffs[] = {
     33     { SkBlendModeCoeff::kZero,    SkBlendModeCoeff::kZero },
     34     { SkBlendModeCoeff::kOne,     SkBlendModeCoeff::kZero },
     35     { SkBlendModeCoeff::kZero,    SkBlendModeCoeff::kOne  },
     36     { SkBlendModeCoeff::kOne,     SkBlendModeCoeff::kISA  },
     37     { SkBlendModeCoeff::kIDA,     SkBlendModeCoeff::kOne  },
     38     { SkBlendModeCoeff::kDA,      SkBlendModeCoeff::kZero },
     39     { SkBlendModeCoeff::kZero,    SkBlendModeCoeff::kSA   },
     40     { SkBlendModeCoeff::kIDA,     SkBlendModeCoeff::kZero },
     41     { SkBlendModeCoeff::kZero,    SkBlendModeCoeff::kISA  },
     42     { SkBlendModeCoeff::kDA,      SkBlendModeCoeff::kISA  },
     43     { SkBlendModeCoeff::kIDA,     SkBlendModeCoeff::kSA   },
     44     { SkBlendModeCoeff::kIDA,     SkBlendModeCoeff::kISA  },
     45 
     46     { SkBlendModeCoeff::kOne,     SkBlendModeCoeff::kOne  },
     47     { SkBlendModeCoeff::kZero,    SkBlendModeCoeff::kSC   },
     48     { SkBlendModeCoeff::kOne,     SkBlendModeCoeff::kISC  },    // screen
     49 };
     50 
     51 bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoeff* dst) {
     52     if (mode > SkBlendMode::kScreen) {
     53         return false;
     54     }
     55     if (src) {
     56         *src = gCoeffs[static_cast<int>(mode)].fSrc;
     57     }
     58     if (dst) {
     59         *dst = gCoeffs[static_cast<int>(mode)].fDst;
     60     }
     61     return true;
     62 }
     63 
     64 void SkBlendMode_AppendStagesNoClamp(SkBlendMode mode, SkRasterPipeline* p) {
     65     auto stage = SkRasterPipeline::srcover;
     66     switch (mode) {
     67         case SkBlendMode::kClear:    stage = SkRasterPipeline::clear; break;
     68         case SkBlendMode::kSrc:      return;  // This stage is a no-op.
     69         case SkBlendMode::kDst:      stage = SkRasterPipeline::move_dst_src; break;
     70         case SkBlendMode::kSrcOver:  stage = SkRasterPipeline::srcover; break;
     71         case SkBlendMode::kDstOver:  stage = SkRasterPipeline::dstover; break;
     72         case SkBlendMode::kSrcIn:    stage = SkRasterPipeline::srcin; break;
     73         case SkBlendMode::kDstIn:    stage = SkRasterPipeline::dstin; break;
     74         case SkBlendMode::kSrcOut:   stage = SkRasterPipeline::srcout; break;
     75         case SkBlendMode::kDstOut:   stage = SkRasterPipeline::dstout; break;
     76         case SkBlendMode::kSrcATop:  stage = SkRasterPipeline::srcatop; break;
     77         case SkBlendMode::kDstATop:  stage = SkRasterPipeline::dstatop; break;
     78         case SkBlendMode::kXor:      stage = SkRasterPipeline::xor_; break;
     79         case SkBlendMode::kPlus:     stage = SkRasterPipeline::plus_; break;
     80         case SkBlendMode::kModulate: stage = SkRasterPipeline::modulate; break;
     81 
     82         case SkBlendMode::kScreen:     stage = SkRasterPipeline::screen; break;
     83         case SkBlendMode::kOverlay:    stage = SkRasterPipeline::overlay; break;
     84         case SkBlendMode::kDarken:     stage = SkRasterPipeline::darken; break;
     85         case SkBlendMode::kLighten:    stage = SkRasterPipeline::lighten; break;
     86         case SkBlendMode::kColorDodge: stage = SkRasterPipeline::colordodge; break;
     87         case SkBlendMode::kColorBurn:  stage = SkRasterPipeline::colorburn; break;
     88         case SkBlendMode::kHardLight:  stage = SkRasterPipeline::hardlight; break;
     89         case SkBlendMode::kSoftLight:  stage = SkRasterPipeline::softlight; break;
     90         case SkBlendMode::kDifference: stage = SkRasterPipeline::difference; break;
     91         case SkBlendMode::kExclusion:  stage = SkRasterPipeline::exclusion; break;
     92         case SkBlendMode::kMultiply:   stage = SkRasterPipeline::multiply; break;
     93 
     94         case SkBlendMode::kHue:        stage = SkRasterPipeline::hue; break;
     95         case SkBlendMode::kSaturation: stage = SkRasterPipeline::saturation; break;
     96         case SkBlendMode::kColor:      stage = SkRasterPipeline::color; break;
     97         case SkBlendMode::kLuminosity: stage = SkRasterPipeline::luminosity; break;
     98     }
     99     p->append(stage);
    100 }
    101 
    102 void SkBlendMode_AppendClampIfNeeded(SkBlendMode mode, SkRasterPipeline* p) {
    103     if (mode == SkBlendMode::kPlus) {
    104         // Both clamp_a and clamp_1 would preserve premultiplication invariants here,
    105         // so we pick clamp_1 for being a smidge faster.
    106         p->append(SkRasterPipeline::clamp_1);
    107     }
    108 }
    109 
    110 SkPM4f SkBlendMode_Apply(SkBlendMode mode, const SkPM4f& src, const SkPM4f& dst) {
    111     // special-case simple/common modes...
    112     switch (mode) {
    113         case SkBlendMode::kClear:   return {{ 0, 0, 0, 0 }};
    114         case SkBlendMode::kSrc:     return src;
    115         case SkBlendMode::kDst:     return dst;
    116         case SkBlendMode::kSrcOver:
    117             return SkPM4f::From4f(src.to4f() + dst.to4f() * Sk4f(1 - src.a()));
    118         default:
    119             break;
    120     }
    121 
    122     SkRasterPipeline_<256> p;
    123     SkPM4f                 src_storage = src,
    124                            dst_storage = dst,
    125                            result_storage,
    126                            *src_ctx = &src_storage,
    127                            *dst_ctx = &dst_storage,
    128                            *res_ctx = &result_storage;
    129 
    130     p.append(SkRasterPipeline::load_f32, &dst_ctx);
    131     p.append(SkRasterPipeline::move_src_dst);
    132     p.append(SkRasterPipeline::load_f32, &src_ctx);
    133     SkBlendMode_AppendStages(mode, &p);
    134     p.append(SkRasterPipeline::store_f32, &res_ctx);
    135     p.run(0, 0, 1);
    136     return result_storage;
    137 }
    138