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