Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2011 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 #include "SkArenaAlloc.h"
      8 #include "SkBlurDrawLooper.h"
      9 #include "SkBlurMaskFilter.h"
     10 #include "SkCanvas.h"
     11 #include "SkColorSpaceXformer.h"
     12 #include "SkColor.h"
     13 #include "SkReadBuffer.h"
     14 #include "SkWriteBuffer.h"
     15 #include "SkLayerDrawLooper.h"
     16 #include "SkString.h"
     17 #include "SkStringUtils.h"
     18 #include "SkUnPreMultiply.h"
     19 #include "SkXfermodePriv.h"
     20 
     21 SkLayerDrawLooper::LayerInfo::LayerInfo() {
     22     fPaintBits = 0;                     // ignore our paint fields
     23     fColorMode = SkBlendMode::kDst;     // ignore our color
     24     fOffset.set(0, 0);
     25     fPostTranslate = false;
     26 }
     27 
     28 SkLayerDrawLooper::SkLayerDrawLooper()
     29         : fRecs(nullptr),
     30           fCount(0) {
     31 }
     32 
     33 SkLayerDrawLooper::~SkLayerDrawLooper() {
     34     Rec* rec = fRecs;
     35     while (rec) {
     36         Rec* next = rec->fNext;
     37         delete rec;
     38         rec = next;
     39     }
     40 }
     41 
     42 SkLayerDrawLooper::Context*
     43 SkLayerDrawLooper::makeContext(SkCanvas* canvas, SkArenaAlloc* alloc) const {
     44     canvas->save();
     45     return alloc->make<LayerDrawLooperContext>(this);
     46 }
     47 
     48 static SkColor xferColor(SkColor src, SkColor dst, SkBlendMode mode) {
     49     switch (mode) {
     50         case SkBlendMode::kSrc:
     51             return src;
     52         case SkBlendMode::kDst:
     53             return dst;
     54         default: {
     55             SkPMColor pmS = SkPreMultiplyColor(src);
     56             SkPMColor pmD = SkPreMultiplyColor(dst);
     57             SkXfermode::Peek(mode)->xfer32(&pmD, &pmS, 1, nullptr);
     58             return SkUnPreMultiply::PMColorToColor(pmD);
     59         }
     60     }
     61 }
     62 
     63 // Even with kEntirePaint_Bits, we always ensure that the master paint's
     64 // text-encoding is respected, since that controls how we interpret the
     65 // text/length parameters of a draw[Pos]Text call.
     66 void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
     67         SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
     68     SkColor srcColor = src.getColor();
     69 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
     70     // The framework may respect the alpha value on the original paint.
     71     // Match this legacy behavior.
     72     if (SkColorGetA(srcColor) == 255) {
     73         srcColor = SkColorSetA(srcColor, dst->getAlpha());
     74     }
     75 #endif
     76     dst->setColor(xferColor(srcColor, dst->getColor(), (SkBlendMode)info.fColorMode));
     77 
     78     BitFlags bits = info.fPaintBits;
     79     SkPaint::TextEncoding encoding = dst->getTextEncoding();
     80 
     81     if (0 == bits) {
     82         return;
     83     }
     84     if (kEntirePaint_Bits == bits) {
     85         // we've already computed these, so save it from the assignment
     86         uint32_t f = dst->getFlags();
     87         SkColor c = dst->getColor();
     88         *dst = src;
     89         dst->setFlags(f);
     90         dst->setColor(c);
     91         dst->setTextEncoding(encoding);
     92         return;
     93     }
     94 
     95     if (bits & kStyle_Bit) {
     96         dst->setStyle(src.getStyle());
     97         dst->setStrokeWidth(src.getStrokeWidth());
     98         dst->setStrokeMiter(src.getStrokeMiter());
     99         dst->setStrokeCap(src.getStrokeCap());
    100         dst->setStrokeJoin(src.getStrokeJoin());
    101     }
    102 
    103     if (bits & kTextSkewX_Bit) {
    104         dst->setTextSkewX(src.getTextSkewX());
    105     }
    106 
    107     if (bits & kPathEffect_Bit) {
    108         dst->setPathEffect(src.refPathEffect());
    109     }
    110     if (bits & kMaskFilter_Bit) {
    111         dst->setMaskFilter(src.refMaskFilter());
    112     }
    113     if (bits & kShader_Bit) {
    114         dst->setShader(src.refShader());
    115     }
    116     if (bits & kColorFilter_Bit) {
    117         dst->setColorFilter(src.refColorFilter());
    118     }
    119     if (bits & kXfermode_Bit) {
    120         dst->setBlendMode(src.getBlendMode());
    121     }
    122 
    123     // we don't override these
    124 #if 0
    125     dst->setTypeface(src.getTypeface());
    126     dst->setTextSize(src.getTextSize());
    127     dst->setTextScaleX(src.getTextScaleX());
    128     dst->setRasterizer(src.getRasterizer());
    129     dst->setLooper(src.getLooper());
    130     dst->setTextEncoding(src.getTextEncoding());
    131     dst->setHinting(src.getHinting());
    132 #endif
    133 }
    134 
    135 // Should we add this to canvas?
    136 static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
    137     SkMatrix m = canvas->getTotalMatrix();
    138     m.postTranslate(dx, dy);
    139     canvas->setMatrix(m);
    140 }
    141 
    142 SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
    143         const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
    144 
    145 bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas,
    146                                                      SkPaint* paint) {
    147     canvas->restore();
    148     if (nullptr == fCurrRec) {
    149         return false;
    150     }
    151 
    152     ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
    153 
    154     canvas->save();
    155     if (fCurrRec->fInfo.fPostTranslate) {
    156         postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
    157                       fCurrRec->fInfo.fOffset.fY);
    158     } else {
    159         canvas->translate(fCurrRec->fInfo.fOffset.fX,
    160                           fCurrRec->fInfo.fOffset.fY);
    161     }
    162     fCurrRec = fCurrRec->fNext;
    163 
    164     return true;
    165 }
    166 
    167 bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
    168     if (fCount != 2) {
    169         return false;
    170     }
    171     const Rec* rec = fRecs;
    172 
    173     // bottom layer needs to be just blur(maskfilter)
    174     if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
    175         return false;
    176     }
    177     if (SkBlendMode::kSrc != (SkBlendMode)rec->fInfo.fColorMode) {
    178         return false;
    179     }
    180     const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
    181     if (nullptr == mf) {
    182         return false;
    183     }
    184     SkMaskFilter::BlurRec maskBlur;
    185     if (!mf->asABlur(&maskBlur)) {
    186         return false;
    187     }
    188 
    189     rec = rec->fNext;
    190     // top layer needs to be "plain"
    191     if (rec->fInfo.fPaintBits) {
    192         return false;
    193     }
    194     if (SkBlendMode::kDst != (SkBlendMode)rec->fInfo.fColorMode) {
    195         return false;
    196     }
    197     if (!rec->fInfo.fOffset.equals(0, 0)) {
    198         return false;
    199     }
    200 
    201     if (bsRec) {
    202         bsRec->fSigma = maskBlur.fSigma;
    203         bsRec->fOffset = fRecs->fInfo.fOffset;
    204         bsRec->fColor = fRecs->fPaint.getColor();
    205         bsRec->fStyle = maskBlur.fStyle;
    206         bsRec->fQuality = maskBlur.fQuality;
    207     }
    208     return true;
    209 }
    210 
    211 sk_sp<SkDrawLooper> SkLayerDrawLooper::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
    212     if (!fCount) {
    213         return sk_ref_sp(const_cast<SkLayerDrawLooper*>(this));
    214     }
    215 
    216     auto looper = sk_sp<SkLayerDrawLooper>(new SkLayerDrawLooper());
    217     looper->fCount = fCount;
    218 
    219     Rec* oldRec = fRecs;
    220     Rec* newTopRec = new Rec();
    221     newTopRec->fInfo = oldRec->fInfo;
    222     newTopRec->fPaint = xformer->apply(oldRec->fPaint);
    223     newTopRec->fNext = nullptr;
    224 
    225     Rec* prevNewRec = newTopRec;
    226     oldRec = oldRec->fNext;
    227     while (oldRec) {
    228         Rec* newRec = new Rec();
    229         newRec->fInfo = oldRec->fInfo;
    230         newRec->fPaint = xformer->apply(oldRec->fPaint);
    231         newRec->fNext = nullptr;
    232         prevNewRec->fNext = newRec;
    233 
    234         prevNewRec = newRec;
    235         oldRec = oldRec->fNext;
    236     }
    237 
    238     looper->fRecs = newTopRec;
    239     return std::move(looper);
    240 }
    241 
    242 ///////////////////////////////////////////////////////////////////////////////
    243 
    244 void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
    245     buffer.writeInt(fCount);
    246 
    247     Rec* rec = fRecs;
    248     for (int i = 0; i < fCount; i++) {
    249         // Legacy "flagsmask" field -- now ignored, remove when we bump version
    250         buffer.writeInt(0);
    251 
    252         buffer.writeInt(rec->fInfo.fPaintBits);
    253         buffer.writeInt((int)rec->fInfo.fColorMode);
    254         buffer.writePoint(rec->fInfo.fOffset);
    255         buffer.writeBool(rec->fInfo.fPostTranslate);
    256         buffer.writePaint(rec->fPaint);
    257         rec = rec->fNext;
    258     }
    259 }
    260 
    261 sk_sp<SkFlattenable> SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
    262     int count = buffer.readInt();
    263 
    264     Builder builder;
    265     for (int i = 0; i < count; i++) {
    266         LayerInfo info;
    267         // Legacy "flagsmask" field -- now ignored, remove when we bump version
    268         (void)buffer.readInt();
    269 
    270         info.fPaintBits = buffer.readInt();
    271         info.fColorMode = (SkBlendMode)buffer.readInt();
    272         buffer.readPoint(&info.fOffset);
    273         info.fPostTranslate = buffer.readBool();
    274         buffer.readPaint(builder.addLayerOnTop(info));
    275     }
    276     return builder.detach();
    277 }
    278 
    279 #ifndef SK_IGNORE_TO_STRING
    280 void SkLayerDrawLooper::toString(SkString* str) const {
    281     str->appendf("SkLayerDrawLooper (%d): ", fCount);
    282 
    283     Rec* rec = fRecs;
    284     for (int i = 0; i < fCount; i++) {
    285         str->appendf("%d: paintBits: (", i);
    286         if (0 == rec->fInfo.fPaintBits) {
    287             str->append("None");
    288         } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
    289             str->append("EntirePaint");
    290         } else {
    291             bool needSeparator = false;
    292             SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style",
    293                               &needSeparator);
    294             SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX",
    295                               &needSeparator);
    296             SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect",
    297                               &needSeparator);
    298             SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter",
    299                               &needSeparator);
    300             SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader",
    301                               &needSeparator);
    302             SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter",
    303                               &needSeparator);
    304             SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode",
    305                               &needSeparator);
    306         }
    307         str->append(") ");
    308 
    309         static const char* gModeStrings[(int)SkBlendMode::kLastMode+1] = {
    310             "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
    311             "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
    312             "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
    313             "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
    314         };
    315 
    316         str->appendf("mode: %s ", gModeStrings[(int)rec->fInfo.fColorMode]);
    317 
    318         str->append("offset: (");
    319         str->appendScalar(rec->fInfo.fOffset.fX);
    320         str->append(", ");
    321         str->appendScalar(rec->fInfo.fOffset.fY);
    322         str->append(") ");
    323 
    324         str->append("postTranslate: ");
    325         if (rec->fInfo.fPostTranslate) {
    326             str->append("true ");
    327         } else {
    328             str->append("false ");
    329         }
    330 
    331         rec->fPaint.toString(str);
    332         rec = rec->fNext;
    333     }
    334 }
    335 #endif
    336 
    337 SkLayerDrawLooper::Builder::Builder()
    338         : fRecs(nullptr),
    339           fTopRec(nullptr),
    340           fCount(0) {
    341 }
    342 
    343 SkLayerDrawLooper::Builder::~Builder() {
    344     Rec* rec = fRecs;
    345     while (rec) {
    346         Rec* next = rec->fNext;
    347         delete rec;
    348         rec = next;
    349     }
    350 }
    351 
    352 SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
    353     fCount += 1;
    354 
    355     Rec* rec = new Rec;
    356     rec->fNext = fRecs;
    357     rec->fInfo = info;
    358     fRecs = rec;
    359     if (nullptr == fTopRec) {
    360         fTopRec = rec;
    361     }
    362 
    363     return &rec->fPaint;
    364 }
    365 
    366 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
    367     LayerInfo info;
    368 
    369     info.fOffset.set(dx, dy);
    370     (void)this->addLayer(info);
    371 }
    372 
    373 SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
    374     fCount += 1;
    375 
    376     Rec* rec = new Rec;
    377     rec->fNext = nullptr;
    378     rec->fInfo = info;
    379     if (nullptr == fRecs) {
    380         fRecs = rec;
    381     } else {
    382         SkASSERT(fTopRec);
    383         fTopRec->fNext = rec;
    384     }
    385     fTopRec = rec;
    386 
    387     return &rec->fPaint;
    388 }
    389 
    390 sk_sp<SkDrawLooper> SkLayerDrawLooper::Builder::detach() {
    391     SkLayerDrawLooper* looper = new SkLayerDrawLooper;
    392     looper->fCount = fCount;
    393     looper->fRecs = fRecs;
    394 
    395     fCount = 0;
    396     fRecs = nullptr;
    397     fTopRec = nullptr;
    398 
    399     return sk_sp<SkDrawLooper>(looper);
    400 }
    401 
    402 sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy)
    403 {
    404     sk_sp<SkMaskFilter> blur = nullptr;
    405     if (sigma > 0.0f) {
    406         blur = SkBlurMaskFilter::Make(kNormal_SkBlurStyle, sigma, SkBlurMaskFilter::kNone_BlurFlag);
    407     }
    408 
    409     SkLayerDrawLooper::Builder builder;
    410 
    411     // First layer
    412     SkLayerDrawLooper::LayerInfo defaultLayer;
    413     builder.addLayer(defaultLayer);
    414 
    415     // Blur layer
    416     SkLayerDrawLooper::LayerInfo blurInfo;
    417     blurInfo.fColorMode = SkBlendMode::kSrc;
    418     blurInfo.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
    419     blurInfo.fOffset = SkVector::Make(dx, dy);
    420     SkPaint* paint = builder.addLayer(blurInfo);
    421     paint->setMaskFilter(std::move(blur));
    422     paint->setColor(color);
    423 
    424     return builder.detach();
    425 }
    426