Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: src/core/SkPicture.cpp

Issue 1130283004: Revert of Sketch splitting SkPicture into an interface and SkBigPicture. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkMiniRecorder.cpp ('k') | src/core/SkPictureCommon.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2007 The Android Open Source Project 2 * Copyright 2007 The Android Open Source Project
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 "SkAtomics.h" 8
9 #include "SkMessageBus.h" 9 #include "SkPictureFlat.h"
10 #include "SkPicture.h"
11 #include "SkPictureData.h" 10 #include "SkPictureData.h"
12 #include "SkPicturePlayback.h" 11 #include "SkPicturePlayback.h"
13 #include "SkPictureRecord.h" 12 #include "SkPictureRecord.h"
14 #include "SkPictureRecorder.h" 13 #include "SkPictureRecorder.h"
15 14
15 #include "SkAtomics.h"
16 #include "SkBitmapDevice.h"
17 #include "SkCanvas.h"
18 #include "SkChunkAlloc.h"
19 #include "SkMessageBus.h"
20 #include "SkPaintPriv.h"
21 #include "SkPathEffect.h"
22 #include "SkPicture.h"
23 #include "SkRegion.h"
24 #include "SkShader.h"
25 #include "SkStream.h"
26 #include "SkTDArray.h"
27 #include "SkTLogic.h"
28 #include "SkTSearch.h"
29 #include "SkTime.h"
30
31 #include "SkReader32.h"
32 #include "SkWriter32.h"
33 #include "SkRTree.h"
34
35 #if SK_SUPPORT_GPU
36 #include "GrContext.h"
37 #endif
38
39 #include "SkRecord.h"
40 #include "SkRecordDraw.h"
41 #include "SkRecordOpts.h"
42 #include "SkRecorder.h"
43
16 DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage); 44 DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage);
17 45
18 /* SkPicture impl. This handles generic responsibilities like unique IDs and se rialization. */ 46 template <typename T> int SafeCount(const T* obj) {
19 47 return obj ? obj->count() : 0;
20 SkPicture::SkPicture() : fUniqueID(0) {} 48 }
49
50 ///////////////////////////////////////////////////////////////////////////////
51
52 namespace {
53
54 // Some commands have a paint, some have an optional paint. Either way, get bac k a pointer.
55 static const SkPaint* AsPtr(const SkPaint& p) { return &p; }
56 static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; }
57
58 /** SkRecords visitor to determine whether an instance may require an
59 "external" bitmap to rasterize. May return false positives.
60 Does not return true for bitmap text.
61
62 Expected use is to determine whether images need to be decoded before
63 rasterizing a particular SkRecord.
64 */
65 struct BitmapTester {
66 // Helpers. These create HasMember_bitmap and HasMember_paint.
67 SK_CREATE_MEMBER_DETECTOR(bitmap);
68 SK_CREATE_MEMBER_DETECTOR(paint);
69
70
71 // Main entry for visitor:
72 // If the command is a DrawPicture, recurse.
73 // If the command has a bitmap directly, return true.
74 // If the command has a paint and the paint has a bitmap, return true.
75 // Otherwise, return false.
76 bool operator()(const SkRecords::DrawPicture& op) { return op.picture->willP layBackBitmaps(); }
77
78 template <typename T>
79 bool operator()(const T& r) { return CheckBitmap(r); }
80
81
82 // If the command has a bitmap, of course we're going to play back bitmaps.
83 template <typename T>
84 static SK_WHEN(HasMember_bitmap<T>, bool) CheckBitmap(const T&) { return tru e; }
85
86 // If not, look for one in its paint (if it has a paint).
87 template <typename T>
88 static SK_WHEN(!HasMember_bitmap<T>, bool) CheckBitmap(const T& r) { return CheckPaint(r); }
89
90 // If we have a paint, dig down into the effects looking for a bitmap.
91 template <typename T>
92 static SK_WHEN(HasMember_paint<T>, bool) CheckPaint(const T& r) {
93 const SkPaint* paint = AsPtr(r.paint);
94 if (paint) {
95 const SkShader* shader = paint->getShader();
96 if (shader &&
97 shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_Bitmap Type) {
98 return true;
99 }
100 }
101 return false;
102 }
103
104 // If we don't have a paint, that non-paint has no bitmap.
105 template <typename T>
106 static SK_WHEN(!HasMember_paint<T>, bool) CheckPaint(const T&) { return fals e; }
107 };
108
109 bool WillPlaybackBitmaps(const SkRecord& record) {
110 BitmapTester tester;
111 for (unsigned i = 0; i < record.count(); i++) {
112 if (record.visit<bool>(i, tester)) {
113 return true;
114 }
115 }
116 return false;
117 }
118
119 // SkRecord visitor to find recorded text.
120 struct TextHunter {
121 // All ops with text have that text as a char array member named "text".
122 SK_CREATE_MEMBER_DETECTOR(text);
123 bool operator()(const SkRecords::DrawPicture& op) { return op.picture->hasTe xt(); }
124 template <typename T> SK_WHEN(HasMember_text<T>, bool) operator()(const T&) { return true; }
125 template <typename T> SK_WHEN(!HasMember_text<T>, bool) operator()(const T&) { return false; }
126 };
127
128 } // namespace
129
130 /** SkRecords visitor to determine heuristically whether or not a SkPicture
131 will be performant when rasterized on the GPU.
132 */
133 struct SkPicture::PathCounter {
134 SK_CREATE_MEMBER_DETECTOR(paint);
135
136 PathCounter() : fNumSlowPathsAndDashEffects(0) {}
137
138 // Recurse into nested pictures.
139 void operator()(const SkRecords::DrawPicture& op) {
140 const SkPicture::Analysis& analysis = op.picture->analysis();
141 fNumSlowPathsAndDashEffects += analysis.fNumSlowPathsAndDashEffects;
142 }
143
144 void checkPaint(const SkPaint* paint) {
145 if (paint && paint->getPathEffect()) {
146 // Initially assume it's slow.
147 fNumSlowPathsAndDashEffects++;
148 }
149 }
150
151 void operator()(const SkRecords::DrawPoints& op) {
152 this->checkPaint(&op.paint);
153 const SkPathEffect* effect = op.paint.getPathEffect();
154 if (effect) {
155 SkPathEffect::DashInfo info;
156 SkPathEffect::DashType dashType = effect->asADash(&info);
157 if (2 == op.count && SkPaint::kRound_Cap != op.paint.getStrokeCap() &&
158 SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
159 fNumSlowPathsAndDashEffects--;
160 }
161 }
162 }
163
164 void operator()(const SkRecords::DrawPath& op) {
165 this->checkPaint(&op.paint);
166 if (op.paint.isAntiAlias() && !op.path.isConvex()) {
167 SkPaint::Style paintStyle = op.paint.getStyle();
168 const SkRect& pathBounds = op.path.getBounds();
169 if (SkPaint::kStroke_Style == paintStyle &&
170 0 == op.paint.getStrokeWidth()) {
171 // AA hairline concave path is not slow.
172 } else if (SkPaint::kFill_Style == paintStyle && pathBounds.width() < 64.f &&
173 pathBounds.height() < 64.f && !op.path.isVolatile()) {
174 // AADF eligible concave path is not slow.
175 } else {
176 fNumSlowPathsAndDashEffects++;
177 }
178 }
179 }
180
181 template <typename T>
182 SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) {
183 this->checkPaint(AsPtr(op.paint));
184 }
185
186 template <typename T>
187 SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { /* do nothing * / }
188
189 int fNumSlowPathsAndDashEffects;
190 };
191
192 SkPicture::Analysis::Analysis(const SkRecord& record) {
193 fWillPlaybackBitmaps = WillPlaybackBitmaps(record);
194
195 PathCounter counter;
196 for (unsigned i = 0; i < record.count(); i++) {
197 record.visit<void>(i, counter);
198 }
199 fNumSlowPathsAndDashEffects = SkTMin<int>(counter.fNumSlowPathsAndDashEffect s, 255);
200
201 fHasText = false;
202 TextHunter text;
203 for (unsigned i = 0; i < record.count(); i++) {
204 if (record.visit<bool>(i, text)) {
205 fHasText = true;
206 break;
207 }
208 }
209 }
210
211 bool SkPicture::Analysis::suitableForGpuRasterization(const char** reason,
212 int sampleCount) const {
213 // TODO: the heuristic used here needs to be refined
214 static const int kNumSlowPathsTol = 6;
215
216 bool ret = fNumSlowPathsAndDashEffects < kNumSlowPathsTol;
217
218 if (!ret && reason) {
219 *reason = "Too many slow paths (either concave or dashed).";
220 }
221 return ret;
222 }
223
224 ///////////////////////////////////////////////////////////////////////////////
225
226 int SkPicture::drawableCount() const {
227 return fDrawablePicts.get() ? fDrawablePicts->count() : 0;
228 }
229
230 SkPicture const* const* SkPicture::drawablePicts() const {
231 return fDrawablePicts.get() ? fDrawablePicts->begin() : NULL;
232 }
21 233
22 SkPicture::~SkPicture() { 234 SkPicture::~SkPicture() {
23 // TODO: move this to ~SkBigPicture() only?
24
25 // If the ID is still zero, no one has read it, so no need to send this mess age. 235 // If the ID is still zero, no one has read it, so no need to send this mess age.
26 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed); 236 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
27 if (id != 0) { 237 if (id != 0) {
28 SkPicture::DeletionMessage msg = { (int32_t)id }; 238 SkPicture::DeletionMessage msg;
239 msg.fUniqueID = id;
29 SkMessageBus<SkPicture::DeletionMessage>::Post(msg); 240 SkMessageBus<SkPicture::DeletionMessage>::Post(msg);
30 } 241 }
31 } 242 }
32 243
244 const SkPicture::AccelData* SkPicture::EXPERIMENTAL_getAccelData(
245 SkPicture::AccelData::Key key) const {
246 if (fAccelData.get() && fAccelData->getKey() == key) {
247 return fAccelData.get();
248 }
249 return NULL;
250 }
251
252 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
253 static int32_t gNextID = 0;
254
255 int32_t id = sk_atomic_inc(&gNextID);
256 if (id >= 1 << (8 * sizeof(Domain))) {
257 SK_CRASH();
258 }
259
260 return static_cast<Domain>(id);
261 }
262
263 ///////////////////////////////////////////////////////////////////////////////
264
265 void SkPicture::playback(SkCanvas* canvas, AbortCallback* callback) const {
266 SkASSERT(canvas);
267
268 // If the query contains the whole picture, don't bother with the BBH.
269 SkRect clipBounds = { 0, 0, 0, 0 };
270 (void)canvas->getClipBounds(&clipBounds);
271 const bool useBBH = !clipBounds.contains(this->cullRect());
272
273 SkRecordDraw(*fRecord, canvas, this->drawablePicts(), NULL, this->drawableCo unt(),
274 useBBH ? fBBH.get() : NULL, callback);
275 }
276
277 ///////////////////////////////////////////////////////////////////////////////
278
279 #include "SkStream.h"
280
281 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
282
283 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
284 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
285 return false;
286 }
287
288 if (info.fVersion < MIN_PICTURE_VERSION ||
289 info.fVersion > CURRENT_PICTURE_VERSION) {
290 return false;
291 }
292
293 return true;
294 }
295
296 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
297 if (NULL == stream) {
298 return false;
299 }
300
301 // Check magic bytes.
302 SkPictInfo info;
303 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
304
305 if (!stream->read(&info.fMagic, sizeof(kMagic))) {
306 return false;
307 }
308
309 info.fVersion = stream->readU32();
310 info.fCullRect.fLeft = stream->readScalar();
311 info.fCullRect.fTop = stream->readScalar();
312 info.fCullRect.fRight = stream->readScalar();
313 info.fCullRect.fBottom = stream->readScalar();
314
315 info.fFlags = stream->readU32();
316
317 if (!IsValidPictInfo(info)) {
318 return false;
319 }
320
321 if (pInfo != NULL) {
322 *pInfo = info;
323 }
324 return true;
325 }
326
327 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo ) {
328 // Check magic bytes.
329 SkPictInfo info;
330 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
331
332 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
333 return false;
334 }
335
336 info.fVersion = buffer->readUInt();
337 buffer->readRect(&info.fCullRect);
338 info.fFlags = buffer->readUInt();
339
340 if (!IsValidPictInfo(info)) {
341 return false;
342 }
343
344 if (pInfo != NULL) {
345 *pInfo = info;
346 }
347 return true;
348 }
349
350 SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* d ata) {
351 if (!data) {
352 return NULL;
353 }
354 SkPicturePlayback playback(data);
355 SkPictureRecorder r;
356 playback.draw(r.beginRecording(SkScalarCeilToInt(info.fCullRect.width()),
357 SkScalarCeilToInt(info.fCullRect.height())),
358 NULL/*no callback*/);
359 return r.endRecording();
360 }
361
362 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
363 SkPictInfo info;
364 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
365 return NULL;
366 }
367 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, in fo, proc));
368 return Forwardport(info, data);
369 }
370
371 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
372 SkPictInfo info;
373 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
374 return NULL;
375 }
376 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, in fo));
377 return Forwardport(info, data);
378 }
379
380 void SkPicture::createHeader(SkPictInfo* info) const {
381 // Copy magic bytes at the beginning of the header
382 SkASSERT(sizeof(kMagic) == 8);
383 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
384 memcpy(info->fMagic, kMagic, sizeof(kMagic));
385
386 // Set picture info after magic bytes in the header
387 info->fVersion = CURRENT_PICTURE_VERSION;
388 info->fCullRect = this->cullRect();
389 info->fFlags = SkPictInfo::kCrossProcess_Flag;
390 // TODO: remove this flag, since we're always float (now)
391 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
392
393 if (8 == sizeof(void*)) {
394 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
395 }
396 }
397
398 // This for compatibility with serialization code only. This is not cheap.
399 SkPictureData* SkPicture::Backport(const SkRecord& src, const SkPictInfo& info,
400 SkPicture const* const drawablePicts[], int d rawableCount) {
401 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.hei ght()), 0/*flags*/);
402 rec.beginRecording();
403 SkRecordDraw(src, &rec, drawablePicts, NULL, drawableCount, NULL/*bbh*/, NULL/*callback*/);
404 rec.endRecording();
405 return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
406 }
407
408 void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
409 SkPictInfo info;
410 this->createHeader(&info);
411 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info, this->drawablePic ts(),
412 this->drawableCount()));
413
414 stream->write(&info, sizeof(info));
415 if (data) {
416 stream->writeBool(true);
417 data->serialize(stream, pixelSerializer);
418 } else {
419 stream->writeBool(false);
420 }
421 }
422
423 void SkPicture::flatten(SkWriteBuffer& buffer) const {
424 SkPictInfo info;
425 this->createHeader(&info);
426 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info, this->drawablePic ts(),
427 this->drawableCount()));
428
429 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
430 buffer.writeUInt(info.fVersion);
431 buffer.writeRect(info.fCullRect);
432 buffer.writeUInt(info.fFlags);
433 if (data) {
434 buffer.writeBool(true);
435 data->flatten(buffer);
436 } else {
437 buffer.writeBool(false);
438 }
439 }
440
441 const SkPicture::Analysis& SkPicture::analysis() const {
442 auto create = [&](){ return SkNEW_ARGS(Analysis, (*fRecord)); };
443 return *fAnalysis.get(create);
444 }
445
446 #if SK_SUPPORT_GPU
447 bool SkPicture::suitableForGpuRasterization(GrContext*, const char **reason) con st {
448 return this->analysis().suitableForGpuRasterization(reason, 0);
449 }
450 #endif
451
452 bool SkPicture::hasText() const { return this->analysis().fHasText; }
453 bool SkPicture::willPlayBackBitmaps() const { return this->analysis().fWillPlayb ackBitmaps; }
454 int SkPicture::approximateOpCount() const { return fRecord->count(); }
455
456 SkPicture::SkPicture(const SkRect& cullRect,
457 SkRecord* record,
458 SnapshotArray* drawablePicts,
459 SkBBoxHierarchy* bbh,
460 AccelData* accelData,
461 size_t approxBytesUsedBySubPictures)
462 : fUniqueID(0)
463 , fCullRect(cullRect)
464 , fRecord(record) // Take ownership of caller's ref.
465 , fDrawablePicts(drawablePicts) // Take ownership.
466 , fBBH(bbh) // Take ownership of caller's ref.
467 , fAccelData(accelData) // Take ownership of caller's ref.
468 , fApproxBytesUsedBySubPictures(approxBytesUsedBySubPictures)
469 {}
470
471
472 static uint32_t gNextID = 1;
33 uint32_t SkPicture::uniqueID() const { 473 uint32_t SkPicture::uniqueID() const {
34 static uint32_t gNextID = 1;
35 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed); 474 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
36 while (id == 0) { 475 while (id == 0) {
37 uint32_t next = sk_atomic_fetch_add(&gNextID, 1u); 476 uint32_t next = sk_atomic_fetch_add(&gNextID, 1u);
38 if (sk_atomic_compare_exchange(&fUniqueID, &id, next, 477 if (sk_atomic_compare_exchange(&fUniqueID, &id, next,
39 sk_memory_order_relaxed, 478 sk_memory_order_relaxed,
40 sk_memory_order_relaxed)) { 479 sk_memory_order_relaxed)) {
41 id = next; 480 id = next;
42 } else { 481 } else {
43 // sk_atomic_compare_exchange replaced id with the current value of fUniqueID. 482 // sk_atomic_compare_exchange replaced id with the current value of fUniqueID.
44 } 483 }
45 } 484 }
46 return id; 485 return id;
47 } 486 }
48
49 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
50
51 SkPictInfo SkPicture::createHeader() const {
52 SkPictInfo info;
53 // Copy magic bytes at the beginning of the header
54 static_assert(sizeof(kMagic) == 8, "");
55 static_assert(sizeof(kMagic) == sizeof(info.fMagic), "");
56 memcpy(info.fMagic, kMagic, sizeof(kMagic));
57
58 // Set picture info after magic bytes in the header
59 info.fVersion = CURRENT_PICTURE_VERSION;
60 info.fCullRect = this->cullRect();
61 info.fFlags = SkPictInfo::kCrossProcess_Flag;
62 // TODO: remove this flag, since we're always float (now)
63 info.fFlags |= SkPictInfo::kScalarIsFloat_Flag;
64
65 if (8 == sizeof(void*)) {
66 info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
67 }
68 return info;
69 }
70
71 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
72 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
73 return false;
74 }
75 if (info.fVersion < MIN_PICTURE_VERSION || info.fVersion > CURRENT_PICTURE_V ERSION) {
76 return false;
77 }
78 return true;
79 }
80
81 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
82 if (!stream) {
83 return false;
84 }
85
86 SkPictInfo info;
87 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
88 if (!stream->read(&info.fMagic, sizeof(kMagic))) {
89 return false;
90 }
91
92 info.fVersion = stream->readU32();
93 info.fCullRect.fLeft = stream->readScalar();
94 info.fCullRect.fTop = stream->readScalar();
95 info.fCullRect.fRight = stream->readScalar();
96 info.fCullRect.fBottom = stream->readScalar();
97 info.fFlags = stream->readU32();
98
99 if (IsValidPictInfo(info)) {
100 if (pInfo) { *pInfo = info; }
101 return true;
102 }
103 return false;
104 }
105
106 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo ) {
107 SkPictInfo info;
108 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
109 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
110 return false;
111 }
112
113 info.fVersion = buffer->readUInt();
114 buffer->readRect(&info.fCullRect);
115 info.fFlags = buffer->readUInt();
116
117 if (IsValidPictInfo(info)) {
118 if (pInfo) { *pInfo = info; }
119 return true;
120 }
121 return false;
122 }
123
124 SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* d ata) {
125 if (!data) {
126 return nullptr;
127 }
128 SkPicturePlayback playback(data);
129 SkPictureRecorder r;
130 playback.draw(r.beginRecording(SkScalarCeilToInt(info.fCullRect.width()),
131 SkScalarCeilToInt(info.fCullRect.height())),
132 nullptr/*no callback*/);
133 return r.endRecording();
134 }
135
136 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
137 SkPictInfo info;
138 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
139 return nullptr;
140 }
141 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, in fo, proc));
142 return Forwardport(info, data);
143 }
144
145 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
146 SkPictInfo info;
147 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
148 return nullptr;
149 }
150 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, in fo));
151 return Forwardport(info, data);
152 }
153
154 SkPictureData* SkPicture::backport() const {
155 SkPictInfo info = this->createHeader();
156 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.hei ght()), 0/*flags*/);
157 rec.beginRecording();
158 this->playback(&rec);
159 rec.endRecording();
160 return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
161 }
162
163 void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
164 SkPictInfo info = this->createHeader();
165 SkAutoTDelete<SkPictureData> data(this->backport());
166
167 stream->write(&info, sizeof(info));
168 if (data) {
169 stream->writeBool(true);
170 data->serialize(stream, pixelSerializer);
171 } else {
172 stream->writeBool(false);
173 }
174 }
175
176 void SkPicture::flatten(SkWriteBuffer& buffer) const {
177 SkPictInfo info = this->createHeader();
178 SkAutoTDelete<SkPictureData> data(this->backport());
179
180 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
181 buffer.writeUInt(info.fVersion);
182 buffer.writeRect(info.fCullRect);
183 buffer.writeUInt(info.fFlags);
184 if (data) {
185 buffer.writeBool(true);
186 data->flatten(buffer);
187 } else {
188 buffer.writeBool(false);
189 }
190 }
191
192 bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) con st {
193 if (this->numSlowPaths() > 5) {
194 if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed). "; }
195 return false;
196 }
197 return true;
198 }
OLDNEW
« no previous file with comments | « src/core/SkMiniRecorder.cpp ('k') | src/core/SkPictureCommon.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698