3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #include "SkLayerRasterizer.h"
12 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h"
15 #include "SkMaskFilter.h"
18 #include "SkPathEffect.h"
19 #include "../core/SkRasterClip.h"
20 #include "SkXfermode.h"
23 struct SkLayerRasterizer_Rec {
28 SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
32 SkLayerRasterizer::~SkLayerRasterizer() {
33 SkDeque::F2BIter iter(fLayers);
34 SkLayerRasterizer_Rec* rec;
36 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
37 rec->fPaint.~SkPaint();
40 void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx,
42 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
44 SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
45 rec->fOffset.set(dx, dy);
48 static bool compute_bounds(const SkDeque& layers, const SkPath& path,
49 const SkMatrix& matrix,
50 const SkIRect* clipBounds, SkIRect* bounds) {
51 SkDeque::F2BIter iter(layers);
52 SkLayerRasterizer_Rec* rec;
54 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32);
56 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
57 const SkPaint& paint = rec->fPaint;
58 SkPath fillPath, devPath;
59 const SkPath* p = &path;
61 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
62 paint.getFillPath(path, &fillPath);
69 // apply the matrix and offset
72 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
73 p->transform(m, &devPath);
77 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(),
79 SkMask::kJustComputeBounds_CreateMode,
80 SkPaint::kFill_Style)) {
84 bounds->join(mask.fBounds);
89 bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
90 const SkIRect* clipBounds,
91 SkMask* mask, SkMask::CreateMode mode) const {
92 if (fLayers.empty()) {
96 if (SkMask::kJustRenderImage_CreateMode != mode) {
97 if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds))
101 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
102 mask->fFormat = SkMask::kA8_Format;
103 mask->fRowBytes = mask->fBounds.width();
104 size_t size = mask->computeImageSize();
106 return false; // too big to allocate, abort
108 mask->fImage = SkMask::AllocImage(size);
109 memset(mask->fImage, 0, size);
112 if (SkMask::kJustComputeBounds_CreateMode != mode) {
114 SkRasterClip rectClip;
116 SkMatrix translatedMatrix; // this translates us to our local pixels
117 SkMatrix drawMatrix; // this translates the path by each layer's offset
119 rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height()));
121 translatedMatrix = matrix;
122 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft),
123 -SkIntToScalar(mask->fBounds.fTop));
125 device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes);
126 device.setPixels(mask->fImage);
128 draw.fBitmap = &device;
129 draw.fMatrix = &drawMatrix;
130 draw.fRC = &rectClip;
131 draw.fClip = &rectClip.bwRgn();
132 // we set the matrixproc in the loop, as the matrix changes each time (potentially)
133 draw.fBounder = NULL;
135 SkDeque::F2BIter iter(fLayers);
136 SkLayerRasterizer_Rec* rec;
138 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
139 drawMatrix = translatedMatrix;
140 drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY);
141 draw.drawPath(path, rec->fPaint);
147 SkLayerRasterizer::SkLayerRasterizer(SkReadBuffer& buffer)
148 : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) {
149 int count = buffer.readInt();
151 for (int i = 0; i < count; i++) {
152 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
154 SkNEW_PLACEMENT(&rec->fPaint, SkPaint);
155 buffer.readPaint(&rec->fPaint);
156 buffer.readPoint(&rec->fOffset);
160 void SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const {
161 this->INHERITED::flatten(buffer);
163 buffer.writeInt(fLayers.count());
165 SkDeque::F2BIter iter(fLayers);
166 const SkLayerRasterizer_Rec* rec;
168 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
169 buffer.writePaint(rec->fPaint);
170 buffer.writePoint(rec->fOffset);