• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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