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 "SkColorData.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_constant_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 std::unique_ptr<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
    101         GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const {
    102     if (SkBlendMode::kDst == fMode) {
    103         return nullptr;
    104     }
    105 
    106     auto constFP = GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpaceInfo),
    107                                                GrConstColorProcessor::InputMode::kIgnore);
    108     auto fp = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode);
    109     if (!fp) {
    110         return nullptr;
    111     }
    112 #ifdef SK_DEBUG
    113     // With a solid color input this should always be able to compute the blended color
    114     // (at least for coeff modes)
    115     if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) {
    116         SkASSERT(fp->hasConstantOutputForConstantInput());
    117     }
    118 #endif
    119     return fp;
    120 }
    121 
    122 #endif
    123 
    124 ///////////////////////////////////////////////////////////////////////////////
    125 
    126 sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) {
    127     if (!SkIsValidMode(mode)) {
    128         return nullptr;
    129     }
    130 
    131     unsigned alpha = SkColorGetA(color);
    132 
    133     // first collaps some modes if possible
    134 
    135     if (SkBlendMode::kClear == mode) {
    136         color = 0;
    137         mode = SkBlendMode::kSrc;
    138     } else if (SkBlendMode::kSrcOver == mode) {
    139         if (0 == alpha) {
    140             mode = SkBlendMode::kDst;
    141         } else if (255 == alpha) {
    142             mode = SkBlendMode::kSrc;
    143         }
    144         // else just stay srcover
    145     }
    146 
    147     // weed out combinations that are noops, and just return null
    148     if (SkBlendMode::kDst == mode ||
    149         (0 == alpha && (SkBlendMode::kSrcOver == mode ||
    150                         SkBlendMode::kDstOver == mode ||
    151                         SkBlendMode::kDstOut == mode ||
    152                         SkBlendMode::kSrcATop == mode ||
    153                         SkBlendMode::kXor == mode ||
    154                         SkBlendMode::kDarken == mode)) ||
    155             (0xFF == alpha && SkBlendMode::kDstIn == mode)) {
    156         return nullptr;
    157     }
    158 
    159     return SkModeColorFilter::Make(color, mode);
    160 }
    161