gfx/skia/trunk/src/core/SkPicture.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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.

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

mercurial