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