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