blob: 390e3a32ff91558fece4c931058a4de67a971134 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/effects/SkLayerRasterizer.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkLayerRasterizer.h"
19#include "SkBuffer.h"
20#include "SkDraw.h"
21#include "SkMask.h"
22#include "SkMaskFilter.h"
23#include "SkPaint.h"
24#include "SkPath.h"
25#include "SkRegion.h"
26#include "SkXfermode.h"
27#include <new>
28
29struct SkLayerRasterizer_Rec {
30 SkPaint fPaint;
31 SkVector fOffset;
32};
33
34SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
35{
36}
37
38SkLayerRasterizer::~SkLayerRasterizer()
39{
40 SkDeque::Iter iter(fLayers);
41 SkLayerRasterizer_Rec* rec;
42
43 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
44 rec->fPaint.~SkPaint();
45}
46
47void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx, SkScalar dy)
48{
49 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
50
51 new (&rec->fPaint) SkPaint(paint);
52 rec->fOffset.set(dx, dy);
53}
54
55static bool compute_bounds(const SkDeque& layers, const SkPath& path, const SkMatrix& matrix,
56 const SkIRect* clipBounds, SkIRect* bounds)
57{
58 SkDeque::Iter iter(layers);
59 SkLayerRasterizer_Rec* rec;
60
61 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32);
62
63 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
64 {
65 const SkPaint& paint = rec->fPaint;
66 SkPath fillPath, devPath;
67 const SkPath* p = &path;
68
69 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style)
70 {
71 paint.getFillPath(path, &fillPath);
72 p = &fillPath;
73 }
74 if (p->isEmpty())
75 continue;
76
77 // apply the matrix and offset
78 {
79 SkMatrix m = matrix;
80 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
81 p->transform(m, &devPath);
82 }
83
84 SkMask mask;
85 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(), &matrix,
86 &mask, SkMask::kJustComputeBounds_CreateMode))
87 return false;
88
89 bounds->join(mask.fBounds);
90 }
91 return true;
92}
93
94bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
95 const SkIRect* clipBounds,
96 SkMask* mask, SkMask::CreateMode mode)
97{
98 if (fLayers.empty())
99 return false;
100
101 if (SkMask::kJustRenderImage_CreateMode != mode)
102 {
103 if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds))
104 return false;
105 }
106
107 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode)
108 {
109 mask->fFormat = SkMask::kA8_Format;
110 mask->fRowBytes = SkToU16(mask->fBounds.width());
111 mask->fImage = SkMask::AllocImage(mask->computeImageSize());
112 memset(mask->fImage, 0, mask->computeImageSize());
113 }
114
115 if (SkMask::kJustComputeBounds_CreateMode != mode)
116 {
117 SkBitmap device;
118 SkDraw draw;
119 SkMatrix translatedMatrix; // this translates us to our local pixels
120 SkMatrix drawMatrix; // this translates the path by each layer's offset
121 SkRegion rectClip;
122
123 rectClip.setRect(0, 0, mask->fBounds.width(), mask->fBounds.height());
124
125 translatedMatrix = matrix;
126 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft),
127 -SkIntToScalar(mask->fBounds.fTop));
128
129 device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes);
130 device.setPixels(mask->fImage);
131
132 draw.fBitmap = &device;
133 draw.fMatrix = &drawMatrix;
134 draw.fClip = &rectClip;
135 // we set the matrixproc in the loop, as the matrix changes each time (potentially)
136 draw.fBounder = NULL;
137
138 SkDeque::Iter iter(fLayers);
139 SkLayerRasterizer_Rec* rec;
140
141 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
142 drawMatrix = translatedMatrix;
143 drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
144 draw.drawPath(path, rec->fPaint);
145 }
146 }
147 return true;
148}
149
150/////////// Routines for flattening /////////////////
151
152static void paint_read(SkPaint* paint, SkFlattenableReadBuffer& buffer)
153{
154 paint->setAntiAlias(buffer.readBool());
155 paint->setStyle((SkPaint::Style)buffer.readU8());
156 paint->setAlpha(buffer.readU8());
157
158 if (paint->getStyle() != SkPaint::kFill_Style)
159 {
160 paint->setStrokeWidth(buffer.readScalar());
161 paint->setStrokeMiter(buffer.readScalar());
162 paint->setStrokeCap((SkPaint::Cap)buffer.readU8());
163 paint->setStrokeJoin((SkPaint::Join)buffer.readU8());
164 }
165
166 paint->setMaskFilter((SkMaskFilter*)buffer.readFlattenable())->safeUnref();
167 paint->setPathEffect((SkPathEffect*)buffer.readFlattenable())->safeUnref();
168 paint->setRasterizer((SkRasterizer*)buffer.readFlattenable())->safeUnref();
169 paint->setXfermode((SkXfermode*)buffer.readFlattenable())->safeUnref();
170}
171
172static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer)
173{
174 buffer.writeBool(paint.isAntiAlias());
175 buffer.write8(paint.getStyle());
176 buffer.write8(paint.getAlpha());
177
178 if (paint.getStyle() != SkPaint::kFill_Style)
179 {
180 buffer.writeScalar(paint.getStrokeWidth());
181 buffer.writeScalar(paint.getStrokeMiter());
182 buffer.write8(paint.getStrokeCap());
183 buffer.write8(paint.getStrokeJoin());
184 }
185
186 buffer.writeFlattenable(paint.getMaskFilter());
187 buffer.writeFlattenable(paint.getPathEffect());
188 buffer.writeFlattenable(paint.getRasterizer());
189 buffer.writeFlattenable(paint.getXfermode());
190}
191
192SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer)
193 : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec))
194{
195 int count = buffer.readS32();
196
197 for (int i = 0; i < count; i++)
198 {
199 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
200
201#if 0
202 new (&rec->fPaint) SkPaint(buffer);
203#else
204 new (&rec->fPaint) SkPaint;
205 paint_read(&rec->fPaint, buffer);
206#endif
207 rec->fOffset.fX = buffer.readScalar();
208 rec->fOffset.fY = buffer.readScalar();
209 }
210}
211
212void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer)
213{
214 this->INHERITED::flatten(buffer);
215
216 buffer.write32(fLayers.count());
217
218 SkDeque::Iter iter(fLayers);
219 const SkLayerRasterizer_Rec* rec;
220
221 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL)
222 {
223#if 0
224 rec->fPaint.flatten(buffer);
225#else
226 paint_write(rec->fPaint, buffer);
227#endif
228 buffer.writeScalar(rec->fOffset.fX);
229 buffer.writeScalar(rec->fOffset.fY);
230 }
231}
232
233SkFlattenable* SkLayerRasterizer::CreateProc(SkFlattenableReadBuffer& buffer)
234{
235 return SkNEW_ARGS(SkLayerRasterizer, (buffer));
236}
237
238SkFlattenable::Factory SkLayerRasterizer::getFactory()
239{
240 return CreateProc;
241}
242