OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBBoxHierarchy.h" | 8 #include "SkBBoxHierarchy.h" |
9 #include "SkBitmapDevice.h" | |
10 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
11 #include "SkData.h" | 10 #include "SkData.h" |
12 #include "SkNoSaveLayerCanvas.h" | |
13 #include "SkPictureUtils.h" | 11 #include "SkPictureUtils.h" |
14 #include "SkPixelRef.h" | |
15 #include "SkRRect.h" | |
16 #include "SkRecord.h" | 12 #include "SkRecord.h" |
17 #include "SkShader.h" | 13 #include "SkShader.h" |
18 | 14 |
19 class PixelRefSet { | |
20 public: | |
21 PixelRefSet(SkTDArray<SkPixelRef*>* array) : fArray(array) {} | |
22 | |
23 // This does a linear search on existing pixelrefs, so if this list gets big | |
24 // we should use a more complex sorted/hashy thing. | |
25 // | |
26 void add(SkPixelRef* pr) { | |
27 uint32_t genID = pr->getGenerationID(); | |
28 if (fGenID.find(genID) < 0) { | |
29 *fArray->append() = pr; | |
30 *fGenID.append() = genID; | |
31 // SkDebugf("--- adding [%d] %x %d\n", fArray->count() - 1, pr, genID
); | |
32 } else { | |
33 // SkDebugf("--- already have %x %d\n", pr, genID); | |
34 } | |
35 } | |
36 | |
37 private: | |
38 SkTDArray<SkPixelRef*>* fArray; | |
39 SkTDArray<uint32_t> fGenID; | |
40 }; | |
41 | |
42 static void not_supported() { | |
43 SkDEBUGFAIL("this method should never be called"); | |
44 } | |
45 | |
46 static void nothing_to_do() {} | |
47 | |
48 /** | |
49 * This device will route all bitmaps (primitives and in shaders) to its PRSet. | |
50 * It should never actually draw anything, so there need not be any pixels | |
51 * behind its device. | |
52 */ | |
53 class GatherPixelRefDevice : public SkBaseDevice { | |
54 public: | |
55 SK_DECLARE_INST_COUNT(GatherPixelRefDevice) | |
56 | |
57 GatherPixelRefDevice(int width, int height, PixelRefSet* prset) { | |
58 fSize.set(width, height); | |
59 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); | |
60 fPRSet = prset; | |
61 } | |
62 | |
63 SkImageInfo imageInfo() const SK_OVERRIDE { | |
64 return SkImageInfo::MakeUnknown(fSize.width(), fSize.height()); | |
65 } | |
66 GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; } | |
67 // TODO: allow this call to return failure, or move to SkBitmapDevice only. | |
68 const SkBitmap& onAccessBitmap() SK_OVERRIDE { | |
69 return fEmptyBitmap; | |
70 } | |
71 void lockPixels() SK_OVERRIDE { nothing_to_do(); } | |
72 void unlockPixels() SK_OVERRIDE { nothing_to_do(); } | |
73 bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } | |
74 bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false;
} | |
75 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImag
eFilter::Context&, | |
76 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { | |
77 return false; | |
78 } | |
79 | |
80 void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE { | |
81 this->addBitmapFromPaint(paint); | |
82 } | |
83 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t coun
t, | |
84 const SkPoint[], const SkPaint& paint) SK_OVERRIDE { | |
85 this->addBitmapFromPaint(paint); | |
86 } | |
87 virtual void drawRect(const SkDraw&, const SkRect&, | |
88 const SkPaint& paint) SK_OVERRIDE { | |
89 this->addBitmapFromPaint(paint); | |
90 } | |
91 virtual void drawRRect(const SkDraw&, const SkRRect&, | |
92 const SkPaint& paint) SK_OVERRIDE { | |
93 this->addBitmapFromPaint(paint); | |
94 } | |
95 virtual void drawOval(const SkDraw&, const SkRect&, | |
96 const SkPaint& paint) SK_OVERRIDE { | |
97 this->addBitmapFromPaint(paint); | |
98 } | |
99 virtual void drawPath(const SkDraw&, const SkPath& path, | |
100 const SkPaint& paint, const SkMatrix* prePathMatrix, | |
101 bool pathIsMutable) SK_OVERRIDE { | |
102 this->addBitmapFromPaint(paint); | |
103 } | |
104 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, | |
105 const SkMatrix&, const SkPaint& paint) SK_OVERRIDE { | |
106 this->addBitmap(bitmap); | |
107 if (kAlpha_8_SkColorType == bitmap.colorType()) { | |
108 this->addBitmapFromPaint(paint); | |
109 } | |
110 } | |
111 virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap, | |
112 const SkRect* srcOrNull, const SkRect& dst, | |
113 const SkPaint& paint, | |
114 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE
{ | |
115 this->addBitmap(bitmap); | |
116 if (kAlpha_8_SkColorType == bitmap.colorType()) { | |
117 this->addBitmapFromPaint(paint); | |
118 } | |
119 } | |
120 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, | |
121 int x, int y, const SkPaint& paint) SK_OVERRIDE { | |
122 this->addBitmap(bitmap); | |
123 } | |
124 virtual void drawText(const SkDraw&, const void* text, size_t len, | |
125 SkScalar x, SkScalar y, | |
126 const SkPaint& paint) SK_OVERRIDE { | |
127 this->addBitmapFromPaint(paint); | |
128 } | |
129 virtual void drawPosText(const SkDraw&, const void* text, size_t len, | |
130 const SkScalar pos[], int, | |
131 const SkPoint&, const SkPaint& paint) SK_OVERRIDE { | |
132 this->addBitmapFromPaint(paint); | |
133 } | |
134 virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, | |
135 const SkPath& path, const SkMatrix* matrix, | |
136 const SkPaint& paint) SK_OVERRIDE { | |
137 this->addBitmapFromPaint(paint); | |
138 } | |
139 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCou
nt, | |
140 const SkPoint verts[], const SkPoint texs[], | |
141 const SkColor colors[], SkXfermode* xmode, | |
142 const uint16_t indices[], int indexCount, | |
143 const SkPaint& paint) SK_OVERRIDE { | |
144 this->addBitmapFromPaint(paint); | |
145 } | |
146 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, | |
147 const SkPaint&) SK_OVERRIDE { | |
148 nothing_to_do(); | |
149 } | |
150 | |
151 protected: | |
152 void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE { | |
153 not_supported(); | |
154 } | |
155 SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& cinfo) SK_OVERRIDE
{ | |
156 // we expect to only get called via savelayer, in which case it is fine. | |
157 SkASSERT(kSaveLayer_Usage == cinfo.fUsage); | |
158 return SkNEW_ARGS(GatherPixelRefDevice, (cinfo.fInfo.width(), cinfo.fInf
o.height(), fPRSet)); | |
159 } | |
160 void flush() SK_OVERRIDE {} | |
161 | |
162 private: | |
163 PixelRefSet* fPRSet; | |
164 SkBitmap fEmptyBitmap; // legacy -- need to remove the need for this guy | |
165 SkISize fSize; | |
166 | |
167 void addBitmap(const SkBitmap& bm) { | |
168 fPRSet->add(bm.pixelRef()); | |
169 } | |
170 | |
171 void addBitmapFromPaint(const SkPaint& paint) { | |
172 SkShader* shader = paint.getShader(); | |
173 if (shader) { | |
174 SkBitmap bm; | |
175 // Check whether the shader is a gradient in order to short-circuit | |
176 // call to asABitmap to prevent generation of bitmaps from | |
177 // gradient shaders, which implement asABitmap. | |
178 if (SkShader::kNone_GradientType == shader->asAGradient(NULL) && | |
179 shader->asABitmap(&bm, NULL, NULL)) { | |
180 fPRSet->add(bm.pixelRef()); | |
181 } | |
182 } | |
183 } | |
184 | |
185 typedef SkBaseDevice INHERITED; | |
186 }; | |
187 | |
188 SkData* SkPictureUtils::GatherPixelRefs(const SkPicture* pict, const SkRect& are
a) { | |
189 if (NULL == pict) { | |
190 return NULL; | |
191 } | |
192 | |
193 // this test also handles if either area or pict's width/height are empty | |
194 if (!SkRect::Intersects(area, pict->cullRect())) { | |
195 return NULL; | |
196 } | |
197 | |
198 SkTDArray<SkPixelRef*> array; | |
199 PixelRefSet prset(&array); | |
200 | |
201 GatherPixelRefDevice device(SkScalarCeilToInt(pict->cullRect().width()), | |
202 SkScalarCeilToInt(pict->cullRect().height()), | |
203 &prset); | |
204 SkNoSaveLayerCanvas canvas(&device); | |
205 | |
206 canvas.clipRect(area, SkRegion::kIntersect_Op, false); | |
207 canvas.drawPicture(pict); | |
208 | |
209 SkData* data = NULL; | |
210 int count = array.count(); | |
211 if (count > 0) { | |
212 data = SkData::NewFromMalloc(array.detach(), count * sizeof(SkPixelRef*)
); | |
213 } | |
214 return data; | |
215 } | |
216 | |
217 struct MeasureRecords { | 15 struct MeasureRecords { |
218 template <typename T> size_t operator()(const T& op) { return 0; } | 16 template <typename T> size_t operator()(const T& op) { return 0; } |
219 size_t operator()(const SkRecords::DrawPicture& op) { | 17 size_t operator()(const SkRecords::DrawPicture& op) { |
220 return SkPictureUtils::ApproximateBytesUsed(op.picture); | 18 return SkPictureUtils::ApproximateBytesUsed(op.picture); |
221 } | 19 } |
222 }; | 20 }; |
223 | 21 |
224 size_t SkPictureUtils::ApproximateBytesUsed(const SkPicture* pict) { | 22 size_t SkPictureUtils::ApproximateBytesUsed(const SkPicture* pict) { |
225 size_t byteCount = sizeof(*pict); | 23 size_t byteCount = sizeof(*pict); |
226 | 24 |
227 byteCount += pict->fRecord->bytesUsed(); | 25 byteCount += pict->fRecord->bytesUsed(); |
228 if (pict->fBBH.get()) { | 26 if (pict->fBBH.get()) { |
229 byteCount += pict->fBBH->bytesUsed(); | 27 byteCount += pict->fBBH->bytesUsed(); |
230 } | 28 } |
231 MeasureRecords visitor; | 29 MeasureRecords visitor; |
232 for (unsigned curOp = 0; curOp < pict->fRecord->count(); curOp++) { | 30 for (unsigned curOp = 0; curOp < pict->fRecord->count(); curOp++) { |
233 byteCount += pict->fRecord->visit<size_t>(curOp, visitor); | 31 byteCount += pict->fRecord->visit<size_t>(curOp, visitor); |
234 } | 32 } |
235 | 33 |
236 return byteCount; | 34 return byteCount; |
237 } | 35 } |
OLD | NEW |