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