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