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     this->INHERITED::flatten(buffer);
    204 
    205 #ifdef SK_DEBUG
    206     {
    207         Rec* rec = fRecs;
    208         int count = 0;
    209         while (rec) {
    210             rec = rec->fNext;
    211             count += 1;
    212         }
    213         SkASSERT(count == fCount);
    214     }
    215 #endif
    216 
    217     buffer.writeInt(fCount);
    218 
    219     Rec* rec = fRecs;
    220     for (int i = 0; i < fCount; i++) {
    221         // Legacy "flagsmask" field -- now ignored, remove when we bump version
    222         buffer.writeInt(0);
    223 
    224         buffer.writeInt(rec->fInfo.fPaintBits);
    225         buffer.writeInt(rec->fInfo.fColorMode);
    226         buffer.writePoint(rec->fInfo.fOffset);
    227         buffer.writeBool(rec->fInfo.fPostTranslate);
    228         buffer.writePaint(rec->fPaint);
    229         rec = rec->fNext;
    230     }
    231 }
    232 
    233 SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
    234     int count = buffer.readInt();
    235 
    236     Builder builder;
    237     for (int i = 0; i < count; i++) {
    238         LayerInfo info;
    239         // Legacy "flagsmask" field -- now ignored, remove when we bump version
    240         (void)buffer.readInt();
    241 
    242         info.fPaintBits = buffer.readInt();
    243         info.fColorMode = (SkXfermode::Mode)buffer.readInt();
    244         buffer.readPoint(&info.fOffset);
    245         info.fPostTranslate = buffer.readBool();
    246         buffer.readPaint(builder.addLayerOnTop(info));
    247     }
    248     SkLayerDrawLooper* looper = builder.detachLooper();
    249     SkASSERT(count == looper->fCount);
    250 
    251 #ifdef SK_DEBUG
    252     {
    253         Rec* rec = looper->fRecs;
    254         int n = 0;
    255         while (rec) {
    256             rec = rec->fNext;
    257             n += 1;
    258         }
    259         SkASSERT(count == n);
    260     }
    261 #endif
    262 
    263     return looper;
    264 }
    265 
    266 #ifndef SK_IGNORE_TO_STRING
    267 void SkLayerDrawLooper::toString(SkString* str) const {
    268     str->appendf("SkLayerDrawLooper (%d): ", fCount);
    269 
    270     Rec* rec = fRecs;
    271     for (int i = 0; i < fCount; i++) {
    272         str->appendf("%d: paintBits: (", i);
    273         if (0 == rec->fInfo.fPaintBits) {
    274             str->append("None");
    275         } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
    276             str->append("EntirePaint");
    277         } else {
    278             bool needSeparator = false;
    279             SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style",
    280                               &needSeparator);
    281             SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX",
    282                               &needSeparator);
    283             SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect",
    284                               &needSeparator);
    285             SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter",
    286                               &needSeparator);
    287             SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader",
    288                               &needSeparator);
    289             SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter",
    290                               &needSeparator);
    291             SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode",
    292                               &needSeparator);
    293         }
    294         str->append(") ");
    295 
    296         static const char* gModeStrings[SkXfermode::kLastMode+1] = {
    297             "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
    298             "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
    299             "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
    300             "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
    301         };
    302 
    303         str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]);
    304 
    305         str->append("offset: (");
    306         str->appendScalar(rec->fInfo.fOffset.fX);
    307         str->append(", ");
    308         str->appendScalar(rec->fInfo.fOffset.fY);
    309         str->append(") ");
    310 
    311         str->append("postTranslate: ");
    312         if (rec->fInfo.fPostTranslate) {
    313             str->append("true ");
    314         } else {
    315             str->append("false ");
    316         }
    317 
    318         rec->fPaint.toString(str);
    319         rec = rec->fNext;
    320     }
    321 }
    322 #endif
    323 
    324 SkLayerDrawLooper::Builder::Builder()
    325         : fRecs(NULL),
    326           fTopRec(NULL),
    327           fCount(0) {
    328 }
    329 
    330 SkLayerDrawLooper::Builder::~Builder() {
    331     Rec* rec = fRecs;
    332     while (rec) {
    333         Rec* next = rec->fNext;
    334         SkDELETE(rec);
    335         rec = next;
    336     }
    337 }
    338 
    339 SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
    340     fCount += 1;
    341 
    342     Rec* rec = SkNEW(Rec);
    343     rec->fNext = fRecs;
    344     rec->fInfo = info;
    345     fRecs = rec;
    346     if (NULL == fTopRec) {
    347         fTopRec = rec;
    348     }
    349 
    350     return &rec->fPaint;
    351 }
    352 
    353 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
    354     LayerInfo info;
    355 
    356     info.fOffset.set(dx, dy);
    357     (void)this->addLayer(info);
    358 }
    359 
    360 SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
    361     fCount += 1;
    362 
    363     Rec* rec = SkNEW(Rec);
    364     rec->fNext = NULL;
    365     rec->fInfo = info;
    366     if (NULL == fRecs) {
    367         fRecs = rec;
    368     } else {
    369         SkASSERT(NULL != fTopRec);
    370         fTopRec->fNext = rec;
    371     }
    372     fTopRec = rec;
    373 
    374     return &rec->fPaint;
    375 }
    376 
    377 SkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() {
    378     SkLayerDrawLooper* looper = SkNEW(SkLayerDrawLooper);
    379     looper->fCount = fCount;
    380     looper->fRecs = fRecs;
    381 
    382     fCount = 0;
    383     fRecs = NULL;
    384     fTopRec = NULL;
    385 
    386     return looper;
    387 }
    388