1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9 #include "SkLayerRasterizer.h"
10 #include "SkDraw.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.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 "../core/SkStrokeRec.h"
20 #include <new>
21
22 struct SkLayerRasterizer_Rec {
23 SkPaint fPaint;
24 SkVector fOffset;
25 };
26
SkLayerRasterizer()27 SkLayerRasterizer::SkLayerRasterizer() : fLayers(new SkDeque(sizeof(SkLayerRasterizer_Rec))) {}
28
SkLayerRasterizer(SkDeque * layers)29 SkLayerRasterizer::SkLayerRasterizer(SkDeque* layers) : fLayers(layers)
30 {
31 }
32
33 // Helper function to call destructors on SkPaints held by layers and delete layers.
clean_up_layers(SkDeque * layers)34 static void clean_up_layers(SkDeque* layers) {
35 SkDeque::F2BIter iter(*layers);
36 SkLayerRasterizer_Rec* rec;
37
38 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != nullptr)
39 rec->fPaint.~SkPaint();
40
41 delete layers;
42 }
43
~SkLayerRasterizer()44 SkLayerRasterizer::~SkLayerRasterizer() {
45 SkASSERT(fLayers);
46 clean_up_layers(const_cast<SkDeque*>(fLayers));
47 }
48
compute_bounds(const SkDeque & layers,const SkPath & path,const SkMatrix & matrix,const SkIRect * clipBounds,SkIRect * bounds)49 static bool compute_bounds(const SkDeque& layers, const SkPath& path,
50 const SkMatrix& matrix,
51 const SkIRect* clipBounds, SkIRect* bounds) {
52 SkDeque::F2BIter iter(layers);
53 SkLayerRasterizer_Rec* rec;
54
55 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32);
56
57 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != nullptr) {
58 const SkPaint& paint = rec->fPaint;
59 SkPath fillPath, devPath;
60 const SkPath* p = &path;
61
62 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
63 paint.getFillPath(path, &fillPath);
64 p = &fillPath;
65 }
66 if (p->isEmpty()) {
67 continue;
68 }
69
70 // apply the matrix and offset
71 {
72 SkMatrix m = matrix;
73 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
74 p->transform(m, &devPath);
75 }
76
77 SkMask mask;
78 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(),
79 &matrix, &mask,
80 SkMask::kJustComputeBounds_CreateMode,
81 SkStrokeRec::kFill_InitStyle)) {
82 return false;
83 }
84
85 bounds->join(mask.fBounds);
86 }
87 return true;
88 }
89
onRasterize(const SkPath & path,const SkMatrix & matrix,const SkIRect * clipBounds,SkMask * mask,SkMask::CreateMode mode) const90 bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
91 const SkIRect* clipBounds,
92 SkMask* mask, SkMask::CreateMode mode) const {
93 SkASSERT(fLayers);
94 if (fLayers->empty()) {
95 return false;
96 }
97
98 if (SkMask::kJustRenderImage_CreateMode != mode) {
99 if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds))
100 return false;
101 }
102
103 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
104 mask->fFormat = SkMask::kA8_Format;
105 mask->fRowBytes = mask->fBounds.width();
106 size_t size = mask->computeImageSize();
107 if (0 == size) {
108 return false; // too big to allocate, abort
109 }
110 mask->fImage = SkMask::AllocImage(size);
111 memset(mask->fImage, 0, size);
112 }
113
114 if (SkMask::kJustComputeBounds_CreateMode != mode) {
115 SkDraw draw;
116 if (!draw.fDst.reset(*mask)) {
117 return false;
118 }
119
120 SkRasterClip rectClip;
121 SkMatrix translatedMatrix; // this translates us to our local pixels
122 SkMatrix drawMatrix; // this translates the path by each layer's offset
123
124 rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height()));
125
126 translatedMatrix = matrix;
127 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft),
128 -SkIntToScalar(mask->fBounds.fTop));
129
130 draw.fMatrix = &drawMatrix;
131 draw.fRC = &rectClip;
132 // we set the matrixproc in the loop, as the matrix changes each time (potentially)
133
134 SkDeque::F2BIter iter(*fLayers);
135 SkLayerRasterizer_Rec* rec;
136
137 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != nullptr) {
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
CreateProc(SkReadBuffer & buffer)146 sk_sp<SkFlattenable> SkLayerRasterizer::CreateProc(SkReadBuffer& buffer) {
147 return sk_sp<SkFlattenable>(new SkLayerRasterizer(ReadLayers(buffer)));
148 }
149
ReadLayers(SkReadBuffer & buffer)150 SkDeque* SkLayerRasterizer::ReadLayers(SkReadBuffer& buffer) {
151 int count = buffer.readInt();
152
153 SkDeque* layers = new SkDeque(sizeof(SkLayerRasterizer_Rec));
154 for (int i = 0; i < count; i++) {
155 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)layers->push_back();
156
157 new (&rec->fPaint) SkPaint;
158 buffer.readPaint(&rec->fPaint);
159 buffer.readPoint(&rec->fOffset);
160 }
161 return layers;
162 }
163
flatten(SkWriteBuffer & buffer) const164 void SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const {
165 this->INHERITED::flatten(buffer);
166
167 SkASSERT(fLayers);
168 buffer.writeInt(fLayers->count());
169
170 SkDeque::F2BIter iter(*fLayers);
171 const SkLayerRasterizer_Rec* rec;
172
173 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != nullptr) {
174 buffer.writePaint(rec->fPaint);
175 buffer.writePoint(rec->fOffset);
176 }
177 }
178
Builder()179 SkLayerRasterizer::Builder::Builder() : fLayers(new SkDeque(sizeof(SkLayerRasterizer_Rec))) {}
180
~Builder()181 SkLayerRasterizer::Builder::~Builder()
182 {
183 if (fLayers != nullptr) {
184 clean_up_layers(fLayers);
185 }
186 }
187
addLayer(const SkPaint & paint,SkScalar dx,SkScalar dy)188 void SkLayerRasterizer::Builder::addLayer(const SkPaint& paint, SkScalar dx,
189 SkScalar dy) {
190 SkASSERT(fLayers);
191 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back();
192
193 new (&rec->fPaint) SkPaint(paint);
194 rec->fOffset.set(dx, dy);
195 }
196
detach()197 sk_sp<SkLayerRasterizer> SkLayerRasterizer::Builder::detach() {
198 SkLayerRasterizer* rasterizer;
199 if (0 == fLayers->count()) {
200 rasterizer = nullptr;
201 delete fLayers;
202 } else {
203 rasterizer = new SkLayerRasterizer(fLayers);
204 }
205 fLayers = nullptr;
206 return sk_sp<SkLayerRasterizer>(rasterizer);
207 }
208
snapshot() const209 sk_sp<SkLayerRasterizer> SkLayerRasterizer::Builder::snapshot() const {
210 if (0 == fLayers->count()) {
211 return nullptr;
212 }
213 SkDeque* layers = new SkDeque(sizeof(SkLayerRasterizer_Rec), fLayers->count());
214 SkDeque::F2BIter iter(*fLayers);
215 const SkLayerRasterizer_Rec* recOrig;
216 SkDEBUGCODE(int count = 0;)
217 while ((recOrig = static_cast<SkLayerRasterizer_Rec*>(iter.next())) != nullptr) {
218 SkDEBUGCODE(count++);
219 SkLayerRasterizer_Rec* recCopy = static_cast<SkLayerRasterizer_Rec*>(layers->push_back());
220 new (&recCopy->fPaint) SkPaint(recOrig->fPaint);
221 recCopy->fOffset = recOrig->fOffset;
222 }
223 SkASSERT(fLayers->count() == count);
224 SkASSERT(layers->count() == count);
225 return sk_sp<SkLayerRasterizer>(new SkLayerRasterizer(layers));
226 }
227