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