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