SkLayerDrawLooper.cpp revision daaafa6e81860e3dc52660ba019c336f0a43f1e7
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
90716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include "SkColor.h"
108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkLayerDrawLooper.h"
134991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com#include "SkString.h"
144991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com#include "SkStringUtils.h"
150716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include "SkUnPreMultiply.h"
160716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com
170716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comSkLayerDrawLooper::LayerInfo::LayerInfo() {
18a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org    fPaintBits = 0;                     // ignore our paint fields
190716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    fColorMode = SkXfermode::kDst_Mode; // ignore our color
200716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    fOffset.set(0, 0);
210716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    fPostTranslate = false;
220716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com}
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
243c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.orgSkLayerDrawLooper::SkLayerDrawLooper()
253c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org        : fRecs(NULL),
268f838259ab65e44562902679fa88cb00575b99cecommit-bot@chromium.org          fTopRec(NULL),
2779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org          fCount(0) {
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkLayerDrawLooper::~SkLayerDrawLooper() {
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Rec* rec = fRecs;
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (rec) {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Rec* next = rec->fNext;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(rec);
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec = next;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
380716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com
3979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.orgSkLayerDrawLooper::Context* SkLayerDrawLooper::createContext(SkCanvas* canvas, void* storage) const {
40091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    canvas->save();
4179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    return SkNEW_PLACEMENT_ARGS(storage, LayerDrawLooperContext, (this));
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
440716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comstatic SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
450716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    switch (mode) {
460716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        case SkXfermode::kSrc_Mode:
470716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com            return src;
480716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        case SkXfermode::kDst_Mode:
490716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com            return dst;
500716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        default: {
510716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com            SkPMColor pmS = SkPreMultiplyColor(src);
520716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com            SkPMColor pmD = SkPreMultiplyColor(dst);
530716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com            SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
540716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com            return SkUnPreMultiply::PMColorToColor(result);
550716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        }
560716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    }
570716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com}
580716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com
598426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com// Even with kEntirePaint_Bits, we always ensure that the master paint's
608426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com// text-encoding is respected, since that controls how we interpret the
618426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com// text/length parameters of a draw[Pos]Text call.
6279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.orgvoid SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
6379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
64a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org
65a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org    dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
66a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org
67a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org    BitFlags bits = info.fPaintBits;
688426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com    SkPaint::TextEncoding encoding = dst->getTextEncoding();
690716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com
703c1225bee4d9ea0963acf47fc5df080b2d5b26b2mike@reedtribe.org    if (0 == bits) {
713c1225bee4d9ea0963acf47fc5df080b2d5b26b2mike@reedtribe.org        return;
723c1225bee4d9ea0963acf47fc5df080b2d5b26b2mike@reedtribe.org    }
730e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (kEntirePaint_Bits == bits) {
74a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org        // we've already computed these, so save it from the assignment
75a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org        uint32_t f = dst->getFlags();
760716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        SkColor c = dst->getColor();
770e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        *dst = src;
78a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org        dst->setFlags(f);
790716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        dst->setColor(c);
808426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com        dst->setTextEncoding(encoding);
810e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        return;
820e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
830e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org
840e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kStyle_Bit) {
850e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setStyle(src.getStyle());
860e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setStrokeWidth(src.getStrokeWidth());
870e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setStrokeMiter(src.getStrokeMiter());
880e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setStrokeCap(src.getStrokeCap());
890e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setStrokeJoin(src.getStrokeJoin());
900e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
910e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org
920e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kTextSkewX_Bit) {
930e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setTextSkewX(src.getTextSkewX());
940e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
950e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org
960e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kPathEffect_Bit) {
970e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setPathEffect(src.getPathEffect());
980e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
990e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kMaskFilter_Bit) {
1000e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setMaskFilter(src.getMaskFilter());
1010e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
1020e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kShader_Bit) {
1030e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setShader(src.getShader());
1040e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
1050e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kColorFilter_Bit) {
1060e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setColorFilter(src.getColorFilter());
1070e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
1080e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    if (bits & kXfermode_Bit) {
1090e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org        dst->setXfermode(src.getXfermode());
1100e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    }
1110e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org
1128426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com    // we don't override these
1130e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org#if 0
1140e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setTypeface(src.getTypeface());
1150e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setTextSize(src.getTextSize());
1160e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setTextScaleX(src.getTextScaleX());
1170e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setRasterizer(src.getRasterizer());
1180e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setLooper(src.getLooper());
1190e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setTextEncoding(src.getTextEncoding());
1200e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org    dst->setHinting(src.getHinting());
1210e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org#endif
1220e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org}
1230e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org
1240716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com// Should we add this to canvas?
1250716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comstatic void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
1260716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    SkMatrix m = canvas->getTotalMatrix();
1270716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    m.postTranslate(dx, dy);
1280716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    canvas->setMatrix(m);
1290716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com}
1300716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com
13179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.orgSkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
13279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
13379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org
13479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.orgbool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas,
13579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                                                     SkPaint* paint) {
1364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    canvas->restore();
1374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (NULL == fCurrRec) {
1384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org    ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
1420716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com
143091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    canvas->save();
1440716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    if (fCurrRec->fInfo.fPostTranslate) {
1450716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
1460716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com                      fCurrRec->fInfo.fOffset.fY);
1470716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    } else {
14879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        canvas->translate(fCurrRec->fInfo.fOffset.fX,
14979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                          fCurrRec->fInfo.fOffset.fY);
1500716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com    }
151e5d0def6d9864463565f9ca6a6e9ceedcb72712dmike@reedtribe.org    fCurrRec = fCurrRec->fNext;
152e5d0def6d9864463565f9ca6a6e9ceedcb72712dmike@reedtribe.org
1534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
156daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.combool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
157daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (fCount != 2) {
158daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
159daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
160daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    const Rec* rec = fRecs;
161daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
162daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    // bottom layer needs to be just blur(maskfilter)
163daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
164daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
165daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
166daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (SkXfermode::kSrc_Mode != rec->fInfo.fColorMode) {
167daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
168daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
169daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
170daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (NULL == mf) {
171daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
172daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
173daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    SkMaskFilter::BlurRec maskBlur;
174daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (!mf->asABlur(&maskBlur)) {
175daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
176daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
177daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
178daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    rec = rec->fNext;
179daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    // top layer needs to be "plain"
180daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (rec->fInfo.fPaintBits) {
181daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
182daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
183daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (SkXfermode::kDst_Mode != rec->fInfo.fColorMode) {
184daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
185daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
186daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (!rec->fInfo.fOffset.equals(0, 0)) {
187daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
188daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
189daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
190daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (bsRec) {
191daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        bsRec->fSigma = maskBlur.fSigma;
192daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        bsRec->fOffset = fRecs->fInfo.fOffset;
193daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        bsRec->fColor = fRecs->fPaint.getColor();
194daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        bsRec->fStyle = maskBlur.fStyle;
195daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        bsRec->fQuality = maskBlur.fQuality;
196daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
197daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    return true;
198daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com}
199daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2028b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->INHERITED::flatten(buffer);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Rec* rec = fRecs;
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = 0;
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (rec) {
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            rec = rec->fNext;
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count += 1;
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count == fCount);
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeInt(fCount);
218fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Rec* rec = fRecs;
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = 0; i < fCount; i++) {
221842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com        // Legacy "flagsmask" field -- now ignored, remove when we bump version
222842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com        buffer.writeInt(0);
223842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com
2240716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        buffer.writeInt(rec->fInfo.fPaintBits);
2250716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        buffer.writeInt(rec->fInfo.fColorMode);
226c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writePoint(rec->fInfo.fOffset);
2270716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        buffer.writeBool(rec->fInfo.fPostTranslate);
228c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writePaint(rec->fPaint);
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec = rec->fNext;
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = buffer.readInt();
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    Builder builder;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = 0; i < count; i++) {
2380716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        LayerInfo info;
239842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com        // Legacy "flagsmask" field -- now ignored, remove when we bump version
24048f31bdbb3346e3003581229395022bf44828b13reed@google.com        (void)buffer.readInt();
241842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com
2420716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        info.fPaintBits = buffer.readInt();
2430716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        info.fColorMode = (SkXfermode::Mode)buffer.readInt();
244c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.readPoint(&info.fOffset);
2450716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com        info.fPostTranslate = buffer.readBool();
24674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        buffer.readPaint(builder.addLayerOnTop(info));
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    SkLayerDrawLooper* looper = builder.detachLooper();
24974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    SkASSERT(count == looper->fCount);
250fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
25374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        Rec* rec = looper->fRecs;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int n = 0;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (rec) {
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            rec = rec->fNext;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            n += 1;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count == n);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
26274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
26374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    return looper;
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2654991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
2660f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
2674991b8f23482afc1494fd17647421ce68de53331robertphillips@google.comvoid SkLayerDrawLooper::toString(SkString* str) const {
2684991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com    str->appendf("SkLayerDrawLooper (%d): ", fCount);
2694991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
2704991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com    Rec* rec = fRecs;
2714991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com    for (int i = 0; i < fCount; i++) {
272842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com        str->appendf("%d: paintBits: (", i);
2734991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        if (0 == rec->fInfo.fPaintBits) {
2744991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            str->append("None");
2754991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
2764991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            str->append("EntirePaint");
2774991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        } else {
2784991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            bool needSeparator = false;
2794991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style",
2804991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
281cdcb2ce2744c7e5c47453328dbf292edee79ab37skia.committer@gmail.com            SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX",
2824991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
2834991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect",
2844991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
2854991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter",
2864991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
287cdcb2ce2744c7e5c47453328dbf292edee79ab37skia.committer@gmail.com            SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader",
2884991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
289cdcb2ce2744c7e5c47453328dbf292edee79ab37skia.committer@gmail.com            SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter",
2904991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
291cdcb2ce2744c7e5c47453328dbf292edee79ab37skia.committer@gmail.com            SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode",
2924991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com                              &needSeparator);
2934991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        }
2944991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->append(") ");
2954991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
2964991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        static const char* gModeStrings[SkXfermode::kLastMode+1] = {
2974991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
2984991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
2994991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
3004991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
3014991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        };
3024991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
3034991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]);
3044991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
3054991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->append("offset: (");
3064991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->appendScalar(rec->fInfo.fOffset.fX);
3074991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->append(", ");
3084991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->appendScalar(rec->fInfo.fOffset.fY);
3094991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->append(") ");
3104991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
3114991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->append("postTranslate: ");
3124991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        if (rec->fInfo.fPostTranslate) {
3134991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            str->append("true ");
3144991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        } else {
3154991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com            str->append("false ");
3164991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        }
3174991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
318791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        rec->fPaint.toString(str);
3194991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        rec = rec->fNext;
3204991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com    }
3214991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com}
3224991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com#endif
32374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
32474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSkLayerDrawLooper::Builder::Builder()
32574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        : fRecs(NULL),
32674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org          fTopRec(NULL),
32774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org          fCount(0) {
32874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org}
32974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
33074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSkLayerDrawLooper::Builder::~Builder() {
33174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    Rec* rec = fRecs;
33274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    while (rec) {
33374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        Rec* next = rec->fNext;
33474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        SkDELETE(rec);
33574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        rec = next;
33674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    }
33774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org}
33874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
33974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
34074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fCount += 1;
34174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
34274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    Rec* rec = SkNEW(Rec);
34374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    rec->fNext = fRecs;
34474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    rec->fInfo = info;
34574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fRecs = rec;
34674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    if (NULL == fTopRec) {
34774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        fTopRec = rec;
34874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    }
34974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
35074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    return &rec->fPaint;
35174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org}
35274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
35374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgvoid SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
35474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    LayerInfo info;
35574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
35674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    info.fOffset.set(dx, dy);
35774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    (void)this->addLayer(info);
35874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org}
35974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
36074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
36174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fCount += 1;
36274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
36374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    Rec* rec = SkNEW(Rec);
36474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    rec->fNext = NULL;
36574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    rec->fInfo = info;
36674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    if (NULL == fRecs) {
36774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        fRecs = rec;
36874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    } else {
36974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        SkASSERT(NULL != fTopRec);
37074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org        fTopRec->fNext = rec;
37174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    }
37274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fTopRec = rec;
37374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
37474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    return &rec->fPaint;
37574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org}
37674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
37774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() {
37874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    SkLayerDrawLooper* looper = SkNEW(SkLayerDrawLooper);
37974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    looper->fCount = fCount;
38074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    looper->fRecs = fRecs;
38174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
38274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fCount = 0;
38374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fRecs = NULL;
38474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    fTopRec = NULL;
38574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org
38674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org    return looper;
38774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org}
388