19f0147143fbedba10bdae496d812a14995304924reed
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
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 */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
99f0147143fbedba10bdae496d812a14995304924reed
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkLayerRasterizer.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h"
1875a0972dd7d0dbc614b9fb81b4450a349c005325reed@google.com#include "SkPathEffect.h"
19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "../core/SkRasterClip.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <new>
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkLayerRasterizer_Rec {
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint     fPaint;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkVector    fOffset;
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgSkLayerRasterizer::SkLayerRasterizer()
29f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))))
30f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org{
31f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org}
32f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
33f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgSkLayerRasterizer::SkLayerRasterizer(SkDeque* layers) : fLayers(layers)
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
376573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org// Helper function to call destructors on SkPaints held by layers and delete layers.
386573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.orgstatic void clean_up_layers(SkDeque* layers) {
396573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkDeque::F2BIter        iter(*layers);
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLayerRasterizer_Rec*  rec;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPaint.~SkPaint();
44f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
456573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkDELETE(layers);
466573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org}
476573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org
486573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.orgSkLayerRasterizer::~SkLayerRasterizer() {
496573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkASSERT(fLayers);
506573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    clean_up_layers(const_cast<SkDeque*>(fLayers));
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
533334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgstatic bool compute_bounds(const SkDeque& layers, const SkPath& path,
543334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                           const SkMatrix& matrix,
553334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                           const SkIRect* clipBounds, SkIRect* bounds) {
564c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter        iter(layers);
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLayerRasterizer_Rec*  rec;
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32);
6082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
613334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPaint&  paint = rec->fPaint;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath          fillPath, devPath;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPath*   p = &path;
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
663334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            paint.getFillPath(path, &fillPath);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            p = &fillPath;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
703334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        if (p->isEmpty()) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
723334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        }
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // apply the matrix and offset
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkMatrix m = matrix;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            m.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            p->transform(m, &devPath);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkMask  mask;
823334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(),
833334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                                &matrix, &mask,
842ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org                                SkMask::kJustComputeBounds_CreateMode,
852ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org                                SkPaint::kFill_Style)) {
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
873334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        }
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds->join(mask.fBounds);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    const SkIRect* clipBounds,
96fdba4041c350b72791a1844ff0bc0af28cbb4199reed@google.com                                    SkMask* mask, SkMask::CreateMode mode) const {
97f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkASSERT(fLayers);
98f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    if (fLayers->empty()) {
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
1003334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    }
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1023334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    if (SkMask::kJustRenderImage_CreateMode != mode) {
103f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org        if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds))
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1073334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        mask->fFormat   = SkMask::kA8_Format;
10949f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com        mask->fRowBytes = mask->fBounds.width();
110543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        size_t size = mask->computeImageSize();
111543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        if (0 == size) {
112543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com            return false;   // too big to allocate, abort
113543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        }
114543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        mask->fImage = SkMask::AllocImage(size);
115543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        memset(mask->fImage, 0, size);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1183334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    if (SkMask::kJustComputeBounds_CreateMode != mode) {
119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkBitmap        device;
120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkRasterClip    rectClip;
121045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkDraw          draw;
122045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkMatrix        translatedMatrix;  // this translates us to our local pixels
123045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkMatrix        drawMatrix;        // this translates the path by each layer's offset
12482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height()));
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        translatedMatrix = matrix;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft),
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       -SkIntToScalar(mask->fBounds.fTop));
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
131dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org        device.installMaskPixels(*mask);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        draw.fBitmap    = &device;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        draw.fMatrix    = &drawMatrix;
135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        draw.fRC        = &rectClip;
136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        draw.fClip      = &rectClip.bwRgn();
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we set the matrixproc in the loop, as the matrix changes each time (potentially)
13882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
139f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org        SkDeque::F2BIter        iter(*fLayers);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkLayerRasterizer_Rec*  rec;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            drawMatrix = translatedMatrix;
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            draw.drawPath(path, rec->fPaint);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1528b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkLayerRasterizer::SkLayerRasterizer(SkReadBuffer& buffer)
153f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    : SkRasterizer(buffer), fLayers(ReadLayers(buffer)) {}
1549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkLayerRasterizer::CreateProc(SkReadBuffer& buffer) {
1579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkNEW_ARGS(SkLayerRasterizer, (ReadLayers(buffer)));
1589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
159f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
160f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgSkDeque* SkLayerRasterizer::ReadLayers(SkReadBuffer& buffer) {
161c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    int count = buffer.readInt();
1629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
163f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec)));
1643334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    for (int i = 0; i < count; i++) {
165f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org        SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)layers->push_back();
16682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
167060ef18d5c02029eade04961f4cf62068d72a68etomhudson@google.com        SkNEW_PLACEMENT(&rec->fPaint, SkPaint);
168c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.readPaint(&rec->fPaint);
169c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.readPoint(&rec->fOffset);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
171f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    return layers;
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const {
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->INHERITED::flatten(buffer);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
177f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkASSERT(fLayers);
178f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    buffer.writeInt(fLayers->count());
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
180f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkDeque::F2BIter                iter(*fLayers);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkLayerRasterizer_Rec*    rec;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1833334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
184c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writePaint(rec->fPaint);
185c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writePoint(rec->fOffset);
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
188f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
189f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgSkLayerRasterizer::Builder::Builder()
190f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org        : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))))
191f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org{
192f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org}
193f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
194f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgSkLayerRasterizer::Builder::~Builder()
195f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org{
1966573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    if (fLayers != NULL) {
1976573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org        clean_up_layers(fLayers);
1986573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    }
199f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org}
200f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
201f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgvoid SkLayerRasterizer::Builder::addLayer(const SkPaint& paint, SkScalar dx,
202f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org                                          SkScalar dy) {
203f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkASSERT(fLayers);
204f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back();
205f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
206f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
207f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    rec->fOffset.set(dx, dy);
208f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org}
209f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org
210f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.orgSkLayerRasterizer* SkLayerRasterizer::Builder::detachRasterizer() {
21165044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo    SkLayerRasterizer* rasterizer;
21265044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo    if (0 == fLayers->count()) {
21365044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo        rasterizer = NULL;
21465044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo        SkDELETE(fLayers);
21565044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo    } else {
21665044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo        rasterizer = SkNEW_ARGS(SkLayerRasterizer, (fLayers));
21765044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo    }
218f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    fLayers = NULL;
219f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org    return rasterizer;
220f792a1b20747f769b28906a4b00fd67691ce8d0bcommit-bot@chromium.org}
2216573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org
2226573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.orgSkLayerRasterizer* SkLayerRasterizer::Builder::snapshotRasterizer() const {
22365044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo    if (0 == fLayers->count()) {
22465044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo        return NULL;
22565044bfe021e9c0023d78080583e9acb3bdb5ce7scroggo    }
2266573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec), fLayers->count()));
2276573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkDeque::F2BIter                iter(*fLayers);
2286573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    const SkLayerRasterizer_Rec*    recOrig;
2296573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkDEBUGCODE(int                 count = 0;)
2306573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    while ((recOrig = static_cast<SkLayerRasterizer_Rec*>(iter.next())) != NULL) {
2316573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org        SkDEBUGCODE(count++);
2326573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org        SkLayerRasterizer_Rec* recCopy = static_cast<SkLayerRasterizer_Rec*>(layers->push_back());
2336573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org        SkNEW_PLACEMENT_ARGS(&recCopy->fPaint, SkPaint, (recOrig->fPaint));
2346573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org        recCopy->fOffset = recOrig->fOffset;
2356573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    }
2366573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkASSERT(fLayers->count() == count);
2376573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkASSERT(layers->count() == count);
2386573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    SkLayerRasterizer* rasterizer = SkNEW_ARGS(SkLayerRasterizer, (layers));
2396573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org    return rasterizer;
2406573ce70e609f19923cea401d4ca3ea1528a78f1commit-bot@chromium.org}
241