2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrRecordReplaceDraw.h"
10 #include "SkRecordDraw.h"
12 GrReplacements::ReplacementInfo* GrReplacements::push() {
13 SkDEBUGCODE(this->validate());
14 return fReplacements.push();
17 void GrReplacements::freeAll() {
18 for (int i = 0; i < fReplacements.count(); ++i) {
19 fReplacements[i].fImage->unref();
20 SkDELETE(fReplacements[i].fPaint);
22 fReplacements.reset();
26 void GrReplacements::validate() const {
27 // Check that the ranges are monotonically increasing and non-overlapping
28 if (fReplacements.count() > 0) {
29 SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop);
31 for (int i = 1; i < fReplacements.count(); ++i) {
32 SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop);
33 SkASSERT(fReplacements[i - 1].fStop < fReplacements[i].fStart);
39 const GrReplacements::ReplacementInfo*
40 GrReplacements::lookupByStart(size_t start, int* searchStart) const {
41 SkDEBUGCODE(this->validate());
42 for (int i = *searchStart; i < fReplacements.count(); ++i) {
43 if (start == fReplacements[i].fStart) {
45 return &fReplacements[i];
46 } else if (start < fReplacements[i].fStart) {
47 return NULL; // the ranges are monotonically increasing and non-overlapping
54 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
56 const SkMatrix& initialMatrix) {
57 SkRect src = SkRect::Make(ri->fSrcRect);
58 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX),
59 SkIntToScalar(ri->fPos.fY),
60 SkIntToScalar(ri->fSrcRect.width()),
61 SkIntToScalar(ri->fSrcRect.height()));
64 canvas->setMatrix(initialMatrix);
65 canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
69 void GrRecordReplaceDraw(const SkRecord& record,
71 const SkBBoxHierarchy* bbh,
72 const GrReplacements* replacements,
73 SkDrawPictureCallback* callback) {
74 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
76 SkRecords::Draw draw(canvas);
77 const GrReplacements::ReplacementInfo* ri = NULL;
80 const SkMatrix initialMatrix = canvas->getTotalMatrix();
83 // Draw only ops that affect pixels in the canvas's current clip.
84 // The SkRecord and BBH were recorded in identity space. This canvas
85 // is not necessarily in that same space. getClipBounds() returns us
86 // this canvas' clip bounds transformed back into identity space, which
87 // lets us query the BBH.
88 SkRect query = { 0, 0, 0, 0 };
89 (void)canvas->getClipBounds(&query);
92 bbh->search(query, &ops);
94 for (int i = 0; i < ops.count(); i++) {
95 if (callback && callback->abortDrawing()) {
98 ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart);
100 draw_replacement_bitmap(ri, canvas, initialMatrix);
102 while ((uintptr_t)ops[i] < ri->fStop) {
105 SkASSERT((uintptr_t)ops[i] == ri->fStop);
109 record.visit<void>((uintptr_t)ops[i], draw);
112 for (unsigned int i = 0; i < record.count(); ++i) {
113 if (callback && callback->abortDrawing()) {
116 ri = replacements->lookupByStart(i, &searchStart);
118 draw_replacement_bitmap(ri, canvas, initialMatrix);
123 record.visit<void>(i, draw);