Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
2 /*
3 * Copyright 2007 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 */
10 #include "SkPictureFlat.h"
11 #include "SkPicturePlayback.h"
12 #include "SkPictureRecord.h"
14 #include "SkBitmapDevice.h"
15 #include "SkCanvas.h"
16 #include "SkChunkAlloc.h"
17 #include "SkPicture.h"
18 #include "SkRegion.h"
19 #include "SkStream.h"
20 #include "SkTDArray.h"
21 #include "SkTSearch.h"
22 #include "SkTime.h"
24 #include "SkReader32.h"
25 #include "SkWriter32.h"
26 #include "SkRTree.h"
27 #include "SkBBoxHierarchyRecord.h"
29 #define DUMP_BUFFER_SIZE 65536
31 //#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
34 #ifdef SK_DEBUG
35 // enable SK_DEBUG_TRACE to trace DrawType elements when
36 // recorded and played back
37 // #define SK_DEBUG_TRACE
38 // enable SK_DEBUG_SIZE to see the size of picture components
39 // #define SK_DEBUG_SIZE
40 // enable SK_DEBUG_DUMP to see the contents of recorded elements
41 // #define SK_DEBUG_DUMP
42 // enable SK_DEBUG_VALIDATE to check internal structures for consistency
43 // #define SK_DEBUG_VALIDATE
44 #endif
46 #if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
47 const char* DrawTypeToString(DrawType drawType) {
48 switch (drawType) {
49 case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
50 case CLIP_PATH: return "CLIP_PATH";
51 case CLIP_REGION: return "CLIP_REGION";
52 case CLIP_RECT: return "CLIP_RECT";
53 case CLIP_RRECT: return "CLIP_RRECT";
54 case CONCAT: return "CONCAT";
55 case DRAW_BITMAP: return "DRAW_BITMAP";
56 case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
57 case DRAW_BITMAP_NINE: return "DRAW_BITMAP_NINE";
58 case DRAW_BITMAP_RECT_TO_RECT: return "DRAW_BITMAP_RECT_TO_RECT";
59 case DRAW_CLEAR: return "DRAW_CLEAR";
60 case DRAW_DATA: return "DRAW_DATA";
61 case DRAW_OVAL: return "DRAW_OVAL";
62 case DRAW_PAINT: return "DRAW_PAINT";
63 case DRAW_PATH: return "DRAW_PATH";
64 case DRAW_PICTURE: return "DRAW_PICTURE";
65 case DRAW_POINTS: return "DRAW_POINTS";
66 case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
67 case DRAW_POS_TEXT_TOP_BOTTOM: return "DRAW_POS_TEXT_TOP_BOTTOM";
68 case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
69 case DRAW_POS_TEXT_H_TOP_BOTTOM: return "DRAW_POS_TEXT_H_TOP_BOTTOM";
70 case DRAW_RECT: return "DRAW_RECT";
71 case DRAW_RRECT: return "DRAW_RRECT";
72 case DRAW_SPRITE: return "DRAW_SPRITE";
73 case DRAW_TEXT: return "DRAW_TEXT";
74 case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
75 case DRAW_TEXT_TOP_BOTTOM: return "DRAW_TEXT_TOP_BOTTOM";
76 case DRAW_VERTICES: return "DRAW_VERTICES";
77 case RESTORE: return "RESTORE";
78 case ROTATE: return "ROTATE";
79 case SAVE: return "SAVE";
80 case SAVE_LAYER: return "SAVE_LAYER";
81 case SCALE: return "SCALE";
82 case SET_MATRIX: return "SET_MATRIX";
83 case SKEW: return "SKEW";
84 case TRANSLATE: return "TRANSLATE";
85 case NOOP: return "NOOP";
86 default:
87 SkDebugf("DrawType error 0x%08x\n", drawType);
88 SkASSERT(0);
89 break;
90 }
91 SkASSERT(0);
92 return NULL;
93 }
94 #endif
96 #ifdef SK_DEBUG_VALIDATE
97 static void validateMatrix(const SkMatrix* matrix) {
98 SkScalar scaleX = matrix->getScaleX();
99 SkScalar scaleY = matrix->getScaleY();
100 SkScalar skewX = matrix->getSkewX();
101 SkScalar skewY = matrix->getSkewY();
102 SkScalar perspX = matrix->getPerspX();
103 SkScalar perspY = matrix->getPerspY();
104 if (scaleX != 0 && skewX != 0)
105 SkDebugf("scaleX != 0 && skewX != 0\n");
106 SkASSERT(scaleX == 0 || skewX == 0);
107 SkASSERT(scaleY == 0 || skewY == 0);
108 SkASSERT(perspX == 0);
109 SkASSERT(perspY == 0);
110 }
111 #endif
114 ///////////////////////////////////////////////////////////////////////////////
116 SkPicture::SkPicture() {
117 fRecord = NULL;
118 fPlayback = NULL;
119 fWidth = fHeight = 0;
120 fAccelData = NULL;
121 }
123 SkPicture::SkPicture(const SkPicture& src)
124 : INHERITED()
125 , fAccelData(NULL) {
126 fWidth = src.fWidth;
127 fHeight = src.fHeight;
128 fRecord = NULL;
130 /* We want to copy the src's playback. However, if that hasn't been built
131 yet, we need to fake a call to endRecording() without actually calling
132 it (since it is destructive, and we don't want to change src).
133 */
134 if (src.fPlayback) {
135 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
136 } else if (src.fRecord) {
137 // here we do a fake src.endRecording()
138 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
139 } else {
140 fPlayback = NULL;
141 }
142 }
144 SkPicture::~SkPicture() {
145 SkSafeUnref(fRecord);
146 SkDELETE(fPlayback);
147 SkSafeUnref(fAccelData);
148 }
150 void SkPicture::internalOnly_EnableOpts(bool enableOpts) {
151 if (NULL != fRecord) {
152 fRecord->internalOnly_EnableOpts(enableOpts);
153 }
154 }
156 void SkPicture::swap(SkPicture& other) {
157 SkTSwap(fRecord, other.fRecord);
158 SkTSwap(fPlayback, other.fPlayback);
159 SkTSwap(fAccelData, other.fAccelData);
160 SkTSwap(fWidth, other.fWidth);
161 SkTSwap(fHeight, other.fHeight);
162 }
164 SkPicture* SkPicture::clone() const {
165 SkPicture* clonedPicture = SkNEW(SkPicture);
166 clone(clonedPicture, 1);
167 return clonedPicture;
168 }
170 void SkPicture::clone(SkPicture* pictures, int count) const {
171 SkPictCopyInfo copyInfo;
173 for (int i = 0; i < count; i++) {
174 SkPicture* clone = &pictures[i];
176 clone->fWidth = fWidth;
177 clone->fHeight = fHeight;
178 SkSafeSetNull(clone->fRecord);
179 SkDELETE(clone->fPlayback);
181 /* We want to copy the src's playback. However, if that hasn't been built
182 yet, we need to fake a call to endRecording() without actually calling
183 it (since it is destructive, and we don't want to change src).
184 */
185 if (fPlayback) {
186 clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, ©Info));
187 } else if (fRecord) {
188 // here we do a fake src.endRecording()
189 clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, true));
190 } else {
191 clone->fPlayback = NULL;
192 }
193 }
194 }
196 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
197 static int32_t gNextID = 0;
199 int32_t id = sk_atomic_inc(&gNextID);
200 if (id >= 1 << (8 * sizeof(Domain))) {
201 SK_CRASH();
202 }
204 return static_cast<Domain>(id);
205 }
207 ///////////////////////////////////////////////////////////////////////////////
209 SkCanvas* SkPicture::beginRecording(int width, int height,
210 uint32_t recordingFlags) {
211 if (fPlayback) {
212 SkDELETE(fPlayback);
213 fPlayback = NULL;
214 }
215 SkSafeUnref(fAccelData);
216 SkSafeSetNull(fRecord);
218 // Must be set before calling createBBoxHierarchy
219 fWidth = width;
220 fHeight = height;
222 const SkISize size = SkISize::Make(width, height);
224 if (recordingFlags & kOptimizeForClippedPlayback_RecordingFlag) {
225 SkBBoxHierarchy* tree = this->createBBoxHierarchy();
226 SkASSERT(NULL != tree);
227 fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size, recordingFlags, tree));
228 tree->unref();
229 } else {
230 fRecord = SkNEW_ARGS(SkPictureRecord, (size, recordingFlags));
231 }
232 fRecord->beginRecording();
234 return fRecord;
235 }
237 SkBBoxHierarchy* SkPicture::createBBoxHierarchy() const {
238 // These values were empirically determined to produce reasonable
239 // performance in most cases.
240 static const int kRTreeMinChildren = 6;
241 static const int kRTreeMaxChildren = 11;
243 SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
244 SkIntToScalar(fHeight));
245 bool sortDraws = false; // Do not sort draw calls when bulk loading.
247 return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
248 aspectRatio, sortDraws);
249 }
251 SkCanvas* SkPicture::getRecordingCanvas() const {
252 // will be null if we are not recording
253 return fRecord;
254 }
256 void SkPicture::endRecording() {
257 if (NULL == fPlayback) {
258 if (NULL != fRecord) {
259 fRecord->endRecording();
260 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
261 SkSafeSetNull(fRecord);
262 }
263 }
264 SkASSERT(NULL == fRecord);
265 }
267 void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) {
268 this->endRecording();
269 if (NULL != fPlayback) {
270 fPlayback->draw(*surface, callback);
271 }
272 }
274 ///////////////////////////////////////////////////////////////////////////////
276 #include "SkStream.h"
278 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
280 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
281 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
282 return false;
283 }
285 if (info.fVersion < MIN_PICTURE_VERSION ||
286 info.fVersion > CURRENT_PICTURE_VERSION) {
287 return false;
288 }
290 return true;
291 }
293 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
294 if (NULL == stream) {
295 return false;
296 }
298 // Check magic bytes.
299 SkPictInfo info;
300 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
301 if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
302 return false;
303 }
305 if (pInfo != NULL) {
306 *pInfo = info;
307 }
308 return true;
309 }
311 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
312 // Check magic bytes.
313 SkPictInfo info;
314 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
315 if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
316 return false;
317 }
319 if (pInfo != NULL) {
320 *pInfo = info;
321 }
322 return true;
323 }
325 SkPicture::SkPicture(SkPicturePlayback* playback, int width, int height)
326 : fPlayback(playback)
327 , fRecord(NULL)
328 , fWidth(width)
329 , fHeight(height)
330 , fAccelData(NULL) {}
332 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
333 SkPictInfo info;
335 if (!InternalOnly_StreamIsSKP(stream, &info)) {
336 return NULL;
337 }
339 SkPicturePlayback* playback;
340 // Check to see if there is a playback to recreate.
341 if (stream->readBool()) {
342 playback = SkPicturePlayback::CreateFromStream(stream, info, proc);
343 if (NULL == playback) {
344 return NULL;
345 }
346 } else {
347 playback = NULL;
348 }
350 return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
351 }
353 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
354 SkPictInfo info;
356 if (!InternalOnly_BufferIsSKP(buffer, &info)) {
357 return NULL;
358 }
360 SkPicturePlayback* playback;
361 // Check to see if there is a playback to recreate.
362 if (buffer.readBool()) {
363 playback = SkPicturePlayback::CreateFromBuffer(buffer);
364 if (NULL == playback) {
365 return NULL;
366 }
367 } else {
368 playback = NULL;
369 }
371 return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
372 }
374 void SkPicture::createHeader(SkPictInfo* info) const {
375 // Copy magic bytes at the beginning of the header
376 SkASSERT(sizeof(kMagic) == 8);
377 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
378 memcpy(info->fMagic, kMagic, sizeof(kMagic));
380 // Set picture info after magic bytes in the header
381 info->fVersion = CURRENT_PICTURE_VERSION;
382 info->fWidth = fWidth;
383 info->fHeight = fHeight;
384 info->fFlags = SkPictInfo::kCrossProcess_Flag;
385 // TODO: remove this flag, since we're always float (now)
386 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
388 if (8 == sizeof(void*)) {
389 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
390 }
391 }
393 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
394 SkPicturePlayback* playback = fPlayback;
396 if (NULL == playback && fRecord) {
397 playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
398 }
400 SkPictInfo header;
401 this->createHeader(&header);
402 stream->write(&header, sizeof(header));
403 if (playback) {
404 stream->writeBool(true);
405 playback->serialize(stream, encoder);
406 // delete playback if it is a local version (i.e. cons'd up just now)
407 if (playback != fPlayback) {
408 SkDELETE(playback);
409 }
410 } else {
411 stream->writeBool(false);
412 }
413 }
415 void SkPicture::flatten(SkWriteBuffer& buffer) const {
416 SkPicturePlayback* playback = fPlayback;
418 if (NULL == playback && fRecord) {
419 playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
420 }
422 SkPictInfo header;
423 this->createHeader(&header);
424 buffer.writeByteArray(&header, sizeof(header));
425 if (playback) {
426 buffer.writeBool(true);
427 playback->flatten(buffer);
428 // delete playback if it is a local version (i.e. cons'd up just now)
429 if (playback != fPlayback) {
430 SkDELETE(playback);
431 }
432 } else {
433 buffer.writeBool(false);
434 }
435 }
437 bool SkPicture::willPlayBackBitmaps() const {
438 if (!fPlayback) {
439 return false;
440 }
441 return fPlayback->containsBitmaps();
442 }
444 #ifdef SK_BUILD_FOR_ANDROID
445 void SkPicture::abortPlayback() {
446 if (NULL == fPlayback) {
447 return;
448 }
449 fPlayback->abort();
450 }
451 #endif