Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 "SkBlendModePriv.h"
     10 #include "SkBlitRow.h"
     11 #include "SkColorFilter.h"
     12 #include "SkColorPriv.h"
     13 #include "SkColorSpaceXformer.h"
     14 #include "SkModeColorFilter.h"
     15 #include "SkPM4f.h"
     16 #include "SkPM4fPriv.h"
     17 #include "SkRandom.h"
     18 #include "SkRasterPipeline.h"
     19 #include "SkReadBuffer.h"
     20 #include "SkString.h"
     21 #include "SkUtils.h"
     22 #include "SkValidationUtils.h"
     23 #include "SkWriteBuffer.h"
     24 
     25 //////////////////////////////////////////////////////////////////////////////////////////////////
     26 
     27 SkModeColorFilter::SkModeColorFilter(SkColor color, SkBlendMode mode) {
     28     fColor = color;
     29     fMode = mode;
     30     // cache
     31     fPMColor = SkPreMultiplyColor(fColor);
     32 }
     33 
     34 #ifndef SK_IGNORE_TO_STRING
     35 void SkModeColorFilter::toString(SkString* str) const {
     36     str->append("SkModeColorFilter: color: 0x");
     37     str->appendHex(fColor);
     38     str->append(" mode: ");
     39     str->append(SkBlendMode_Name(fMode));
     40 }
     41 #endif
     42 
     43 bool SkModeColorFilter::asColorMode(SkColor* color, SkBlendMode* mode) const {
     44     if (color) {
     45         *color = fColor;
     46     }
     47     if (mode) {
     48         *mode = fMode;
     49     }
     50     return true;
     51 }
     52 
     53 uint32_t SkModeColorFilter::getFlags() const {
     54     uint32_t flags = 0;
     55     switch (fMode) {
     56         case SkBlendMode::kDst:      //!< [Da, Dc]
     57         case SkBlendMode::kSrcATop:  //!< [Da, Sc * Da + (1 - Sa) * Dc]
     58             flags |= kAlphaUnchanged_Flag;
     59         default:
     60             break;
     61     }
     62     return flags;
     63 }
     64 
     65 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
     66     buffer.writeColor(fColor);
     67     buffer.writeUInt((int)fMode);
     68 }
     69 
     70 sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
     71     SkColor color = buffer.readColor();
     72     SkBlendMode mode = (SkBlendMode)buffer.readUInt();
     73     return SkColorFilter::MakeModeFilter(color, mode);
     74 }
     75 
     76 void SkModeColorFilter::onAppendStages(SkRasterPipeline* p,
     77                                        SkColorSpace* dst,
     78                                        SkArenaAlloc* scratch,
     79                                        bool shaderIsOpaque) const {
     80     p->append(SkRasterPipeline::move_src_dst);
     81     p->append_uniform_color(scratch, SkPM4f_from_SkColor(fColor, dst));
     82     SkBlendMode_AppendStages(fMode, p);
     83 }
     84 
     85 sk_sp<SkColorFilter> SkModeColorFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
     86     SkColor color = xformer->apply(fColor);
     87     if (color != fColor) {
     88         return SkColorFilter::MakeModeFilter(color, fMode);
     89     }
     90     return this->INHERITED::onMakeColorSpace(xformer);
     91 }
     92 
     93 ///////////////////////////////////////////////////////////////////////////////
     94 #if SK_SUPPORT_GPU
     95 #include "GrBlend.h"
     96 #include "effects/GrXfermodeFragmentProcessor.h"
     97 #include "effects/GrConstColorProcessor.h"
     98 #include "SkGr.h"
     99 
    100 sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
    101                                                     GrContext*, SkColorSpace* dstColorSpace) const {
    102     if (SkBlendMode::kDst == fMode) {
    103         return nullptr;
    104     }
    105 
    106     sk_sp<GrFragmentProcessor> constFP(
    107         GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace),
    108                                     GrConstColorProcessor::kIgnore_InputMode));
    109     sk_sp<GrFragmentProcessor> fp(
    110         GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode));
    111     if (!fp) {
    112         return nullptr;
    113     }
    114 #ifdef SK_DEBUG
    115     // With a solid color input this should always be able to compute the blended color
    116     // (at least for coeff modes)
    117     if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) {
    118         SkASSERT(fp->hasConstantOutputForConstantInput());
    119     }
    120 #endif
    121     return fp;
    122 }
    123 
    124 #endif
    125 
    126 ///////////////////////////////////////////////////////////////////////////////
    127 
    128 sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) {
    129     if (!SkIsValidMode(mode)) {
    130         return nullptr;
    131     }
    132 
    133     unsigned alpha = SkColorGetA(color);
    134 
    135     // first collaps some modes if possible
    136 
    137     if (SkBlendMode::kClear == mode) {
    138         color = 0;
    139         mode = SkBlendMode::kSrc;
    140     } else if (SkBlendMode::kSrcOver == mode) {
    141         if (0 == alpha) {
    142             mode = SkBlendMode::kDst;
    143         } else if (255 == alpha) {
    144             mode = SkBlendMode::kSrc;
    145         }
    146         // else just stay srcover
    147     }
    148 
    149     // weed out combinations that are noops, and just return null
    150     if (SkBlendMode::kDst == mode ||
    151         (0 == alpha && (SkBlendMode::kSrcOver == mode ||
    152                         SkBlendMode::kDstOver == mode ||
    153                         SkBlendMode::kDstOut == mode ||
    154                         SkBlendMode::kSrcATop == mode ||
    155                         SkBlendMode::kXor == mode ||
    156                         SkBlendMode::kDarken == mode)) ||
    157             (0xFF == alpha && SkBlendMode::kDstIn == mode)) {
    158         return nullptr;
    159     }
    160 
    161     return SkModeColorFilter::Make(color, mode);
    162 }
    163