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