Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "SkCanvas.h" | 8 #include "SkCanvas.h" |
| 9 #include "SkPictureData.h" | 9 #include "SkPictureData.h" |
| 10 #include "SkPicturePlayback.h" | 10 #include "SkPicturePlayback.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 void get_text(SkReader32* reader, TextContainer* text) { | 99 void get_text(SkReader32* reader, TextContainer* text) { |
| 100 size_t length = text->fByteLength = reader->readInt(); | 100 size_t length = text->fByteLength = reader->readInt(); |
| 101 text->fText = (const char*)reader->skip(length); | 101 text->fText = (const char*)reader->skip(length); |
| 102 } | 102 } |
| 103 | 103 |
| 104 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multip le threads. | 104 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multip le threads. |
| 105 static SkBitmap shallow_copy(const SkBitmap& bitmap) { | 105 static SkBitmap shallow_copy(const SkBitmap& bitmap) { |
| 106 return bitmap; | 106 return bitmap; |
| 107 } | 107 } |
| 108 | 108 |
| 109 void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) { | 109 const SkPicture::OperationList* SkPicturePlayback::getActiveOps(const SkCanvas* canvas) { |
| 110 AutoResetOpID aroi(this); | |
| 111 SkASSERT(0 == fCurOffset); | |
| 112 | |
| 113 // kDrawComplete will be the signal that we have reached the end of | |
| 114 // the command stream | |
| 115 static const uint32_t kDrawComplete = SK_MaxU32; | |
| 116 | |
| 117 SkReader32 reader(fPictureData->fOpData->bytes(), fPictureData->fOpData->siz e()); | |
| 118 SkAutoTDelete<const SkPicture::OperationList> activeOpsList; | |
| 119 const SkTDArray<void*>* activeOps = NULL; | |
| 120 | 110 |
| 121 if (fUseBBH && NULL != fPictureData->fStateTree && NULL != fPictureData->fBo undingHierarchy) { | 111 if (fUseBBH && NULL != fPictureData->fStateTree && NULL != fPictureData->fBo undingHierarchy) { |
| 122 SkRect clipBounds; | 112 SkRect clipBounds; |
| 123 if (canvas->getClipBounds(&clipBounds)) { | 113 if (canvas->getClipBounds(&clipBounds)) { |
| 124 SkIRect query; | 114 SkIRect query; |
| 125 clipBounds.roundOut(&query); | 115 clipBounds.roundOut(&query); |
| 126 | 116 |
| 127 activeOpsList.reset(fPictureData->getActiveOps(query)); | 117 return fPictureData->getActiveOps(query); |
| 128 if (NULL != activeOpsList.get()) { | 118 } |
| 129 if (0 == activeOpsList->numOps()) { | 119 } |
| 130 return; // nothing to draw | 120 |
| 121 return NULL; | |
| 122 } | |
| 123 | |
| 124 // Initialize the state tree iterator. Return false if there is nothing left to draw. | |
| 125 bool SkPicturePlayback::initIterator(SkPictureStateTree::Iterator* iter, | |
| 126 SkCanvas* canvas, | |
| 127 const SkPicture::OperationList *activeOpsLi st) { | |
| 128 | |
| 129 if (NULL != activeOpsList) { | |
| 130 if (0 == activeOpsList->numOps()) { | |
| 131 return false; // nothing to draw | |
| 132 } | |
| 133 | |
| 134 fPictureData->fStateTree->initIterator(iter, activeOpsList->fOps, canvas ); | |
| 135 } | |
| 136 | |
| 137 return true; | |
| 138 } | |
| 139 | |
| 140 // If 'iter' is valid use it to skip forward through the picture. | |
| 141 void SkPicturePlayback::StepIterator(SkPictureStateTree::Iterator* iter, SkReade r32* reader) { | |
| 142 if (iter->isValid()) { | |
| 143 uint32_t skipTo = iter->nextDraw(); | |
| 144 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) { | |
| 145 reader->setOffset(reader->size()); // skip to end | |
| 146 } else { | |
| 147 reader->setOffset(skipTo); | |
| 148 } | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 bool SkPicturePlayback::replaceOps(SkPictureStateTree::Iterator* iter, | |
| 153 SkReader32* reader, | |
| 154 SkCanvas* canvas, | |
| 155 const SkMatrix& initialMatrix) { | |
| 156 if (NULL != fReplacements) { | |
| 157 // Potentially replace a block of operations with a single drawBitmap ca ll | |
| 158 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp = | |
| 159 fReplacements->lookupByStart(reader- >offset()); | |
| 160 if (NULL != temp) { | |
| 161 SkASSERT(NULL != temp->fBM); | |
| 162 SkASSERT(NULL != temp->fPaint); | |
| 163 canvas->save(); | |
| 164 canvas->setMatrix(initialMatrix); | |
| 165 SkRect src = SkRect::Make(temp->fSrcRect); | |
| 166 SkRect dst = SkRect::MakeXYWH(temp->fPos.fX, temp->fPos.fY, | |
| 167 temp->fSrcRect.width(), | |
| 168 temp->fSrcRect.height()); | |
| 169 canvas->drawBitmapRectToRect(*temp->fBM, &src, dst, temp->fPaint); | |
| 170 canvas->restore(); | |
| 171 | |
| 172 if (iter->isValid()) { | |
| 173 // This save is needed since the BBH will automatically issue | |
| 174 // a restore to balanced the saveLayer we're skipping | |
| 175 canvas->save(); | |
| 176 | |
| 177 // At this point we know that the PictureStateTree was aiming | |
| 178 // for some draw op within temp's saveLayer (although potentiall y | |
| 179 // in a separate saveLayer nested inside it). | |
| 180 // We need to skip all the operations inside temp's range | |
| 181 // along with all the associated state changes but update | |
| 182 // the state tree to the first operation outside temp's range. | |
| 183 | |
| 184 uint32_t skipTo; | |
| 185 do { | |
| 186 skipTo = iter->nextDraw(); | |
| 187 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) { | |
| 188 break; | |
| 189 } | |
| 190 | |
| 191 if (skipTo <= temp->fStop) { | |
| 192 reader->setOffset(skipTo); | |
| 193 uint32_t size; | |
| 194 DrawType op = ReadOpAndSize(reader, &size); | |
| 195 // Since we are relying on the normal SkPictureStateTree | |
| 196 // playback we need to convert any nested saveLayer call s | |
| 197 // it may issue into saves (so that all its internal | |
| 198 // restores will be balanced). | |
| 199 if (SAVE_LAYER == op) { | |
| 200 canvas->save(); | |
| 201 } | |
| 202 } | |
| 203 } while (skipTo <= temp->fStop); | |
| 204 | |
| 205 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) { | |
| 206 reader->setOffset(reader->size()); // skip to end | |
| 207 return true; | |
| 131 } | 208 } |
| 132 | 209 |
| 133 activeOps = &(activeOpsList.get()->fOps); | 210 reader->setOffset(skipTo); |
| 211 } else { | |
| 212 reader->setOffset(temp->fStop); | |
| 213 uint32_t size; | |
| 214 SkDEBUGCODE(DrawType op = ) ReadOpAndSize(reader, &size); | |
| 215 SkASSERT(RESTORE == op); | |
| 134 } | 216 } |
| 217 | |
| 218 return true; | |
| 135 } | 219 } |
| 136 } | 220 } |
| 137 | 221 |
| 138 SkPictureStateTree::Iterator it = (NULL == activeOps) ? | 222 return false; |
| 139 SkPictureStateTree::Iterator() : | 223 } |
| 140 fPictureData->fStateTree->getIterator(*activeOps, canvas); | |
| 141 | 224 |
| 142 if (it.isValid()) { | 225 // Update the iterator and state tree to catch up with the skipped ops. |
| 143 uint32_t skipTo = it.nextDraw(); | 226 void SkPicturePlayback::SkipIterTo(SkPictureStateTree::Iterator* iter, |
| 144 if (kDrawComplete == skipTo) { | 227 SkReader32* reader, |
| 145 return; | 228 uint32_t skipTo) { |
| 146 } | 229 if (iter->isValid()) { |
| 147 reader.setOffset(skipTo); | 230 // If using a bounding box hierarchy, advance the state tree |
| 231 // iterator until at or after skipTo | |
| 232 uint32_t adjustedSkipTo; | |
| 233 do { | |
| 234 adjustedSkipTo = iter->nextDraw(); | |
| 235 } while (adjustedSkipTo < skipTo); | |
| 236 skipTo = adjustedSkipTo; | |
| 148 } | 237 } |
| 238 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) { | |
|
mtklein
2014/07/09 17:55:01
Is there any chance we could have passed this whil
robertphillips
2014/07/09 18:12:39
skipTo will never be kDrawComplete on entry (I'll
| |
| 239 reader->setOffset(reader->size()); // skip to end | |
| 240 } else { | |
| 241 reader->setOffset(skipTo); | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) { | |
| 246 AutoResetOpID aroi(this); | |
| 247 SkASSERT(0 == fCurOffset); | |
| 248 | |
| 249 SkAutoTDelete<const SkPicture::OperationList> activeOpsList(this->getActiveO ps(canvas)); | |
| 250 SkPictureStateTree::Iterator it; | |
| 251 | |
| 252 if (!this->initIterator(&it, canvas, activeOpsList.get())) { | |
| 253 return; // nothing to draw | |
| 254 } | |
| 255 | |
| 256 SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->s ize()); | |
| 257 | |
| 258 StepIterator(&it, &reader); | |
| 149 | 259 |
| 150 // Record this, so we can concat w/ it if we encounter a setMatrix() | 260 // Record this, so we can concat w/ it if we encounter a setMatrix() |
| 151 SkMatrix initialMatrix = canvas->getTotalMatrix(); | 261 SkMatrix initialMatrix = canvas->getTotalMatrix(); |
| 152 | 262 |
| 153 SkAutoCanvasRestore acr(canvas, false); | 263 SkAutoCanvasRestore acr(canvas, false); |
| 154 | 264 |
| 155 while (!reader.eof()) { | 265 while (!reader.eof()) { |
| 156 if (callback && callback->abortDrawing()) { | 266 if (NULL != callback && callback->abortDrawing()) { |
| 157 return; | 267 return; |
| 158 } | 268 } |
| 159 | 269 |
| 160 if (NULL != fReplacements) { | 270 if (this->replaceOps(&it, &reader, canvas, initialMatrix)) { |
| 161 // Potentially replace a block of operations with a single drawBitma p call | 271 continue; |
| 162 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp = | |
| 163 fReplacements->lookupByStart(reader.offset()); | |
| 164 if (NULL != temp) { | |
| 165 SkASSERT(NULL != temp->fBM); | |
| 166 SkASSERT(NULL != temp->fPaint); | |
| 167 canvas->save(); | |
| 168 canvas->setMatrix(initialMatrix); | |
| 169 SkRect src = SkRect::Make(temp->fSrcRect); | |
| 170 SkRect dst = SkRect::MakeXYWH(temp->fPos.fX, temp->fPos.fY, | |
| 171 temp->fSrcRect.width(), | |
| 172 temp->fSrcRect.height()); | |
| 173 canvas->drawBitmapRectToRect(*temp->fBM, &src, dst, temp->fPaint ); | |
| 174 canvas->restore(); | |
| 175 | |
| 176 if (it.isValid()) { | |
| 177 // This save is needed since the BBH will automatically issu e | |
| 178 // a restore to balanced the saveLayer we're skipping | |
| 179 canvas->save(); | |
| 180 | |
| 181 // At this point we know that the PictureStateTree was aimin g | |
| 182 // for some draw op within temp's saveLayer (although potent ially | |
| 183 // in a separate saveLayer nested inside it). | |
| 184 // We need to skip all the operations inside temp's range | |
| 185 // along with all the associated state changes but update | |
| 186 // the state tree to the first operation outside temp's rang e. | |
| 187 | |
| 188 uint32_t skipTo; | |
| 189 do { | |
| 190 skipTo = it.nextDraw(); | |
| 191 if (kDrawComplete == skipTo) { | |
| 192 break; | |
| 193 } | |
| 194 | |
| 195 if (skipTo <= temp->fStop) { | |
| 196 reader.setOffset(skipTo); | |
| 197 uint32_t size; | |
| 198 DrawType op = ReadOpAndSize(&reader, &size); | |
| 199 // Since we are relying on the normal SkPictureState Tree | |
| 200 // playback we need to convert any nested saveLayer calls | |
| 201 // it may issue into saves (so that all its internal | |
| 202 // restores will be balanced). | |
| 203 if (SAVE_LAYER == op) { | |
| 204 canvas->save(); | |
| 205 } | |
| 206 } | |
| 207 } while (skipTo <= temp->fStop); | |
| 208 | |
| 209 if (kDrawComplete == skipTo) { | |
| 210 break; | |
| 211 } | |
| 212 | |
| 213 reader.setOffset(skipTo); | |
| 214 } else { | |
| 215 reader.setOffset(temp->fStop); | |
| 216 uint32_t size; | |
| 217 SkDEBUGCODE(DrawType op = ) ReadOpAndSize(&reader, &size); | |
| 218 SkASSERT(RESTORE == op); | |
| 219 } | |
| 220 continue; | |
| 221 } | |
| 222 } | 272 } |
| 223 | 273 |
| 224 fCurOffset = reader.offset(); | 274 fCurOffset = reader.offset(); |
| 225 uint32_t size; | 275 uint32_t size; |
| 226 DrawType op = ReadOpAndSize(&reader, &size); | 276 DrawType op = ReadOpAndSize(&reader, &size); |
| 227 size_t skipTo = 0; | |
| 228 if (NOOP == op) { | 277 if (NOOP == op) { |
| 229 // NOOPs are to be ignored - do not propagate them any further | 278 // NOOPs are to be ignored - do not propagate them any further |
| 230 skipTo = fCurOffset + size; | 279 SkipIterTo(&it, &reader, fCurOffset + size); |
| 231 } | |
| 232 | |
| 233 if (0 != skipTo) { | |
| 234 if (it.isValid()) { | |
| 235 // If using a bounding box hierarchy, advance the state tree | |
| 236 // iterator until at or after skipTo | |
| 237 uint32_t adjustedSkipTo; | |
| 238 do { | |
| 239 adjustedSkipTo = it.nextDraw(); | |
| 240 } while (adjustedSkipTo < skipTo); | |
| 241 skipTo = adjustedSkipTo; | |
| 242 } | |
| 243 if (kDrawComplete == skipTo) { | |
| 244 break; | |
| 245 } | |
| 246 reader.setOffset(skipTo); | |
| 247 continue; | 280 continue; |
| 248 } | 281 } |
| 249 | 282 |
| 250 this->handleOp(&reader, op, size, canvas, initialMatrix); | 283 this->handleOp(&reader, op, size, canvas, initialMatrix); |
| 251 | 284 |
| 252 if (it.isValid()) { | 285 StepIterator(&it, &reader); |
| 253 uint32_t skipTo = it.nextDraw(); | |
| 254 if (kDrawComplete == skipTo) { | |
| 255 break; | |
| 256 } | |
| 257 reader.setOffset(skipTo); | |
| 258 } | |
| 259 } | 286 } |
| 260 } | 287 } |
| 261 | 288 |
| 262 void SkPicturePlayback::handleOp(SkReader32* reader, | 289 void SkPicturePlayback::handleOp(SkReader32* reader, |
| 263 DrawType op, | 290 DrawType op, |
| 264 uint32_t size, | 291 uint32_t size, |
| 265 SkCanvas* canvas, | 292 SkCanvas* canvas, |
| 266 const SkMatrix& initialMatrix) { | 293 const SkMatrix& initialMatrix) { |
| 267 switch (op) { | 294 switch (op) { |
| 268 case CLIP_PATH: { | 295 case CLIP_PATH: { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 case TRANSLATE: { | 593 case TRANSLATE: { |
| 567 SkScalar dx = reader->readScalar(); | 594 SkScalar dx = reader->readScalar(); |
| 568 SkScalar dy = reader->readScalar(); | 595 SkScalar dy = reader->readScalar(); |
| 569 canvas->translate(dx, dy); | 596 canvas->translate(dx, dy); |
| 570 } break; | 597 } break; |
| 571 default: | 598 default: |
| 572 SkASSERT(0); | 599 SkASSERT(0); |
| 573 } | 600 } |
| 574 } | 601 } |
| 575 | 602 |
| OLD | NEW |