• 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 "SkFlattenableBuffers.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 
22 struct SkLayerRasterizer_Rec {
23     SkPaint     fPaint;
24     SkVector    fOffset;
25 };
26 
SkLayerRasterizer()27 SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
28 {
29 }
30 
~SkLayerRasterizer()31 SkLayerRasterizer::~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 
addLayer(const SkPaint & paint,SkScalar dx,SkScalar dy)39 void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx,
40                                  SkScalar dy) {
41     SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
42 
43     SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
44     rec->fOffset.set(dx, dy);
45 }
46 
compute_bounds(const SkDeque & layers,const SkPath & path,const SkMatrix & matrix,const SkIRect * clipBounds,SkIRect * bounds)47 static 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 
onRasterize(const SkPath & path,const SkMatrix & matrix,const SkIRect * clipBounds,SkMask * mask,SkMask::CreateMode mode) const88 bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
89                                     const SkIRect* clipBounds,
90                                     SkMask* mask, SkMask::CreateMode mode) const {
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 
SkLayerRasterizer(SkFlattenableReadBuffer & buffer)146 SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer)
147     : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) {
148     int count = buffer.readInt();
149 
150     for (int i = 0; i < count; i++) {
151         SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
152 
153         SkNEW_PLACEMENT(&rec->fPaint, SkPaint);
154         buffer.readPaint(&rec->fPaint);
155         buffer.readPoint(&rec->fOffset);
156     }
157 }
158 
flatten(SkFlattenableWriteBuffer & buffer) const159 void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const {
160     this->INHERITED::flatten(buffer);
161 
162     buffer.writeInt(fLayers.count());
163 
164     SkDeque::F2BIter                iter(fLayers);
165     const SkLayerRasterizer_Rec*    rec;
166 
167     while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
168         buffer.writePaint(rec->fPaint);
169         buffer.writePoint(rec->fOffset);
170     }
171 }
172