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