1
2/*
3 * Copyright 2006 The Android Open Source Project
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
9
10#include "SkLayerRasterizer.h"
11#include "SkBuffer.h"
12#include "SkDraw.h"
13#include "SkMask.h"
14#include "SkMaskFilter.h"
15#include "SkPaint.h"
16#include "SkPath.h"
17#include "../core/SkRasterClip.h"
18#include "SkXfermode.h"
19#include <new>
20
21struct SkLayerRasterizer_Rec {
22    SkPaint     fPaint;
23    SkVector    fOffset;
24};
25
26SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
27{
28}
29
30SkLayerRasterizer::~SkLayerRasterizer() {
31    SkDeque::F2BIter        iter(fLayers);
32    SkLayerRasterizer_Rec*  rec;
33
34    while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
35        rec->fPaint.~SkPaint();
36}
37
38void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx,
39                                 SkScalar dy) {
40    SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
41
42    new (&rec->fPaint) SkPaint(paint);
43    rec->fOffset.set(dx, dy);
44}
45
46static bool compute_bounds(const SkDeque& layers, const SkPath& path,
47                           const SkMatrix& matrix,
48                           const SkIRect* clipBounds, SkIRect* bounds) {
49    SkDeque::F2BIter        iter(layers);
50    SkLayerRasterizer_Rec*  rec;
51
52    bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32);
53
54    while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
55        const SkPaint&  paint = rec->fPaint;
56        SkPath          fillPath, devPath;
57        const SkPath*   p = &path;
58
59        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
60            paint.getFillPath(path, &fillPath);
61            p = &fillPath;
62        }
63        if (p->isEmpty()) {
64            continue;
65        }
66
67        // apply the matrix and offset
68        {
69            SkMatrix m = matrix;
70            m.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
71            p->transform(m, &devPath);
72        }
73
74        SkMask  mask;
75        if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(),
76                                &matrix, &mask,
77                                SkMask::kJustComputeBounds_CreateMode)) {
78            return false;
79        }
80
81        bounds->join(mask.fBounds);
82    }
83    return true;
84}
85
86bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
87                                    const SkIRect* clipBounds,
88                                    SkMask* mask, SkMask::CreateMode mode) {
89    if (fLayers.empty()) {
90        return false;
91    }
92
93    if (SkMask::kJustRenderImage_CreateMode != mode) {
94        if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds))
95            return false;
96    }
97
98    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
99        mask->fFormat   = SkMask::kA8_Format;
100        mask->fRowBytes = mask->fBounds.width();
101        size_t size = mask->computeImageSize();
102        if (0 == size) {
103            return false;   // too big to allocate, abort
104        }
105        mask->fImage = SkMask::AllocImage(size);
106        memset(mask->fImage, 0, size);
107    }
108
109    if (SkMask::kJustComputeBounds_CreateMode != mode) {
110        SkBitmap        device;
111        SkRasterClip    rectClip;
112        SkDraw          draw;
113        SkMatrix        translatedMatrix;  // this translates us to our local pixels
114        SkMatrix        drawMatrix;        // this translates the path by each layer's offset
115
116        rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height()));
117
118        translatedMatrix = matrix;
119        translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft),
120                                       -SkIntToScalar(mask->fBounds.fTop));
121
122        device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes);
123        device.setPixels(mask->fImage);
124
125        draw.fBitmap    = &device;
126        draw.fMatrix    = &drawMatrix;
127        draw.fRC        = &rectClip;
128        draw.fClip      = &rectClip.bwRgn();
129        // we set the matrixproc in the loop, as the matrix changes each time (potentially)
130        draw.fBounder   = NULL;
131
132        SkDeque::F2BIter        iter(fLayers);
133        SkLayerRasterizer_Rec*  rec;
134
135        while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
136            drawMatrix = translatedMatrix;
137            drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
138            draw.drawPath(path, rec->fPaint);
139        }
140    }
141    return true;
142}
143
144/////////// Routines for flattening /////////////////
145
146static void paint_read(SkPaint* paint, SkFlattenableReadBuffer& buffer) {
147    paint->setAntiAlias(buffer.readBool());
148    paint->setStyle((SkPaint::Style)buffer.readU8());
149    paint->setAlpha(buffer.readU8());
150
151    if (paint->getStyle() != SkPaint::kFill_Style) {
152        paint->setStrokeWidth(buffer.readScalar());
153        paint->setStrokeMiter(buffer.readScalar());
154        paint->setStrokeCap((SkPaint::Cap)buffer.readU8());
155        paint->setStrokeJoin((SkPaint::Join)buffer.readU8());
156    }
157
158    SkSafeUnref(paint->setMaskFilter((SkMaskFilter*)buffer.readFlattenable()));
159    SkSafeUnref(paint->setPathEffect((SkPathEffect*)buffer.readFlattenable()));
160    SkSafeUnref(paint->setRasterizer((SkRasterizer*)buffer.readFlattenable()));
161    SkSafeUnref(paint->setXfermode((SkXfermode*)buffer.readFlattenable()));
162}
163
164static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer) {
165    buffer.writeBool(paint.isAntiAlias());
166    buffer.write8(paint.getStyle());
167    buffer.write8(paint.getAlpha());
168
169    if (paint.getStyle() != SkPaint::kFill_Style) {
170        buffer.writeScalar(paint.getStrokeWidth());
171        buffer.writeScalar(paint.getStrokeMiter());
172        buffer.write8(paint.getStrokeCap());
173        buffer.write8(paint.getStrokeJoin());
174    }
175
176    buffer.writeFlattenable(paint.getMaskFilter());
177    buffer.writeFlattenable(paint.getPathEffect());
178    buffer.writeFlattenable(paint.getRasterizer());
179    buffer.writeFlattenable(paint.getXfermode());
180}
181
182SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer)
183    : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) {
184    int count = buffer.readS32();
185
186    for (int i = 0; i < count; i++) {
187        SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
188
189#if 0
190        new (&rec->fPaint) SkPaint(buffer);
191#else
192        new (&rec->fPaint) SkPaint;
193        paint_read(&rec->fPaint, buffer);
194#endif
195        rec->fOffset.fX = buffer.readScalar();
196        rec->fOffset.fY = buffer.readScalar();
197    }
198}
199
200void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) {
201    this->INHERITED::flatten(buffer);
202
203    buffer.write32(fLayers.count());
204
205    SkDeque::F2BIter                iter(fLayers);
206    const SkLayerRasterizer_Rec*    rec;
207
208    while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
209#if 0
210        rec->fPaint.flatten(buffer);
211#else
212        paint_write(rec->fPaint, buffer);
213#endif
214        buffer.writeScalar(rec->fOffset.fX);
215        buffer.writeScalar(rec->fOffset.fY);
216    }
217}
218
219SkFlattenable* SkLayerRasterizer::CreateProc(SkFlattenableReadBuffer& buffer) {
220    return SkNEW_ARGS(SkLayerRasterizer, (buffer));
221}
222
223SkFlattenable::Factory SkLayerRasterizer::getFactory() {
224    return CreateProc;
225}
226
227SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerRasterizer)
228
229